对于Java开发人员来说,了解Java内存模型是必不可少的知识。

JVM内存模型

在生产环境上一般会配置JVM参数以充分利用硬件资源,不管是在云主机或容器里面,也就是在启动应用时添加下面的某些配置:

  • -XmsSetting —初始堆大小
  • -XmxSetting —最大堆大小
  • -XX:NewSizeSetting —新一代堆大小
  • -XX:MaxNewSizeSetting —最大新一代堆大小
  • -XX:MaxPermGenSetting —永久生成的最大大小
  • -XX:SurvivorRatioSetting —新的堆大小比率(例如,如果Young Gen大小为10m并且内存开关为–XX:SurvivorRatio=2,则将为Eden空间保留5m,为两个Survivor空间分别保留2.5m,默认值= 8)
  • -XX:NewRatio —提供新旧大小的比率(默认值= 2)

就像任何其他软件一样,JVM占用主机OS内存上的可用空间。

在JVM内部存在单独的内存空间(堆、非堆和缓存),用来存储运行时数据和编译后的代码。

阅读全文 »

JVM架构

JVM只是一个规范,在市面上有不同的公司进行了实现,这包含收费的以及免费的。下面这张图是JVM的整体架构图,涵盖了java代码执行的全过程,下面分别就这些过程进行说明。

类加载器子系统

如果与php相比较,当php文件执行完后Zend引擎被立即销毁,可java却不同,JVM会长驻在内存并一直工作。它在执行期间使用Class Loader子系统将类文件带到RAM,这被称为Java动态类加载。在它首次运行时(而非编译时)将加载、链接和初始化类文件(.class)。

加载

将编译的类(.class文件)加载到内存中是Class Loader的主要任务。通常类加载过程从加载主类(即带有 static main() 方法声明的类)开始的,所有后续的类加载都是根据已运行类中的类引用完成的,如以下情况所述:

  • 当字节码静态引用一个类时(例如 System.out
  • 当字节码创建一个类对象时(例如 Person person = new Person("John")

在JVM中有三个类加载器(与继承属性相关),它们工作时遵循4个主要原则。

阅读全文 »

介绍

什么是分布式应用?

简单点说就是一个完整的应用被拆分成了多个应用,每个拆出来的应用都可以单独部署,每个应用负责原来那个完整应用的一部分功能,只有当这些应用全部提供服务时才是完整的。这其实很好理解,举个例子,比如某商城系统被划分成了营销子系统、订单子系统和会员子系统,在这里面每个子系统有其固有职责,对于整个商城系统来说是不可缺少的一部分,通常这种划分也被称为垂直拆分

什么是微服务应用?

其实所谓微服务应用算是分布式应用的一种特殊形式,它们之间区别不大,相同点很多。唯一比较明显的区分是前者对系统拆分的更加,更加注重拆分后的子系统(也称为服务)功能复用,职责非常单一,小团队可维护。另外一点是注重DevOps的工作流,让服务的开发、迭代、测试和部署更加自动化,极大提高项目交付效率。

即使是在同一个系统里面,因为依据不同的拆分原则,最终得到的微服务可能不一致,这和站的角度、业务特点以及架构思路有关。实际工作中有些人把握不好原则,容易把服务拆分的过细导致维护非常麻烦,也有拆分的过大而不能复用已有的模块。虽然业界也没有完全统一的结论,不过也有一些原则被总结出来,有兴趣的小伙伴可以在网络上看看相关的文章。

阅读全文 »

源起

为什么需要分布式锁?

要回答这个问题先要搞清楚为什么需要锁?可以试想一下当多个线程同时访问临界资源引起竞争后肯定会导致错误或其它意外行为,这时通过锁这种机制可以避免出现这样的问题,因为锁的存在让多个线程有序的访问临界资源。如果在同一个JVM环境下,本地锁可以满足使用目的,但如果是跨JVM呢?

锁只存在于某一个地方肯定不行,锁本身也需要共享出去,其它JVM才能知道系统整体的锁定情况,否则锁定将失效,因为有的可以锁定了,但有的却没有。这也是为什么需要分布式锁的原因,对于跨JVM、跨物理机器的系统需要能够共享的分布式锁。

使用分布式锁的场景有哪些?

在实际项目中需要被锁定的资源有很多,不单单只是某个变量而已,往大了看在分布式(微服务)体系下任何资源都可能有被锁定的需求,因为你肯定不想同样的事情被重复处理,特别是这些处理是昂贵的。到底有哪些业务呢?还是举一些常见的例子:

  1. 在电商平台中对于订单的处理由多个内部服务,多个节点处理,而订单的处理状态是有严格方向的,每当处理完当前业务,就应该(也只能)进入下一个状态,出不能被重复处理,并且更重要的是同一时刻应该只能有一个系统在进行处理,它是有这样一个严格的顺序执行场景的。你要在内部那么多系统和N多节点中保证前面提到的这个要求,那肯定需要引入分布式锁的支持,当前正在处理的系统或节点在处理某个订单前,要先获取它的分布式锁,自己处理完再释放锁。后续系统在处理时也应该是同样的操作,也就是保证它的顺序执行。
  2. 某个后台任务需要对一张表的数据进行处理,为了提高处理效率而启用多线程或多进程(多次启动程序)执行方案,但由于是同张表也就会发现同时处理相同数据的情况,而每条数据的处理是昂贵的,那如何避免这个问题呢?其中一种方案是引入分布式锁的支持来解决,我们可以让程序随机获取表中的数据,这样大大减少获取同条数据的概念,但不可能完全避免,再加上在处理每条数据时要先获取对应的分布式锁,如果获取不到则随机到下一条数据,这样就可以实现前面的要求。

实际需要应用分布式锁的场景还有很多,这样就不再列举了。要判断是否需要分布式锁的一条原则:是否出现跨系统访问临界资源的情况,基本上达到这个要求就需要。

阅读全文 »

所谓“免密码”登入远程linux系统,其实并不是真的不需要“密码”,而是不再使用明文密码。我们通过利用RSA加密算法构建一个安全的SSH通道,实际使用时通过证书来双向验证彼此的身份,证书本身可以选择是否加密,如果是那最终还是要有输入密码的过程。

阅读全文 »