服务注册与发现

随着业务的发展,用户量日益上升,单一的系统越来越复杂,越来越庞大,单纯的提升服务器性能始终有顶天的一天,我们可以通过分布式技术,例如:服务器集群,水平业务划分,应用分解,系统分流,微服务架构等方式来解决系统性能问题和复杂业务问题。

第一篇:架构演进

在分布式体系下服务注册与发现将会以核心组件而存在,也将是接下来讨论的话题。

Lazy服务注册与发现(一)

由于应用的分解,微服务的引入,服务越来越多,业务系统与服务系统之间的调用,都需要有效管理。

在服务化的早期,服务不是很多,服务的注册与发现并不是什么新鲜的名词,Nginx+内部域名服务器方式,甚至Nginx+host文件配置方式也能完成服务的注册与发现。

架构图如下:

(架构一)


各组件角色如下:

Nginx通过多域名配置实现生产者服务路由,通过upstream对生产者提供负载均衡,通过checkhealth对生产者提供健康检查。

在内部域名服务器/本地host文件配置服务域名的方式,实现域名与服务的绑定。

生产者提供服务给消费者访问,并通过Nginx来进行请求分发。在服务化的早期,服务较少,访问量较小,解决了服务的注册与发现与负载均衡等问题。随着业务的发展,用户量日益上升,服务也越来越多,该架构的问题暴露出来:

1)最明显的问题是所有的请求都需要nginx来转发,同时随着访问量的提升,会成为一个性能瓶颈。

2)随着内部服务的越来越多,服务上线nginx的配置,内部域名的配置也越来越多,不利于快速部署。

3)一旦内部网络调整,nginx upstream也需要做对应的配置调整。

Lazy服务注册与发现(二)

由于所有的请求都需要nginx来转发,同时随着访问量的提升,会成为一个性能瓶颈,为了解决这个瓶颈,引入下面这个架构。

(架构二)


这个架构在nginx的上层加入了LVS,LVS基于第四层的IP转发,一定限度提高了并发能力,但是所有请求都通过LVS来转发。

同时nginx分组,服务分组,虽然nginx不再是瓶颈的所在,但是这样带来的代价太高,配置越来越多,工作量越来越大,对系统压力需要有预见性,有效nginx分组,服务分组部署。

Lazy服务注册与发现(三)

由于所有的请求都需要LVS来转发,同时随着访问量的提升,会成为一个性能瓶颈,为了解决这个瓶颈,引入下面这个架构。

(架构三)


在这个架构基础上需要做两件事情:

对系统压力需要有预见性,有效nginx分组,服务分组部署。

消费端需要编程实现分组选择,可以是轮训,random等实现,我们每一个消费者同时承担了的负载均衡的职责。

ZK服务注册与发现 (一)

通过架构三解决了nginx的瓶紧,但是服务上下线需要在nginx,域名服务器做相应的配置,一旦服务的IP端口发生变化,都需要在nginx上做相应的配置,为了解决这个问题引入下面这个架构。

(架构四)


服务在启动的时候就将endpoint注册到Zookeeper对服务进行统一管理。

服务节点增加Endpoint不需要做任何配置,ZK将以Watch机制通知消费者。

消费者本地缓存了提供者服务列表,不需要转发,直接发起服务调用。

缺点:

需要通过zookeeper API来实现服务注册与发现,负载均衡,以及容错,为了解决nginx的瓶紧架构三也是需要通过编程的方式实现负载均衡。

ZK服务注册与发现 (二)

Zookeeper数据模型结构是一个树状层次结构。每个节点叫做Znode,节点可以拥有子节点,同时允许将少量数据存储在该节点下,客户端可以通过NodeCacheListener监听节点的数据变更,PathChildrenCacheListener监听子节点变更来实时获取Znode的变更(Wather机制)。

以下是点融成都服务注册结构,见下图,接下来的讲解也将以这个结构为基础:

ZK服务注册与发现 (三)

1./com/dianrong/cfg/1.0.0/rpcservice: 命名空间,用来跟其他用途区分。

2./com/dianrong/cfg/1.0.0/rpcservice下的所有子目录由两部分组成,

“应用名称” + “-” +  “分组名称”例如:ProductService-SG1,ProductService-SG2, 对应Nginx注册中心Nginx-SG1, Nginx-SG2

3. 服务分组下的所有子节点为临时节点,key为“PROVIDER”+ IP(去符号.)  + “-” + 端口,Value为endpoint信息。

例如:PROVIDER1921681010-8080   = http://192.168.10.10:8080

第二篇:代码分析

项目说明

有了上面的理论我们接下来针对基于ZK的服务与发现的代码分析,代码已经提交到git

GIT地址:

https://code.dianrong.com/projects/PLAT/repos/platform/compare/commits?sourceBranch=refs%2Fheads%2FEVER-81-zk&targetBranch=refs%2Fheads%2Fmaster

说明:

1. 该组件建立在Curator基础之上,Curator是Netflix开源的一套ZooKeeper客户端框架封装ZooKeeper client与ZooKeeper server之间的连接处理。

2. Curator提供如下机制,保证我们不需要关注网络通信,而把主要精力放在业务逻辑的处理。

重试机制:提供可插拔的重试机制, 它将给捕获所有可恢复的异常配置一个重试策略, 并且内部也提供了几种标准的重试策略

连接状态监控: Curator初始化之后会一直的对zk连接进行监听, 一旦发现连接状态发生变化, 将作出相应的处理

ZK客户端实例管理:Curator对zk客户端到server集群连接进行管理. 并在需要的情况, 透明重建zk实例, 保证与zk集群的可靠连接

基于ZK的服务与发现UML类图:


目标

1. 统一配置中心

数据实时性,一旦zk节点发生变化,实时通知本地hash同步刷新。

2. 服务注册

服务启动完成,服务IP,端口以临时节点的形式注册到zk,在网络正常的情况下,一直存在。

3. 服务发现

服务启动完成,将服务注册信息刷新到本地hash。

4. 服务上下线

服务注册到zk将实时通知服务发现方,更新本地hash,服务下线也将实时通知服务发现方,更新本地hash。

5. 负载均衡

服务发现方获取服务缓存在本地hash,通过random,robin等负载均衡算法完成服务选择性调用。

6. 网络中断容灾

针对注册方网络中断,服务下线,网络恢复,服务上线,并通知服务发现方更新本地Hash;

针对发现方网络中断,通过本地hash负载均衡,网络恢复重刷hash,负载均衡重新分配。

7. Zookeeper宕机容灾

针对注册方Zookeeper宕机,服务下线,尝试重连, Zookeeper 启动重连成功,服务上线,并通知服务发现方更新本地hash,针对发现方Zookeeper宕机,通过本地hash负载均衡,尝试重连,  Zookeeper 启动重连成功,重刷hash,负载均衡重新分配。

基本配置

PathConfig.java

包含服务注册的命名空间和统一配置的命名空间的配置。

SgConfig.java

包含服务名和分组名的配置

ZookeeperConfig.java

包含zookeeper地址,会话超时时间,连接超时时间,命名空间以及认证信息的配置

ZK操作框架

IzookeeperManager.java

定义了一套zookeeper操作规范(类似JDBC操作数据数据库规范),有待继续完善。

ZookeeperManager.java

针对IzookeeperManager接口规范的实现(类似Mysql驱动对Mysql操作的实现)

ZookeeperManagerPool.java

针对ZookeeperManager实例的缓存,不同配置缓存不同ZookeeperManager实例,避免zookeeper连接创建的开销,同时可以根据zookeeper水平分组扩展zookeeper

实例。

统一配置,服务注册与发现

AbstractZookeeperFeature.java

内部两个接口定义:

IConfigService 提供针对统一配置接口的定义, IManagementService提供服务注册与发现接口的定义。

ConfigService.java

统一配置的实现。

ManagementService.java

服务注册与发现的实现。

负载均衡

LbStrategy.java

负载均衡策略接口定义,目前实现了两种负载均衡算法,Random负载均衡和Robin负载均衡。

RandomStrategy.java

基于随机负载均衡的实现。

RobinStrategy.java

基于轮循负载均衡的实现。

统一配置Listener

ConfigPathChildrenCacheListener.java

统一配置结点监听, 针对CHILD_REMOVED,CHILD_ADDED,CHILD_UPDATED事件对本地hash实时更新。

服务注册与发现Listener

ZookeeperStateListener.java

Zookeeper状态监听接口定义,定义需要关心的三种事件:

LOST-断开连接达到一定时间

CONNECTED-第一次连接成功

RECONNECTED-重连成功触发事件。

ServiceRegistStateListener.java

服务注册状态监听实现:

1.一旦网络丢包严重/ zk宕机/ zk重启,客户端将会与zk断开,服务下线,网络恢复将触发reconnected连接,服务重新注册。

2.一旦zk断开服务下线,长时间连接不上触发Lost事件,ServiceRegistStateListener将会尝试不断连接直到连上为止,服务重新注册。

ServiceDiscoverStateListener.java

服务发现状态监听实现:

1.一旦网络丢包严重/ zk宕机/ zk重启,客户端将会与zk断开,网络恢复将触发reconnected连接,重新获取服务列表,刷新本地hash。

2.一旦zk断开服务下线,长时间连接不上触发Lost事件,ServiceDiscoverStateListener将会尝试不断连接直到连上为止,以便刷新本地hash。

ServicePathChildrenCacheListener.java

服务发现结点监听, 针对CHILD_REMOVED,CHILD_ADDED,CHILD_UPDATED事件消费者对本地hash实时更新,以便及时刷新服务上下线。

第三篇:单元测试

环境准备

1. 在zookeeper中准备结点 com/dianrong/cfg/1.0.0/rpcservice

create /com/dianrong/cfg/1.0.0/rpcservice  “”

2. 模拟docker/JVM启动参数设置

由于点融网是通过物理机IP加端口映射到docker实例IP加端口的方式对外提供服务,因此需要通过java -D配置宿主机的IP加端口以便应用程序获取服务IP加端口用来进行服务注册。

服务注册

1. 在服务注册之前通过zookeeper控制台查看,期望的注册节点目前为空。

2. 启动服务注册单元测试,sleep 10s。

3. 观察zookeeper中注册结点,期望的临时节点已经存在。

服务发现

通过服务注册以后然后服务发现,发现节点与预期注册结点一致。

负载均衡

通过服务注册以后然后负载均衡,负载均衡获取节点与预期节点一致。

服务上下线

1. 准备两套单元测试并模拟docker/JVM启动参数设置。

2.启动服务注册,服务发现,负载均衡集成单元测试,测试控制台按照预期打印出服务注册信息,注册了两个服务节点通过负载均衡交叉出现。

3. 通过zookeeper控制台查看成功注册两个节点。

4.关闭机器1单元测试,结点1在zookeeper离线,结点2在zookeeper在线。

负载均衡只有一个节点存在达到预期目的

网络中断

1. 启动服务注册,服务发现,负载均衡集成单元测试,测试控制台按照预期打印出服务注册信息。

2. 通过Linux iptables开启防火墙,模拟网络中断。

服务掉线,通过zookeeper控制台查看注册节点消失。

服务发现方任然可以从本地Hash中获取服务节点。

3. 关闭Iptables,服务上线。

服务上线,通过zookeeper控制台查看注册节点出现。

服务发现方获取服务节点重刷本地Hash中。

Zookeeper宕机

1. 启动服务注册,服务发现,负载均衡集成单元测试,测试控制台按照预期打印出服务注册信息。

2.关闭zookeeper,单元测试出现连接拒绝错误,但是任然能按照预期获取本地hash中的服务注册信息。

3. 启动zookeeper,单元测试打印出重连信息,并重刷本地服务hash。

本文作者:秦瑜 Chris.Qin(点融黑帮),来自点融BE Team, 2015年10月加入点融,多年大并发分布式互联网架构经验。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容