前言
为什么要设计这样一个框架?
答:重点当然是炫技啊!!!哈哈哈,开个玩笑而已。个人感觉无论是spring-cloud还是dubbo框架在服务调用技术底层方面已经趋于完美,但是实际应用场景中,我们经常需要一个请求贯穿N个服务。那么问题来了:我们怎样知道每个服务的之间的服务调用关系呢?如何控制服务间调用的权限呢?是否可以用一个平台来维护我们系统间接口调用权限呢?我这里关注的重点是如何可视化管理系统间调用权限。
spring cloud和dubbo无法实现上面的功能吗?
答:这里就谈谈个人的理解,也许不是非常正确。
第一:spring-cloud和dubbo都实现了服务间调用的底层逻辑,但是他们仅仅作为Rpc底层的一种框架,并没有加入过多的规范限制。比如他们都实现的A调用B的操作,但是并没有过多约束A是否可以调用B,不能做到B的服务都允许哪些服务调用。因为他们关注的是实现A调用B的过程,而不是关注于基于此框架之上产生N多服务需要如何管理。
第二:不可否认的,如果希望能通过上面框架实现我所希望的目标,也是可以实现的。但是我希望打造的是一个可以跨Spring Web平台间的服务治理框架,因为我们的系统内部可能存在既有较为传统的基于Spring的web项目,也有较为流行的spring-boot项目。为了无缝衔接所以我准备打造一款小框架,并冠名为XRpc。
为了这个伟大的目标,我决定设计一个框架,就是它:XRpc
介绍
什么是XRpc?
答:具备服务注册、服务发现、动态维护服务间调用权限的能力。
整合服务管理平台,可视化管理接口权限。具备注册中心能力,可监控在线服务实例。
术语
概念角度:
- 名称空间:实现隔离,不同名称空间下服务不可以相互访问
- 应用名称:一个名称空间下,具有多个应用。即:一个微服务
- 服务名称:一个应用下,具有多个服务。即:一个service bean
- 版本:同一个服务可以拥有多个版本号。可以指定版本号进行服务调用。
- 方法名称:一个服务下具有多个方法。即:service interface中的一个业务处理方法。
代码角度:
- Provider:服务提供方
- Consumer:服务调用方
- Proxyer:分为ProviderProxyer和ConsumerProxyer。单实例用于维护服务状态,收发于xrpc-server的消息
- Agent:分为ProviderAgent和ConsumerAgent。为每一个service bean创建一个代理实例,用于访问远程or内部方法的调用。
设计方案
Provider接口
服务注册
服务方在启动后,扫描本服务需暴露的服务元数据,上报xrpc-server,以注册应用。
请求数据
RpcAppMeta
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
appName | String | Y | 应用名称 |
instanceId | String | Y | 实例ID |
endpoint | String | Y | 暴露服务调用地址 |
expire | Number | Y | 过期时间 |
registry | RegistryConfig | Y | 注册中心配置 |
serviceMetaList | List<RpcServiceMeta> | Y | 服务元数据列表 |
RegistryConfig
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
address | String | Y | 注册中心地址 |
namespace | String | Y | 名称空间 |
perfectIpAddress | Boolean | Y | 是否优先IP地址 |
List<RpcServiceMeta>
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
serviceName | String | Y | 服务名称 |
version | Number | Y | 服务版本号,默认1 |
methodMetaList | List<RpcMethodMeta> | Y | 方法元数据列表 |
List<RpcMethodMeta>
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
methodName | String | Y | 方法名称 |
paramListMeta | List<RpcParamMeta> | Y | 方法参数列表 |
List<RpcParamMeta>
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
type | String | Y | 参数类型,类全名 |
响应数据
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
resCode | String | Y | 响应代码 OK:成功,否则失败 |
resMsg | String | Y | 响应代码描述信息 |
data | 复杂类型 | Y | 业务数据 |
data
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
expire | Number | Y | 过期时间,单位:秒 |
expireAt | Number | Y | 过期时间戳 格式:yyyy-MM-dd HH:mm:ss.SSS |
心跳保持
服务注册完成后,需要进行心跳保持,以确保服务正常。
请求数据
RpcPing
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
namespace | String | Y | 名称空间 |
instanceId | String | Y | 实例ID |
appName | String | Y | 应用名称 |
响应数据
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
resCode | String | Y | 响应代码 OK:成功,否则失败 |
resMsg | String | Y | 响应代码描述信息 |
data | 复杂类型 | Y | 业务数据 |
data
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
expire | Number | Y | 过期时间,单位:秒 |
expireAt | Number | Y | 过期时间戳 格式:yyyy-MM-dd HH:mm:ss.SSS |
Consumer接口
获取在线服务列表
consumer端应用启动后,根据自身依赖服务关系,获取注册中心可用服务列表
请求数据
注意:请求数据为JSON 数组
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
namespace | String | Y | 名称空间 |
appName | String | Y | 应用名称 |
serviceMetaList | List<RpcServiceMeta> | Y | 服务名称元数据列表 |
List<RpcServiceMeta>
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
serviceName | String | Y | 服务名称 |
version | Number | Y | 服务版本号,默认1 |
响应数据
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
resCode | String | Y | 响应代码 OK:成功,否则失败 |
resMsg | String | Y | 响应代码描述信息 |
data | List<GetOnlineAppResData> | Y | 业务数据 |
data
List<GetOnlineAppResData>
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
namespace | String | Y | 名称空间 |
appName | String | Y | 应用名称 |
instanceId | String | Y | 实例ID |
endpoint | String | Y | 暴露服务调用地址 |
serviceMetaList | List<RpcServiceMeta> | Y | 服务元数据列表 |
List<RpcServiceMeta>
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
serviceName | String | Y | 服务名称 |
version | Number | Y | 服务版本号,默认1 |
methodMetaList | List<RpcMethodMeta> | Y | 方法元数据列表 |
List<RpcMethodMeta>
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
methodName | String | Y | 方法名称 |
paramListMeta | List<RpcParamMeta> | Y | 方法参数列表 |
List<RpcParamMeta>
字段名称 | 字段类型 | 是否必传 | 说明 |
---|---|---|---|
type | String | Y | 参数类型,类全名 |