反应式宣言
在不同领域中深耕的组织都在不约而同地尝试发现相似的软件构建模式。 希望这些系统会更健壮、更具回弹性 、更灵活,也能更好地满足现代化的需求。
近年来,应用程序的需求已经发生了戏剧性的更改,模式变化也随之而来。仅在几年前, 一个大型应用程序通常拥有数十台服务器、 秒级的响应时间、 数小时的维护时间以及GB级的数据。 而今,应用程序被部署到了形态各异的载体上, 从移动设备到运行着数以千计的多核心处理器的云端集群。 用户期望着毫秒级的响应时间,以及服务100%正常运行(随时可用)。 而数据则以PB计量。 昨日的软件架构已经根本无法满足今天的需求。
我们相信大家需要一套贯通整个系统的架构设计方案, 而设计中必需要关注的各个角度也已被理清: 我们需要系统具备以下特质:即时响应性(Responsive)、回弹性(Resilient)、弹性(Elastic)以及消息驱动(Message Driven)。 对于这样的系统,我们称之为反应式系统(Reactive System)。
使用反应式方式构建的反应式系统会更加灵活、松耦合、可伸缩。 这使得它们的开发和调整更加容易。 它们对系统的失败 也更加的包容, 而当失败确实发生时, 它们的应对方案会是得体处理而非混乱无序。 反应式系统具有高度的即时响应性, 为用户提供了高效的互动反馈。
Dubbo源码分析:Cluster
在介绍 Cluster
之前再来回顾一下集群容错的架构图:

看下官网对 Cluster
的介绍:
Cluster
将Directory
中的多个Invoker
伪装成一个Invoker
,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个
什么意思呢,简单来说就是上层在调用的时候不需要关心具体有多少个 Invoker
,只需要使用 Cluster
包装过的一个 Invoker
即可,同时包装过的 Invoker
包含了容错处理。
下面看下 Cluster
的类图:

可以看到,具体有9个实现类,分别对应不同的容错处理策略。
Dubbo源码分析:LoadBalance
前两篇文章分析了 Directory
和 Router
,本文继续分析第三个部分 LoadBalance
的实现。
回顾一下 AbstractClusterInvoker
中的 invoke
方法:
|
|
Dubbo源码分析:Router
介绍
上篇文章介绍了 Directory
,再次看一下dubbo调用的处理流程:

本篇文章介绍调用的第二步, Router
的实现。
从图中可以看到, Router
的实现有两种: Script
和 Condition
,官网对其的描述为:
Router
负责从多个Invoker
中按路由规则选出子集,比如读写分离,应用隔离等
也就是说,第一步通过 Directory
选出当前可用的服务提供者,然后再通过 Router
按规则过滤出服务提供者的子集。
Dubbo源码分析:Directory
介绍
在集群容错时,dubbo处理的流程如下图所示:

下面是来自官网的介绍,各节点关系如下:
- 这里的
Invoker
是Provider
的一个可调用Service
的抽象,Invoker
封装了Provider
地址及Service
接口信息 Directory
代表多个Invoker
,可以把它看成List<Invoker>
,但与List
不同的是,它的值可能是动态变化的,比如注册中心推送变更Cluster
将Directory
中的多个Invoker
伪装成一个Invoker
,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个Router
负责从多个Invoker
中按路由规则选出子集,比如读写分离,应用隔离等LoadBalance
负责从多个Invoker
中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选
本篇将介绍这里的 Directory
。
TCP的连接队列与backlog参数
在Netty中经常会看到这样的代码:
|
|
这里有一个SO_BACKLOG
参数,本篇文章解释一下这个参数的具体用途。
Java线程上下文加载器与SPI
SPI机制
SPI的全名为Service Provider Interface.大多数开发人员可能不熟悉,因为这个是针对厂商或者插件的。在java.util.ServiceLoader
的文档里有比较详细的介绍。简单的总结下java spi机制的思想。我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 java spi就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。
AIO写文件的OutOfMemoryError
问题重现
AIO进行写文件使用了AsynchronousFileChannel类来实现,测试代码如下:
|
|
Netty4源码分析-Channel
Channel的功能
基本的 I/O 操作(bind()、connect()、read()和 write())依赖于底层网络传输所提 供的原语。在基于 Java 的网络编程中,其基本的构造是 class Socket。Netty 的 Channel 接 口所提供的 API,大大地降低了直接使用 Socket 类的复杂性。此外,Channel 也是拥有许多 预定义的、专门化实现的广泛类层次结构的根,下面是一些Channel的类型:
- EmbeddedChannel
- LocalServerChannel
- NioDatagramChannel
- NioSctpChannel
- NioSocketChannel
io.netty.channel.Channel 是 Netty 网络操作抽象类,它聚合了一组功能,包括但不限于网络的读、写,客户端发起连接、主动关闭连接,链路关闭,获取通信双方的网络地址等。
它也包含了Netty框架相关的一些功能,包括获取该 Chanel的EventLoop,获取缓冲分配
器 ByteBufAllocator 和 pipeline 等。