服务发现的基本原理[转]

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 服务发现的基本原理 钱文品 5 天前 请原谅我使用了链家的图标,小编真不是给房产中介来打广告的。 什么是服务发现? 服务发现并没有怎样的高深莫测,它的原理再简单不过。
钱文品 钱文品
5 天前

请原谅我使用了链家的图标,小编真不是给房产中介来打广告的。

什么是服务发现?

服务发现并没有怎样的高深莫测,它的原理再简单不过。只是市面上太多文章将服务发现的难度妖魔化,读者被绕的云里雾里,顿觉自己智商低下不敢高攀。

服务提供者是什么,简单点说就是一个HTTP服务器,提供了API服务,有一个IP端口作为服务地址。服务消费者是什么,它就是一个简单的进程,想要访问服务提供者提供的服务来干一些事情。一个HTTP服务器既可以是服务提供者对外提供服务,也可以是消费者需要别的服务提供者提供的服务,这就是服务依赖,没有你我就不是我自己。复杂的服务甚至有多个服务依赖。

服务发现有三个角色,服务提供者、服务消费者和服务中介。服务中介是联系服务提供者和服务消费者的桥梁。服务提供者将自己提供的服务地址注册到服务中介,服务消费者从服务中介那里查找自己想要的服务的地址,然后享受这个服务。服务中介提供多个服务,每个服务对应多个服务提供者。

服务中介就是一个字典,字典里有很多key/value键值对,key是服务名称,value是服务提供者的地址列表。服务注册就是调用字典的Put方法塞东西,服务查找就是调用字典的Get方法拿东西。

当服务提供者节点挂掉时,要求服务能够及时取消注册,比便及时通知消费者重新获取服务地址。

当服务提供者新加入时,要求服务中介能及时告知服务消费者,你要不要尝试一下新的服务。

Redis作为服务中介

Redis里面有丰富的数据结构,拿来存储服务字典再合适不过了。对每一个服务名称,我们用一个set结构存储服务的IP:Port字符串。如果服务提供者加入,调用sadd命令加入服务地址,如果服务挂掉,调用srem命令移除服务地址。对服务消费者使用smembers指令获取所有服务地址然后在消费进程里随机挑一个,或者使用srandmemember指令直接获取随机服务地址。

这个时候你也许会表示怀疑,服务发现真这么简单么?答案是还差一点,关于上面的这个解决方案有几个问题。

第一个问题是服务提供者进程如果被kill -9暴力杀死,不能主动调用srem命令怎么办?

这个时候服务列表中多了一个黑地址指向了不存在的服务而消费者完全不知道,这个时候服务中介就成了黑中介了。那该怎么办呢?

我们引入服务保活和检查机制,并更换数据结构。服务提供者需要每隔5秒左右向服务中介汇报存活,服务中介将服务地址和汇报时间记录在zset数据结构的value和score中。服务中介需要每隔10秒左右检查zset数据结构,踢掉汇报时间严重落后的服务地址项。这样就可以准实时地保证服务列表中服务地址的有效性。

第二个问题是服务列表变动时如何通知消费者。有两种解决方案。

第一种是轮询,消费者需要每隔几秒查询服务列表是否有改变。如果服务很多,服务列表很大,消费者很多,redis会有一定压力。所以这时候可以引入服务列表的版本号机制,给每个服务提供一个key/value设置服务的版本号,就是在服务列表发生变动时,递增这个版本号。消费者只需要轮询这个版本号的变动即可知道服务列表是否发生了变化。因为服务列表比较稳定,仅在网络严重抖动的情况下才会频繁发生变动,所以redis几乎没有压力。

第二种是采用pubsub。这种方式及时性要明显好于轮询。缺点是每个pubsub都会占用消费者一个线程和一个额外的redis连接。为了减少对线程和连接的浪费,我们使用单个pubsub广播全局版本号的变动。所谓全局版本号就是任意服务列表发生了变动,这个版本号都会递增。接收到版本变动的消费者再去检查各自的依赖服务列表的版本号是否发生了变动。这种全局版本号也可以用于第一种轮询方案。

第三个问题是redis是单点的,如果挂掉了怎么办?

这是个大问题。正是因为这个问题的存在,流行的服务发现系统都是使用分布式数据库zookeeper/etcd/consul等来作为服务中介,它们是分布式的多节点的,挂掉了一个节点没关系,系统仍然可以正常工作。

那如果整个zk集群挂掉会怎样呢?其实每个服务消费者在本地内存里都会存一份当前的服务列表,即使服务中介集群挂掉,也是可以使用当前的服务列表正常工作的。

那redis作为服务中介就真的不靠谱了么?其实还有个redis-sentinel可以消除redis的单点问题,redis-sentinel可以在主节点挂掉的时候,自动升级从节点为主节点。所以拿redis干这件事也是可以的。用redis干服务发现确实非常简单,虽然这种方式非常不流行。

服务提供者不只是HTTP服务

上面提到服务提供者简单来说就是HTTP服务器,其实服务多种多样。可以是数据库服务,可以是RPC服务,可以是UDP服务等等。

如果是MySQL数据库,那如何将MySQL服务注册到服务中介呢?原生的MySQL可没有提供这样功能。一般做法是提供一个Agent代理去注册。这个代理除了将服务地址注册到服务中介外,还需要监控MySQL的健康状况,以便当MySQL宕机时能及时切换到新的MySQL服务地址。一般这个Agent为了节省资源而不止监控一个数据库,它可以同时监控多个数据库,甚至是多种数据库。

服务配置重加载

服务发现一般只是用来注册和查找服务列表这样一个比较单纯的功能。不过现代的服务发现系统还会集成服务配置管理功能。这样可以实现服务配置的实时重加载。原理也很简单,就是对于每一个服务项,服务中介还会存储一个单独的key/value用来存储这个服务的配置信息。当这个配置项在后台被修改时,服务中介会实时通知相关服务器变更配置信息。比如数据库地址变动,业务参数修改等。

服务管理后台

为了便于服务管理,一般服务发现还会提供一个服务管理后台,用于管理人员查看服务集群的状态。如果服务注册和汇报时提供冗余的配置信息,服务管理后台就可以呈现更为详细的服务信息。服务管理后台还可以将所有的服务依赖组织起来,呈现出一颗漂亮的服务依赖树。

服务发现的一个简单实现

小编在闲暇之余基于Redis实现了一个简单的服务发现系统Captain。读者可以去github上下载这个项目进行学习。我除了编写了服务发现的服务器之外,客户端sdk也一块做了开发,可能不太稳定,希望读者体谅,不要用于线上的业务系统。

 

 
谋胆并重
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
5月前
|
传感器 安全 中间件
深入浅出:SOME/IP协议中的服务发现机制解析
深入浅出:SOME/IP协议中的服务发现机制解析
335 0
|
11月前
|
负载均衡 Dubbo 应用服务中间件
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
88 0
|
12月前
|
存储 运维 持续交付
Nacos架构与原理 - 寻址机制
Nacos架构与原理 - 寻址机制
104 0
|
自然语言处理 监控 Cloud Native
精华推荐 |【深入浅出Sentinel原理及实战】「原理探索专题」完整剖析Alibaba微服务架构体系之轻量级高可用流量控制组件Sentinel(1)
精华推荐 |【深入浅出Sentinel原理及实战】「原理探索专题」完整剖析Alibaba微服务架构体系之轻量级高可用流量控制组件Sentinel(1)
931 0
精华推荐 |【深入浅出Sentinel原理及实战】「原理探索专题」完整剖析Alibaba微服务架构体系之轻量级高可用流量控制组件Sentinel(1)
|
2月前
|
缓存 Linux 测试技术
微服务过载保护原理与实战
微服务过载保护原理与实战
|
2月前
|
存储 缓存 Java
Eureka原理与实践:深入探索微服务架构的核心组件
在微服务架构日益盛行的今天,服务之间的注册与发现成为了保证系统高可用性和灵活性的关键。Eureka,作为Netflix开源的服务注册与发现框架,凭借其简单、健壮的特性,在微服务领域占据了举足轻重的地位。本文将深入剖析Eureka的原理,并通过实践案例展示其在实际项目中的应用,以期为开发者提供一个高端、深入的视角。
|
5月前
|
负载均衡 算法
软件体系结构 - 负载均衡算法
软件体系结构 - 负载均衡算法
42 4
|
5月前
|
Kubernetes Cloud Native 微服务
作者推荐|剖析云原生服务框架中服务发现机制的核心原理与实现机制
作者推荐|剖析云原生服务框架中服务发现机制的核心原理与实现机制
165 0
|
Kubernetes 负载均衡 网络协议
K8s如何实现服务发现与配置管理
K8s在实现负载均衡与配置管理上的原理是咋样的呢?
|
存储 负载均衡 算法
08-微服务技术栈(扩展):负载均衡算法
负载均衡算法作为Redis、MQ、ZK,GateWay等集群、组件必不可少的算法策略,是微服务框架中不可或缺的一部分知识点,本节我们将花费短暂的时间做个了解。
273 0