十、服务发布和引用

服务提供者需要支持通过配置、注解、API调用等方式,把本地接口发布成远程服务;对于消费者,可以通过对等的方式引用远程服务提供者,实现服务的发布和引用。

1 服务发布设计

服务发布流程:

1.1 服务发布的几种方式

  1. XML配置化方式:业务代码零侵入
  2. 注解方式:业务代码低侵入
  3. API调用方式:业务代码侵入较强

1.2 本地实现类封装成代理

对于服务提供者,将本地实现类封装成代理对象不是必需的:也可以利用一系列工具类解析服务提供者信息,然后将服务提供者的地址信息注册到服务注册中心。采用动态代理的好处如下:

  1. 不管是什么服务,它们的发布流程都是相似的,通过抽象代理层,可以对服务发布行为本身进行封装和抽象。
  2. 通过动态代理对象,可以对服务发布进行动态拦截,方便平台和业务对服务发布进行个性化定制。
  3. 便于扩展和替换。

1.3 服务发布成指定协议

同一个服务,允许发布成多种协议,例如 HTTP、Thrift 等。

1.4 服务提供者信息注册

服务按指定协议发布之后,需要将服务发布信息注册到注册中心,用于服务路由和服务治理。

服务注册的结构有多种方式,例如按照主机地址、按照服务名或者 URL。

2 服务引用设计

消费者导入服务提供者的接口 API定义,配置服务引用信息,即可在代码中直接调用远程服务:

2.1 本地接口调用转换成远程服务调用

原理在于根据导入的服务提供者接口 API和服务引用信息,生成远程服务的本地动态代理对象;它负责将本地的 API调用转换成远程服务调用,然后将结果返回给调用者。

2.2 服务地址的本地缓存

服务消费者和提供者的启动顺序无法控制,因此消费者需要检测指定服务目录,监听新的服务提供者注册和已发布服务的下线,工作原理如下:

2.3 远程服务调用

消费者从本地缓存的服务列表中按照指定策略路由,将请求消息封装成协议消息:调用相关协议的客户端将请求发送给服务提供者,业务线程按照服务调用方式选择同步等待或者注册监听器回调。

3 最佳实践

3.1 对等设计原则

例如,通过 XML的 Method 元素可以配置方法级参数,那么 API或者注解也应该支持方法级设置,以防止能力不对等。

3.2 启动顺序问题

服务注册中心如果后启动,需要服务提供者和消费者能够自动重连。

3.3 同步还是异步发布服务

通常情况下,服务全部准备就绪的时间比较短,而且系统启动之后也并不意味着所有服务都会被立即消费,因此,采用异步的方式发布服务也是可行的。
当然还有另外一些办法可减少系统启动时间。例如对于不经常访问的服务采用延迟发布的策略;还有就是服务的懒加载,只发布服务但是不初始化,等到消费者真正调用的时候才进行初始化服务。

3.4 警惕网络风暴

在大规模集群系统中,服务注册中心可能管理数十万条的服务注册信息以及上万个服务提供者和消费者节点。如果服务注册中心管理了大量经常变更的信息,就会发生频繁的变更通知:而这种海量的变更通知可能会挤占服务注册中心的网络带宽,严重时还会导致网络风暴。
因此,在设计时需要考虑如下几个要素:

  1. 哪些信息需要注册到服务注册中心,需要甄别。
  2. 服务注册中心能够管理的服务上限。
  3. 服务注册中心的网络带宽规划。
  4. 服务注册中心的磁盘空间规划。
  5. 服务注册中心的性能。

3.5 配置扩展

4 个人总结

好的分布服务框架对业务代码的侵入要足够低(使用 XML配置方式),将普通的 Java 接口发布成远程服务。