从服务框架开始
服务拆分在项目中是有帮助的,但是有帮助的「度」也存在,因为还有诸如「不同系统中存在代码冗余」等问题。等好的方式应该是服务化,就是将系统分层。
服务化就是之前提到的概念,存在多层,比如:顶层 Web 系统,中间服务中心,底层数据库。
1. 远程调用
服务化带来了各种各样的问题,内部系统依赖变得错综复杂,我们需要解决它所带来的问题。
没有服务化之前,我们通过「本地调用」的方式使用其他组件,服务化以后我们需要使用的是「远程调用」,这里我们需要关注提高易用性与降低性能损失两个问题。
因此一个通用的服务框架,要先完成 RPC 功能,为服务使用者提供相应的客户端。多机之间,我们需要对请求进行编码,传到远程节点,解码后进行真正的调用。
- 寻址路由:「调用方」确定哪个实例被调用。
- 实例地位:「被调用方」找到对应的实例进行调用。
2. 服务框架原型
上面的图只是一个从一端到另外一端的请求,服务框架是一个既包含调用端逻辑又包含服务端逻辑的一个是实现。
在远程调用中,一般有如下的「请求流程」:
- 获取可用服务地址列表;
- 确定调用的目标机器; // 这两步完成「寻址路由」,方式很多,规则服务器、名称服务等等。
- 建立连接;
- 请求序列化;
- 发送请求;
- 接收结果;
- 解析结果。
而对于「服务端」而言,也要加入请求的处理:接收比特流,「实例定位」,返回结果。
3. 消费者设计
假设用 Spring 作为一个服务的框架,在 Bean 的定义中,需要指定这些 Bean 属性:「interfaceName」、「version」、「group」。
在本地通过「动态代理」的方式实现方法的调用。
- 首先需要「interfaceName」确认被调用接口是哪一个,显然使用的是全限定名;
- 接着「version」主要用以升级的场景,让版本存在隔离;
- 最后「group」,假设同一个服务有很多机器,我们可以把这些服务的机器归组,选择不同的组来调用。
「服务框架」可以作为:Web 应用的扩展(jar 包)、Web 容器的一部分(Web 应用)、本身作为容器。这些都可行,在开发中应该根据不同的场景来进行选择。
3.1 通信问题
我们的假想中调用的服务是一台的,但实际中一定是多台的集群:
处理方式多种,可以采用「透明代理」或者「直连」的方式,主流采用「直连」的方式:
引入一个「注册中心」来支持查找,让客户端拿到服务提供者列表,然后就是「路由」的问题了。
3.2 路由问题
「基于接口、方法、参数的路由」也是我们要解决的问题。下面两个调用者可能都调用同一个服务:
假设现在接口 A 的方法 1 是比较慢的方法,可能会陷入不断的等待:
我们会发现执行过程中很容易陷入 IA.m1 方法的等待队列,简单处理可以「增加资源保证系统能力」,另一种一种可行的方式「隔离资源」。
现在只有接口 A 的方法 2 会收到接口 A 方法 1 的影响了,那么我们可以对路由更加细致一点,可以基于「具体方法进行路由」,而不是「基于接口进行路由」,沿着这个思路,还有「基于参数进行路由」的选择。
3.3 多机房场景
如果在「服务注册中心」和「调用者」、「提供者」之间加上「机房」的概念。我们可以在「路由」中下文章:
给不同机房的调用者相同的服务提供者列表,然后根据「虚拟机房」等策略完成路由,一般是基于接口的路由(服务框架进行集中配置管理)。
另外流控是为了保证系统的稳定性,序列化是为了传输对象,网络一般采用 NIO ,这些都是老生常谈了。
3.4 多种异步调用
- Oneway
- 只管发送不关心结果的方式。只需要把发送的数据放入数据队列,然后继续处理后续任务;而 IO 线程也只需要从数据队列中读到数据,然后通过 Socket 连接发送出去即可。它是不保证可靠传达的通知。
- Callback
- 请求发送方发送请求后会继续执行自己的操作,等对方有响应时进行一个回调。
- Future
- 先把 Future 放入队列,然后把数据放入队列,接着就在线程中进行处理,等到请求线程在其他工作处理结束后,就通过 Future 来获取通信结果并直接控制超时。
- 可靠异步
- 一般通过消息中间件完成。
4. 提供者设计
在服务端我们也要像调用端一样设置特殊字段,以此暴露出远程服务的具体接口。
具体的请求流程从「网络通信层」一直延续到调用「具体服务」:
4.2 不同服务的线程隔离
值得注意的是,服务端线程池不是一个,定位服务以后,根据名称、方法、参数等信息来决定具体执行服务调用的线程池是哪一个,不会出现争抢线程资源的情况:
4.3 分布式环境合并请求
我们知道,合并请求的线程流程如下:
但是在分布式环境中,会有新的问题,需要使用「分布式锁」或者「路由」:
具体场景需要具体分析。
5. 总结
服务框架为我们从集中式系统转向分布式系统提供了基础支持:
完成服务框架,还需要针对自身环境完成工作,以助于开发中定位和发现问题。