在互联网应用领域,服务的动态性需求十分常见,这就对服务的自动发现和可动态扩展提出了很高的要求。
微服务系统动辄上万个服务,而且还要动态伸缩。以人工写好的IP、Port 硬编码脚本的方式无法做到大规模自动化,稍微多点服务运维就傻了。微服务必然要做到ip和port自动分配,减少人工干预。我们需要让每个服务能动态的创建地址,同时调用方要能感知地址变化。
这就需要有一个服务注册与发现的机制,这篇文件就是讨论如何实现这个机制。
Docker 的出现,以及微服务架构的兴起,让众多开源项目开始关注在松耦合的架构前提下,如何基于 Docker 实现一套真正可动态扩展的服务架构。
Registrator
Registrator是一个能自动发现docker container提供的服务,并在后端服务注册中心注册服务或者取消服务注册的工具,后端注册中心支持consul、etcd、skydns2、zookeeper等存储。Registrator认为任何监听在某个端口的程序都是一个服务,如果这个程序监听了多个端口,则这个程序是多个服务。既然Registrator是关于docker container的服务发现的,那么Registrator部署的最好方式就是在每个docker engine上部署一个Registrator实例了。这样就和我们的代码实现完全解耦了,对上层透明化,无感知。它有如下特点:
1、通过docker socket直接监听容器event,根据容器启动/停止等event来注册/注销服务
2、每个容器的每个exposed端口对应不同的服务
3、支持可插拔的registry backend,默认支持Consul, etcd and SkyDNS
4、自身也是docker化的,可以容器方式启动
5、用户可自定义配置,如服务TTL(time-to-live)、服务名称、服务tag等
nginx
这个耳熟能详的名字,不用过多介绍了,它在这里就是做负载均衡,转发请求用的。当然最擅长负载均衡的是直接用硬件,软件做性能比不上。但软件成本低、维护方便。
负载均衡的方式没有变,只是多了一些外围的组件,当然这些组件对client是不可见的,client依然只能看到nginx入口,访问方式也没变化。
其中,我们用registrator来监控每个web server的状态。当有新的web server启动的时候,registrator会把它注册到consul这个注册中心上。由于consul_template已经订阅了该注册中心上的服务消息,此时consul注册中心会将新的web server信息推送给consul_template,consul_template则会去修改nginx.conf的配置文件,然后让nginx重新载入配置以达到自动修改负载均衡的目的。同样当一个web server挂了,registrator也能感知到,进而通知consul做出响应。
consul
consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。服务部署简单,只有一个可运行的二进制的包。每个节点都需要运行agent,他有两种运行模式server和client。每个数据中心官方建议需要3或5个server节点以保证数据安全,同时保证server-leader的选举能够正确的进行。
上图是一个简单的consul cluster的架构,Consul Cluster有Server和Client两种角色。不管是Server还是Client,统称为Agent,Consul Client是相对无状态的,只负责转发RPC到Server,资源开销很少。Server是一个有一组扩展功能的代理,这些功能包括参与Raft选举,维护集群状态,响应RPC查询,与其他数据中心交互WAN gossip和转发查询给leader或者远程数据中心。
在每个数据中心,client和server是混合的。一般建议有3-5台server。这是基于有故障情况下的可用性和性能之间的权衡结果,因为越多的机器加入达成共识越慢,Server之间会选举出一个leader。然而,并不限制client的数量,它们可以很容易的扩展到数千或者数万台。
SpringCloud Feign、grpc、rest通信之间的不同点
Feign与grpc在性能不仅仅体现在http1和http2的差异上,大部分其实是数据的传输性能,同样的数据,传输的越少,用的带宽就越少,性能就越好。其实主要体现在序列化协议上,Springcloud使用JSON序列化,可读性更高,但是JSON占用空间大,又没有类型,所以在传输效率和序列化上都比较耗性能,然后grpc使用ProtoBuf序列化协议,将对象序列化成二进制数据,占用空间更小,序列化和反序列化效率更高。所以在通信效率上grpc要更好一些