微服务框架学习一:架构介绍
需求说明书
目的
构建一个稳定,高效,容错,易维护,可监控的服务调用框架,以便推动公司业务系统朝着SOA架构演进,从而使整体业务架构更加清晰,可控和可度量,最终实现业务产品的健康,敏捷发展。
项目背景
目前汇付各业务系统各自独立,存在重复业务逻辑,通过数据库共享数据等问题。项目粗放式生长,缺乏清晰的脉络和独立的职责。
很多相同数据在不同的系统中存在冗余,给变更和维护带来很大的难度,也没有系统负责维护这些数据,基本靠人工重复维护的方式。
系统职责的不独立,必然带来人员职责的划分不清,导致生产率的低下和产品演进速度的缓慢。
可行性分析
构建这样一套框架需要从底层通信,编码/解码,序列化,异步处理,线程池等几个大的方面入手,具体可行性分析如下:
底层通信:依赖于第三方包netty
编码/解码:自定义二进制编码协议
序列化:依赖于第三方协议,如hessian, protobuf, thrift,以实际情况权衡使用
异步处理:基于Future Pattern实现
线程池:使用JDK concurrent包自带的线程池,若有效率问题,后期再做优化
功能需求
稳定:不会因为系统请求并发量的陡增而出现性能大幅度下降的情况,并且持续可用
高效:性能及吞吐量应比开源的rpc框架高,如hessian, xfire等
容错:应具备底层网络通信容错及部分只读业务容错的能力
负载均衡:通过客户端负载均衡的方式,摒弃额外的软/硬负载设备,具备更好的性能和可靠性
简单监控:V1.0.0版本中仅实现简单的监控统计功能(log/jmx/telnet方式)
配置服务提供者:V1.0.0版本中仅支持客户端手工配置服务提供者地址和权重的方式,后续版本改由注册中心提供
项目计划
1. 项目信息
项目编号 | 251 |
---|---|
项目名称 | Pegasus |
项目经理 | 刘健 |
项目简述 |
Pegasus为分布式服务框架,推进公司业务架构朝着SOA方向发展 |
2. 目的与范围
3. 参考文献
名称 | 版本 | 链接 |
---|---|---|
4. 项目计划
4.1 历史项目参考
无
4.2 项目估算
FP | 624.00 |
---|---|
生产率基线 | 3.01 |
工作量估算 | 207.3089701 |
# | 模块 | 子模块 | 功能 | EI | EO | EQ | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
S | M | C | S | M | C | S | M | C | ||||
1 | 通信客户端 | service stub | 2 | 2 | ||||||||
2 | invoke filter chain | 5 | 5 | |||||||||
3 | client route | 4 | 4 | |||||||||
4 | client load balance | 4 | 4 | |||||||||
5 | heart beat task | 3 | 3 | |||||||||
6 | reconnect task | 2 | 2 | |||||||||
7 | communicate protocol | 5 | 5 | |||||||||
8 | 通信服务端 | service registry | 4 | 4 | ||||||||
9 | communicate protocol | 5 | 5 | |||||||||
10 | service processor | 2 | 2 | |||||||||
11 | process filter chain | 4 | 4 | |||||||||
12 | 客户端服务端集成 | 3 | 3 | |||||||||
13 | http通信支持 | design & coding | 5 | 5 |
影响因子列表 | 级别(0-5) | 原因 |
---|---|---|
数据通信 | 5 | |
分布式数据处理 | 5 | |
性能 | 5 | |
大业务量配置 | 5 | |
复杂处理 | 5 | |
可复用性 | 5 | |
支持变更 | 5 | |
级别总数 | 35 |
4.3 项目资源
4.3.1 人力资源
角色 | 人数 | 姓名 | 备注 |
---|---|---|---|
项目经理 | 1 | 刘健 | |
架构工程师 | 1 | 刘健 | 初期1人,后续加入其他开发工程师 |
开发工程师 | 3 | 刘健,刘成业,待定 | |
测试工程师 | 2 | 待定 | 需要与测试部门协调 |
4.3.2 基础设施
硬件环境 | 线下3台虚拟机用于测试 |
---|---|
软件环境 | linux系统(centos), 局域网千兆网络 |
4.3.3 工具和技术
用途 | 工具名称 | 版本 | 生产厂商 |
---|---|---|---|
开发 | Eclipse/IDEA | 任意 | / |
测试 | EasyMock | 任意 | / |
设计 | Microsoft Visio | 2007 | Microsoft |
压测 | JMeter | 任意 | Apache |
构建 | Maven | 2 | Apache |
持续集成 | Jenkins | 任意 | / |
4.4 项目排期及流程
4.4.1 项目排期
任务 | 负责人员 | 参与人员 | 开始日期 | 完成日期 | 估算工时 | 实际完成日期 | 备注 |
---|---|---|---|---|---|---|---|
需求分析 | 刘健 | 各业务项目责任人 | 2013-05-22 | 2013-05-28 | 12h | 2013-05-28 | |
FP估算 | 刘健 | 项目开发成员 | 2013-05-30 | 2013-05-30 | 4h | 2013-05-30 | |
概要设计 | 刘健 | 项目开发成员 | 2013-06-03 | 2013-06-03 | 8h | todo | |
源代码编写 | 刘健 | 项目开发成员 | 2013-06-04 | 2013-08-12 | 500h | todo | |
单元测试及报告 | 刘成业 | 项目开发成员 | 2013-06-04 | 2013-08-12 | 100h | todo | |
源代码审核 | 刘健 | 项目开发成员 | 2013-06-04 | 2013-08-12 | 50h | todo | |
开发模拟上线 | 刘健 | 项目开发成员 | 2013-08-15 | 2013-08-16 | 2d | todo | |
质量测试 | QA | QA,项目开发 | 2013-08-14 | 2013-08-19 | 4d | todo | |
性能测试 | QA | QA,项目开发 | 2013-08-20 | 2013-08-21 | 2d | todo | |
QA模拟上线 | QA | QA,项目开发 | 2013-08-22 | 2013-08-27 | 4d | todo | |
生产上线(含准备) | 刘健 | 小白鼠项目人员,项目开发,QA | 2013-08-22 | 2013-08-29 | 6d | todo | |
生产测试 | 刘健 | 小白鼠项目人员,项目开发,QA | 2013-08-29 | 2013-08-30 | 2d | todo |
4.4.2 项目文档
4.4.3 上线计划
4.5 项目培训
培训需求 | 参加人员 | 培训师 | 计划日期 |
---|---|---|---|
项目目标及总体概要设计 | 开发人员,QA | 刘健 | 2013.06.05 ~ 06.07中一天 |
How to test pegasus | 开发人员,QA | 待定 | 待定 |
5 项目跟踪计划
5.1 沟通计划
# | 会议名称 | 频率/日期 | 参与人员 |
---|---|---|---|
1 | 项目每日例会 | daily | 项目成员,QA |
2 | 项目周会 | weekly | 项目成员,上级管理,QA |
3 |
5.2 风险管理
风险类型 | 风险描述 | 风险规避措施 | 负责人 |
---|---|---|---|
项目管理 | 规避项目进度,人力方面的风险 | 每日例会上跟进 | 刘健 |
开发 | 模块设计,实现,接口契约方面的风险 | 每日实时跟进 | 刘成业 |
测试 | 测试进度,问题反馈,及时跟进修复等风险 | 每日例会跟进 | 待定 |
其他 | 线下测试环境可靠性及持续集成等支撑平台状态跟进 | 每日实时跟进 | 刘成业 |
项目文档
1. 目的与范围
2. 参考文献
名称 | 版本 | 链接 |
---|---|---|
Netty Doc | 3.2.1-Final | http://netty.io/3.6/guide |
Hessian Doc | 3.1.5 | http://hessian.caucho.com/doc/ |
3. 缩写或名词
RPC | Remote Procedure Call |
---|---|
Sync | 同步调用,客户端调用远程服务接口时,业务线程Block,直到服务返回结果 |
Callback | 回调调用,客户端调用远程服务接口时,业务线程不Block,并且无结果返回,结果会在后续返回,并触发注册的Callback接口执行 |
Future |
异步调用,客户端调用远程服务接口时,业务线程不Block,无结果返回,但可以获取到这次调用的句柄Future实例,后续可以通过 |
Oneway |
单向调用,客户端调用远程服务接口时,业务线程不Block,无结果返回,并且服务端无响应消息写回,客户端不关心服务端是否正 |
4. 整体流程图
5. 类图
注:简要绘制,实际编码时进行丰富和调整
6. 子模块设计
6.1 序列化方式
序列化 | 优点 | 缺点 |
---|---|---|
XML | 描述能力强,跨语言 | 占用空间大,marshall/unmarshall效率极低 |
JSON | 描述能力强,跨语言,比XML节省空间 | 占用空间较大,jackson引擎尚不熟悉 |
Java | 对Java的各类对象支持完善,使用方便 | 速度慢,占空间 |
Hessian | 字节码方式,跨语言,性能较快,空间较小 | 各类语言的实现支持不够 |
Protobuf | 跨语言,占用空间极小,性能极快 | 需要编写中间代码并生成最终代码,每次更新代码非常麻烦 |
Thrift | 性能,空间俱佳,功能较protobuf完善 | 需要中间代码生成最终代码,跟新代码非常麻烦 |
综合以上各类序列化方式的优缺点,从性能和使用性方便综合权衡,选择较中庸的Hessian序列化方式作为Pegasus的默认序列化方式。后续考虑将其他方式作为可选的实现,使用者自由进行选择。
跨语言方面通过提供http + json的方式实现。
6.2 插件化
暂不考虑,作为v2版本实现,因为目前不需要考虑注册/订阅和监控模块。
6.3 负载均衡
目前包含两类实现:随机路由(random),依据服务提供者负载进行均衡路由(load-autoaware)
Random:
Load Autoaware:
- 具体服务的每个provider在调用端都会维护一个水桶,桶中的水量即为从该客户端发往该provider的,且尚未返回响应的请求量,请求发往该provider时,桶中增加水量,该请求的响应返回时,从桶中减少水量
- 某个服务的请求,发往该服务的所有provider中,对应桶中水量最少的那个provider,因为水量最少,表明当前其处理能力最强---负载最低)
6.4 异常处理
将异常与正常返回区别对待,正常返回使用object::response.return,异常使用throwable::response.error返回,以便服务端异常序列化后传递到客户端,客户端没有该异常的完整结构信息时,能够反序列化为throwable对象,而非无法反序列化或反序列化为map。
序列化或反序列化过程中出现异常,需要模拟为error response返回给调用端,以便调用端知晓具体的异常信息。
业务异常需要enrich上相关的远程调用信息,如请求派发的地址,请求类型,请求sequence,请求超时时间等,以便快速定位异常。
6.5 传输协议设计
+----------------+----------------------+-------------------+----------------------+------------------------+----------------------+------------------+ | magic (2 bytes)| serialize (1 byte) | sequence(8 bytes) | message type(1 byte) | expand region(8 bytes) | body length(4 bytes) | message body | +----------------+----------------------+-------------------+----------------------+------------------------+----------------------+------------------+
magic: magic number
serialize: 标记使用的是什么序列化协议(目前支持hessian, java)
sequence: 该次请求的序列号
message type: 消息类型(业务调用/心跳/业务异常/框架异常)
expand region: 预留扩展区
body length: body区的长度
message body: 消息body区
6.6 线程规范
使用统一的threadfactory和threadpool,以便对线程规范命名,统一监控定位,以及后续的统一优化。
6.7 上下文传递
需要区分为session context与transient context,区别如下:
session context:在每次rpc调用时,从client端一直传递到server端,并从server端返回到client端。
transient context: 仅在client端或server端传递,如client端的invoke chain,server端的process chain上传递,不会传递到相对的另一端。
使用tracker context(session context)进行分布式调用的调用信息跟踪。
6.8 关于超时
由于对目前公司各业务项目的性能控制情况不了解,并且支付交易系统对数据完整性有极高的要求,所以谨慎起见,将框架的默认RPC超时时间设置为15s,若超过15s仍不返回,则视作超时,且现阶段不对超时做传递计算的优化处理。
6.9 http接口
开发排期较紧,开发完毕后,再一次性补充设计文档内容!!!
测试文档
测试范围
1. 同步应答接口功能,http协议,测试该接口的各种调用方法以及成功率
2. 异步应答接口功能,binary协议,4个接口为:sync,oneway,future,callback
3. 注册中心控台功能测试,包含:权重配比功能,动态增减server服务,配置生效的实时性以及心跳带来的容错处理机制
4. 性能测试,主要包含稳定性测试和容量测试的评估,模拟异常情况下系统运行情况以及容错效率的提升
测试计划
-
各测试阶段资源要求
测试任务 | 人员 | 方法或工具 |
---|---|---|
测试计划以及测试策略 | 张林 | 文档描述 |
功能测试 | 张林、龚建林 | 调用接口,工具ecplise junit |
性能测试 | 张林、马莉莉 | 执行工具jmeter或loadrunner |
其他任务 |
|
-
时间计划
里程碑任务 | 工作量 | 计划开始日期 | 计划结束日期 | 人员安排 |
---|---|---|---|---|
制订测试计划 | 1d | 2013-7-29 | 2013-7-29 | 张林 |
设计测试用例 | 3d | 2013-7-30 | 2013-8-1 | 张林、龚建林 |
执行功能测试 | 3d | 2013-8-2 | 2013-8-6 | 张林、马莉莉、龚建林 |
执行性能测试 | 3d | 2013-8-7 | 2013-8-9 | 张林、马莉莉 |
实际应用测试 | 3d | 2013-8-12 | 2013-8-14 | 功能测试组(钱管家) |
测试策略
-
测试需求
功能:
注册中心控台功能测试,该功能有2个
- 权重可以自由设置配比,从而达到各种配比功能
- 自由动态的扩展server服务
性能:
此次性能测试,主要测试该系统在正常运行时,其稳定性和容错性,在正常运行情况下,该系统的内存消耗以及对于服务器的cpu消耗情况,在发生错误或者异常的情况下,该系统是否能够无错误的继续运行,从而构建一个稳定,高效,容错,易维护,可监控的服务调用框架。
接口:
本次测试的接口有5个,分别如下:
- 同步应答接口,http协议
- 4个异步应答接口,binary协议,分别为:sync,oneway,future,callback
-
测试类型及方法
测试方法:
本次测试,将通信中间件基础服务提供的jar包,以应用的形式,部署在本地,提供接口供客户端访问及调用。
1. 根据不同的接口,采取不同的调用方式,模拟各种类型如String,int,long等的调用,检验接口返回是否正确。
2. 根据不同的接口,模拟报异常的情况传送给客户端及服务端,检验服务端或者客户端对于异常处理的情况是否满足需求。
注册中心权重配比功能测试:
Case 1
测试目标 |
检验server权重分为0表示服务停止工作 |
测试方法 |
将2台机器的权重配比更改,如:server1权重改为0,server2改为1 |
完成标准 |
当server1改为0,server2改为1之后,server1停止工作,检查系统运行状态或者观察日志去判断 |
Case 2
测试目标 |
权重分配后,其是否实时生效 |
测试方法 |
将server服务权重同时设置为0或者同时设置为1-10不等,检验系统是否能够实时暂停服务或者运行服务 |
完成标准 |
同时设置为0时,系统暂停工作,客户端响应报错 同时开启权重1-10不等,检验系统是否能够立即工作 |
Case 3
测试目标 |
检测权重分配比例是否生效 |
测试方法 |
初始状态:server权重都为5 将server的权重配置,一个改为1,另外一个改为9,检验其发送的请求是否按照1比9的比例,流向server服务 |
完成标准 |
通过观察cpu的消耗来模糊的观察压力分布,通过日志的计数,来观察精细的压力分布 |
Case 4
测试目标 |
心跳异常测试 |
测试方法 |
大量的发送请求至server端,突然将某台server权重设置为0 |
完成标准 |
|
Case 5
测试目标 |
找不同配置的机器作为server端,检验配比效果是否与预期一致 |
测试方法 |
找配置比例差距较大的server服务(2C和4C和32C) |
完成标准 |
完成各种配比检测(在机器不出现任何异常的情况下),按照实际配比进行请求流向分配,通过日志可以查询 |
注册中心增减server功能测试
Case 1
测试目标 |
增加一台server服务后,该服务能够正常接受请求 |
测试方法 |
手动配置一台新的server服务,查看后台日志是否接收到请求 |
完成标准 |
添加完server服务,该应用能够正常运行起到分流减压作用 |
Case 2
测试目标 |
减少一台server服务,系统不受影响,能够正常运行 |
测试方法 |
将权重设置为0再删除该应用 |
完成标准 |
能够成功删除该server并通过日志查看该应用不再接受到请求 |
Case 3
测试目标 |
增加或删除server服务过程中,不对其他server造成任何功能上的影响 |
测试方法 |
增加或者server服务 |
完成标准 |
在增加或减少过程中,其他server正常运行,无任何异常情况出现 |
性能测试:
测试目标 |
检验系统的所能承受的最大请求数(TPS) |
测试方法 |
模拟用户发送请求,观察测试指标 |
完成标准 |
容量测试,主要测出最大值,结果待定(需评审) |