简单RPC系统设计

RPC是什么?

  • RPC即远程过程调用,即调用远程计算机上的服务,就像调用本地服务一样方便。RPC可以基于HTTP或者TCP协议,Web Service就是基于HTTP协议的RPC。为了支持高并发,java提供的BIO阻塞式io不合适,因此需要异步IO,即NIO,比较流行的NIO框架有Netty以及apache的Mina。

简单的RPC系统设计框架

  • 曾经在的公司使用的rpc系统是自己编写的,并没有使用阿里巴巴开源的dubbo,原理比较简单,使用netty作为服务器和客户端,使用zookeeper作为服务器注册中心,将服务全路径和服务地址注册到zookeeper中的永久节点中,然后客户端从zk永久节点中查询服务端的ip,随机返回ip地址,连接对应的ip,对应地址服务器使用反射调用本地方法,最后将结果返回去,完成了rpc调用过程,编码格式使用了protobuf来实现,提高了传输效率。简单流程图如下:

垃圾回收算法

垃圾回收算法

1.标记-清除算法:最基础的算法是“标记-清除算法”,分为:

  • 标记
  • 清除

两个阶段。
——————————————————————————————————————————————————————

该算法的缺点是:

  • 效率问题,标题和清除的效率都不高;
  • 空间问题:标记清除后会有大量的不连续的内存碎片,碎片太多会导致分配较大空间的对象时候,无法找到足够的内存而不得不提前出发另一次垃圾收集动作。

2.复制算法

  • 它将内存划分为大小相等的两块,每次使用其中一块,当内存块用完了,将或者的对象复制到另一块上,然后将已经使用的空间给清除掉。算法的代价是内存缩小了一半。

3.标记-整理算法

  • 标记整理算法类似标记清除算法,但是不是对可回收对象直接清理,而是让所有存活对象向一端移动,然后直接清理掉端以外的内存。
    *4.分代收集算法
  • 算法根据各个年代特点使用适合的算法,内存堆分为新生的老年代。

jdk中的引用

java引用

jdk中将引用分为四种

  • 强引用(Strong Reference):是程序中普遍存在的,类似Object obj = new Object(),只要强引用存在,那么垃圾收集器就不会回收掉被引用的对象。
  • 软引用(Soft Reference):软引用对象在系统内存溢出前,将这些对象进行范围之中的二次回收,如果回收后还没有足够内存,就会抛出内存溢出异常。
  • 弱引用(Weak Reference):弱引用只能生存到下一次垃圾收集发生前无论内存是否足够都会被回收掉。
  • 虚引用(PhantomReference):称为幽灵引用或者幻影引用,最弱的一种引用关系。对象存在虚引用对其生存时间不构成影响,也无法通过虚引用获取一个对象实例。唯一目的就是在这个对象呗收集器回收的时候收到系统通知。

java内存区域

运行时候的区域

  • Java虚拟机在执行程序的时候将它所管理内存区域划分为若干数据区域,这些区域各有用途,创建时间和销毁时间等都不同。

程序计数器

  • 程序计数器是一块较小内存的空间,可以看做当前线程所执行的字节码行号指示器。java虚拟机的多线程是通过线程轮流切换并分配处理执行时间的方式来实现的,任何时刻,一个处理器都会执行一个线程的指令。因此为了切换后能够恢复到正确的执行位置,每个线程独有一个程序计数器,线程独立存储,互不影响,被称作“线程私有”内存。

  • 线程执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果执行时native方法,计数器为空。此区域是唯一一个没有OutOfMemeoryError情况的区域。

java虚拟机栈

  • java虚拟机栈也是线程私有的,和线程生命周期相同。
  • 描述的是java方法执行的内存模型:每个方法执行的时候都会创建一个栈帧用来存储局部变量表、操作数栈、动态链接、方法出口信息,每个方法从调用到直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈道出栈的过程。
  • 如果请求的栈的深度超过了虚拟机最大的深度,会抛出StackOverFlowError异常
  • 如果扩展时候无法申请到足够的内存,就会抛出OutOfMemoryError异常。

    本地方法栈

  • 虚拟栈为虚拟机执行java方法服务,本地方法栈 则为虚拟机使用到的native方法服务。
  • 本地方法栈也会抛出StackOverFlowError和OutOfMemoryError异常。

Java堆

  • java堆是虚拟机管理的内存最大的一块,是所有的线程共享的区域,此内存唯一目的就是存放对象实例。
  • java堆是垃圾收集器管理的主要区域,因此被称为GC堆,由于收集器都采用分代收集算法,所以堆可以分为:新生代、老年代。

方法区

  • 方法区和java堆一样是各个线程共享区域,用户存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
  • 更多的人把方法区成为”永久代”,但是两者并不等价,仅仅是因为Hotspot虚拟机设计团队选择吧GC分代扩展至方法区,或者使用永久代来实现方法区而已。