整体架构设计
mykit-serial的整体架构图如下所示。
mykit-serial框架各模块的含义如下:
-
mykit-bean:提供统一的bean类封装和整个框架使用的常量等信息。
-
mykit-common:封装整个框架通用的工具类。
-
mykit-config:提供全局配置能力。
-
mykit-core:整个框架的核心实现模块。
-
mykit-db:存放数据库脚本。
-
mykit-interface:整个框架的核心抽象接口。
-
mykit-service:基于Spring实现的核心功能。
-
mykit-rpc:以RPC方式对外提供服服务(后续支持Dubbo,motan、sofa、SpringCloud、SpringCloud Alibaba等主流的RPC框架)。
-
mykit-server:目前实现了Dubbo方式,后续迁移到mykit-rpc模块。
-
mykit-rest:基于SpringBoot实现的Rest服务。
-
mykit-rest_netty:基于Netty实现的Rest服务。
-
mykit-test:整个框架的测试模块,通过此模块可以快速掌握mykit-serial的使用方式。
发布模式
根据最终的客户使用方式,可分为嵌入发布模式,RPC发布模式和Rest发布模式。
-
嵌入发布模式:只适用于Java客户端,提供一个本地的Jar包,Jar包是嵌入式的原生服务,需要提前配置本地机器ID(或者服务启动时,由Zookeeper动态分配唯一的分布式序列号),但是不依赖于中心服务器。
-
RPC发布模式:只适用于Java客户端,提供一个服务的客户端Jar包,Java程序像调用本地API一样来调用,但是依赖于中心的分布式序列号(分布式ID)产生服务器。
-
REST发布模式:中心服务器通过Restful API提供服务,供非Java语言客户端使用。
发布模式最后会记录在生成的全局序列号中。
序列号类型
根据时间的位数和序列号的位数,可分为最大峰值型和最小粒度型。
1. 最大峰值型:采用秒级有序,秒级时间占用30位,序列号占用20位
| 字段 | 版本 | 类型 | 生成方式 | 秒级时间 | 序列号 | 机器ID |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| 位数 | 63 | 62 | 60-61 | 30-59 | 10-29 | 0-9 |
2. 最小粒度型:采用毫秒级有序,毫秒级时间占用40位,序列号占用10位
| 字段 | 版本 | 类型 | 生成方式 | 毫秒级时间 | 序列号 | 机器ID |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| 位数 | 63 | 62 | 60-61 | 20-59 | 10-19 | 0-9 |
最大峰值型能够承受更大的峰值压力,但是粗略有序的粒度有点大,最小粒度型有较细致的粒度,但是每个毫秒能承受的理论峰值有限,为1024,同一个毫秒如果有更多的请求产生,必须等到下一个毫秒再响应。
分布式序列号(分布式ID)的类型在配置时指定,需要重启服务才能互相切换。
数据结构
1. 序列号
最大峰值型
20位,理论上每秒内平均可产生2^20= 1048576个ID,百万级别,如果系统的网络IO和CPU足够强大,可承受的峰值达到每毫秒百万级别。
最小粒度型
10位,每毫秒内序列号总计2^10=1024个, 也就是每个毫秒最多产生1000+个ID,理论上承受的峰值完全不如我们最大峰值方案。
2. 秒级时间/毫秒级时间
最大峰值型
30位,表示秒级时间,2^30/60/60/24/365=34,也就是可使用30+年。
最小粒度型
40位,表示毫秒级时间,2^40/1000/60/60/24/365=34,同样可以使用30+年。
3. 机器ID
10位, 2^10=1024, 也就是最多支持1000+个服务器。中心发布模式和REST发布模式一般不会有太多数量的机器,按照设计每台机器TPS 1万/s,10台服务器就可以有10万/s的TPS,基本可以满足大部分的业务需求。
但是考虑到我们在业务服务可以使用内嵌发布方式,对机器ID的需求量变得更大,这里最多支持1024个服务器。
4. 生成方式
2位,用来区分三种发布模式:嵌入发布模式,RPC发布模式,REST发布模式。
00:嵌入发布模式
01:RPC发布模式
02:REST发布模式
03:保留未用
5. 序列号类型
1位,用来区分两种ID类型:最大峰值型和最小粒度型。
0:最大峰值型
1:最小粒度型
6. 版本
1位,用来做扩展位或者扩容时候的临时方案。
0:默认值,以免转化为整型再转化回字符串被截断
1:表示扩展或者扩容中
作为30年后扩展使用,或者在30年后ID将近用光之时,扩展为秒级时间或者毫秒级时间来挣得系统的移植时间窗口,其实只要扩展一位,完全可以再使用30年。
并发处理
对于中心服务器和REST发布方式,ID生成的过程涉及到网络IO和CPU操作,ID的生成基本都是内存到高速缓存的操作,没有IO操作,网络IO是系统的瓶颈。
相对于CPU计算速度来说网络IO是瓶颈,因此,ID产生的服务使用多线程的方式,对于ID生成过程中的竞争点time和sequence,这里使用了多种实现方式
- 使用concurrent包的ReentrantLock进行互斥,这是缺省的实现方式,也是追求性能和稳定两个目标的妥协方案。
- 使用传统的synchronized进行互斥,这种方式的性能稍微逊色一些,通过传入JVM参数-Dmykit.serial.sync.lock.impl.key=true来开启。
- 使用CAS方式进行互斥,这种实现方式的性能非常高,但是在高并发环境下CPU负载会很高,通过传入JVM参数-Dmykit.serial.atomic.impl.key=true来开启。
机器ID的分配
我们将机器ID分为两个区段,一个区段服务于RPC发布模式和REST发布模式,另外一个区段服务于嵌入发布模式。
0-923:嵌入发布模式,预先配置,(或者由Zookeeper产生),最多支持924台内嵌服务器
924 – 1023:中心服务器发布模式和REST发布模式,最多支持300台,最大支持300*1万=300万/s的TPS
如果嵌入式发布模式和RPC发布模式以及REST发布模式的使用量不符合这个比例,我们可以动态调整两个区间的值来适应。
另外,各个垂直业务之间具有天生的隔离性,每个业务都可以使用最多1024台服务器。
与Zookeeper集成
对于嵌入发布模式,服务启动需要连接Zookeeper集群,Zookeeper分配一个0-923区间的一个ID,如果0-923区间的ID被用光,Zookeeper会分配一个大于923的ID,这种情况,拒绝启动服务。
如果不想使用Zookeeper产生的唯一的机器ID,我们提供缺省的预配的机器ID解决方案,每个使用统一分布式全局序列号(分布式ID)服务的服务需要预先配置一个默认的机器ID。
时间同步
使用mykit-serial生成分布式全局序列号(分布式ID)时,需要我们保证服务器的时间正常。此时,我们可以使用Linux的定时任务crontab,定时通过授时服务器虚拟集群(全球有3000多台服务器)来核准服务器的时间。
ntpdate -u pool.ntp.orgpool.ntp.org
最终的性能验证要保证每台服务器的TPS达到1万/s以上。
产生分布式全局序列号
-
描述:根据系统时间产生一个全局唯一的全局序列号并且在方法体内返回。
-
路径:/genSerialNumber
-
参数:N/A
-
非空参数:N/A
-
示例:http://localhost:8080/genSerialNumber
-
结果:3456526092514361344
反解全局序列号
-
描述:对产生的serialNumber进行反解,在响应体内返回反解的JSON字符串。
-
路径:/expSerialNumber
-
参数:serialNumber=?
-
非空参数:serialNumber
-
示例:http://localhost:8080/expSerialNumber?serialNumber=3456526092514361344
-
结果:{“genMethod”:2,“machine”:1022,“seq”:0,“time”:12758739,“type”:0,“version”:0}
翻译时间
-
描述:把长整型的时间转化成可读的格式。
-
路径:/transtime
-
参数:time=?
-
非空参数:time
-
示例:http://localhost:8080/transtime?time=12758739
-
结果:Thu May 28 16:05:39 CST 2015
制造全局序列号
-
描述:通过给定的分布式全局序列号元素制造分布式全局序列号。
-
路径:/makeSerialNumber
-
参数:genMethod=?&machine=?&seq=?&time=?&type=?&version=?
-
非空参数:time,seq
-
示例:http://localhost:8080/makeSerialNumber?genMethod=2&machine=1022&seq=0&time=12758739&type=0&version=0
-
结果:3456526092514361344
产生全局序列号
-
描述:根据系统时间产生一个全局唯一的分布式序列号(分布式ID)并且在方法体内返回。
-
类:SerialNumberService
-
方法:genSerialNumber
-
参数:N/A
-
返回类型:long
-
示例:long serialNumber= serialNumberService.genSerialNumber();
反解全局序列号
-
描述:对产生的分布式序列号(分布式ID)进行反解,在响应体内返回反解的JSON字符串。
-
类:SerialNumberService
-
方法:expSerialNumber
-
参数:long serialNumber
-
返回类型:SerialNumber
最后
权威指南-第一本Docker书
引领完成Docker的安装、部署、管理和扩展,让其经历从测试到生产的整个开发生命周期,深入了解Docker适用于什么场景。并且这本Docker的学习权威指南介绍了其组件的基础知识,然后用Docker构建容器和服务来完成各种任务:利用Docker为新项目建立测试环境,演示如何使用持续集成的工作流集成Docker,如何构建应用程序服务和平台,如何使用Docker的API,如何扩展Docker。
总共包含了:简介、安装Docker、Docker入门、使用Docker镜像和仓库、在测试中使用Docker、使用Docker构建服务、使用Fig编配Docke、使用Docker API、获得帮助和对Docker进行改进等9个章节的知识。
关于阿里内部都在强烈推荐使用的“K8S+Docker学习指南”—《深入浅出Kubernetes:理论+实战》、《权威指南-第一本Docker书》,看完之后两个字形容,爱了爱了!
如何构建应用程序服务和平台,如何使用Docker的API,如何扩展Docker。
总共包含了:简介、安装Docker、Docker入门、使用Docker镜像和仓库、在测试中使用Docker、使用Docker构建服务、使用Fig编配Docke、使用Docker API、获得帮助和对Docker进行改进等9个章节的知识。
[外链图片转存中…(img-85BAXrjC-1714584811607)]
[外链图片转存中…(img-w1wdMBFw-1714584811607)]
[外链图片转存中…(img-gcWuXOBf-1714584811607)]
[外链图片转存中…(img-EP6lzwQ6-1714584811608)]
关于阿里内部都在强烈推荐使用的“K8S+Docker学习指南”—《深入浅出Kubernetes:理论+实战》、《权威指南-第一本Docker书》,看完之后两个字形容,爱了爱了!