在实际生产系统中,会有这样的一种状况:A服务调用B服务,B服务调用C服务(只考虑同步调用,不考虑异步调用,因此经过mq的方式这里排除):
若是A服务想要调用B服务,咱们是须要知道B服务的IP的,同理B服务也要知道C服务的IP:
看起来已经解决了多个服务同步调用的问题,若是此时B服务的IP变了怎么办?A服务是否是就要作更改了,可是有没有想过,若是还有其余服务也调用B呢,那这些服务都要作变动,没及时变动的就不能正常调用了。segmentfault
有人说,用Nginx反向代理:
此时对B服务的调用都是经过NGINX_1,对C服务的调用都是经过NGINX_2,若是B服务的地址改了,咱们只须要改NGINX_1的配置文件而后重启就好。看起来能够解决,咱们示例只有3个服务调用,链路就这么长了,若是是更多的服务调用,那链路要多长,并且每次新增一个服务都要配置一个新的Nginx,那运维可能会打你。缓存
有人说,那用DNS吧:
虽然屏蔽了IP,和上面同样,每次新增一个服务都要配置一个新的域名对应IP,更麻烦的是,在集群状况下,Nginx能够知道哪一个服务不可用,并把请求转发到其余集群服务器,可是DNS不知道,并且DNS也不能根据必定的策略进行负载均衡,还有缓存等等问题。服务器
既然上面两种方式都不合适,咱们能够用注册中心。
在服务B启动的时候,会往注册中心注册当前服务的ip以及端口,注册中心维护这些注册信息,A服务在调用以前,会经过注册中心拿到B服务的ip和端口,这样就能够直接调用B服务了,不再怕服务B乱改地址、在集群里增减服务了。网络
常见的注册中心有zookeeper、consul、eureka、nacos,前两个是CP,eureka是AP,nacos两个都支持,那咱们是选哪种呢?CAP概念见以前文章负载均衡
AP模型状况下,此时B服务1已经注册到注册中心1了,B服务2也注册到注册中心2了,A服务1是能够经过注册中心1获取B服务1的地址,A服务2也能够经过注册中心2获取B服务2的地址,虽然注册中心最终会由于同步而保持数据最终一致,可是在这个过程当中,并不影响服务从注册中心获取被调用方的地址,虽然有可能获取到的数据并非完整的(数据没有强一致性)。
CP模型状况下,能够看到只有Leader才能够注册,而后把数据同步到Slave。这个就相对于注册中心是单写了,因此写的性能就比AP的差。并且为了保证数据的一致性,要同步到其余Follower节点的时候才能够被读取到,另外若是Leader宕机了,整个服务在选举的时候是不可用的,知道新的Leader被选举出来。
综上,AP虽然牺牲了数据的强一致性,可是性能上比CP好。好比上面的例子,虽然A服务1只有B服务1的地址,可是也能够正常工做的,因此数据的强一致性实际上是不太须要的。可是他也有一个问题,就是B服务宕机的时候,A服务并不能及时的发现。运维
在CP模型下,咱们假设A服务1和A服务3是同一个机房的,A服务2是另一个机房的,此时出现了脑裂,致使两个机房不能互相通讯。在这种状况下,为了保证数据的一致性,下面机房的注册中心此时是不能读写的,这样形成的后果以下:异步
因此明明是同一个机房的,却由于脑裂而不能对B服务扩容,甚至没法访问B服务。
综上,咱们应该选择AP的注册中心。性能
不论是CP模型仍是AP模型,在大规模服务下,注册中心都很难支持。
AP模型下,他们会互相同步注册信息,致使大量的数据来各个节点传递,占用了网络带宽以及CPU。
CP模型下,每一个服务的上线下线都要通知各个服务,服务一多,网络带宽就被占用。spa