浅谈服务发现和负载均衡的来龙去脉

问题缘由

随着时代发展,单机程序遇到了计算力和存储的双重瓶颈,分布式架构应运而生。单体应用通过函数名(标识)便可轻松完成本地函数调用,在分布式系统中,服务(RPC/RESTful API)承担了类似的角色,但请求服务单靠服务名还不够,服务名只是服务能力(服务类型)的标识,还需要指示服务位于网络何处,而部署在云中的服务实例IP是动态分配的,扩缩容、失败和更新则让问题变得更加复杂,静态配置服务实例适应不了新变化,需要更精细化的服务治理能力,为了解决或者说简化这个问题,服务发现作为一种基础能力被抽象和提供,它试图让请求网络服务像调用本地函数一样简单透明。

服务即功能(函数)。只是服务跟网络紧密联系在一起,所有才会出现网络服务这个名词,服务提供者通过网络发布服务,服务使用者通过网络请求服务,分布式系统突破了单机算力和存储的限制,提升了系统稳定性,使得高并发高可用的海量服务成为可能,但这也增加了软件复杂度,引入软件分层、负载均衡、微服务、服务发现/治理、分布式一致性等新的问题和挑战。

服务发现

服务分服务提供者(Service Provider)和服务消费者(Service Consumer),如果要提供海量服务能力,单一的服务实例显然是不够的,如果要提供成千上万种服务,则需要有一个地方记录服务名到服务实例列表的映射,所以,有必要引入一个新的角色:服务中介,服务中介维护一个服务注册表(Service Registry),可以把注册表理解为服务字典,key是服务名,value是服务提供实例列表;服务注册表是联系服务提供者和服务消费者的桥梁,它维护服务提供者的最新网络位置等信息,也是服务发现最核心的部分。

服务启动的时候,把服务信息注册(put)到服务注册表;服务终止的时候,从服务注册表删除(remove)自身的服务信息。

服务消费者在请求服务的时候,先去服务注册表按名查询(get)服务提供者列表,然后从列表里挑选一个服务实例,向该实例请求服务。

大道至简,这便是最简单的服务发现模型,也是服务发现的基本原理,至此,似乎一切都OK,但其实尚有几个问题没有说清楚。

问题和解法

第一个问题

服务如果不是正常停止,而是被系统kill掉,它便没有机会通知服务注册表把自身服务信息删除,这样注册表便多了一条指向无效服务实例的信息,而服务消费者却并不知情,怎么办?解决的办法很简单:保活(keepalive),服务提供者定期(比如每隔10秒)给服务中介发送keepalive消息,服务中介收到keepalive消息后更新该服务实例的keepalive timestamp,服务中介定期检查该timestamp,如果超期便把该服务实例从注册表剔除。

第二个问题

服务实例列表变化如何通知服务消费者?不外乎两种方法,轮询和pub-sub。轮询是消费者主动询问服务中介服务列表是否变化,如果有变化,则把新的服务列表发送给消费者。如果消费者过多,则服务中介处理轮询的消息会有压力,在服务类别很多,服务列表很大的时候,它甚至会成为瓶颈。pub-sub是服务中介主动通知服务消费者,时效性相比轮询更好,缺点是会占用单独的线程或者连接资源。

第三个问题

服务中介如果挂了怎么办?所以我们要解决单点的问题,通常会用集群来对抗这种脆弱性,有很多用于做服务注册表的开源解决方案,比如etcd/zookeeper/consul,本质上使用分布式一致性数据库来保存注册表信息,它既解决读写性能问题又提高了系统稳定性可用性。

第四个问题

如果服务消费者每次使用远程服务都需要先查询服务中介获取实例列表,再请求服务,这样效率太低效?对服务中介的压力也不小?通常,客户端会缓存服务实例列表,这样对同名服务的多次请求,便不用重复查询,既减少了延迟又减轻了对服务中介的访问压力。

第五个问题

前述的keepalive有间隔,如果在这个间隔内服务实例不可用,那么服务消费者还是不能感知的,所以还是有可能把请求发送到一个无法提供服务的网络远端机器上去,这样自然是没法work。我们无法从根本上杜绝这种情况,系统需要容忍这种错误,但也可以做一些改进,比如向某实例请求服务失败后便拉黑,避免向同一无效服务实例多次派发请求。

第六个问题

服务消费者怎么从多个服务实例里选择一个?如何确保同一服务消费者的多次服务请求被分配到固定的服务实例(有时候需要这样)?这其实就是负载均衡的问题,有多种策略,比如rr、优先级、比如加权随机、一致性哈希。

服务发现模式

服务发现主要有两种模式:客户端发现模式(client-side discovery)和服务端发现模式(server-side discovery)。

客户端发现模式

客户端负责查询服务实例列表并决定向哪个实例请求服务,也就是负载均衡策略在客户端实现。该模式包括注册和发现两个部分。

服务实例调用服务中介的注册接口进行实例注册,服务实例通过keepalive做服务续期,服务中介通过健康检查剔除不可用的服务实例。

服务消费者请求服务的时候,先向服务注册表查询服务实例列表,注册表是一个服务数据库,为了提升性能和可靠性,客户端通常会缓存服务列表(缓存用来确保注册表挂了之后还能继续工作),拿到实例列表后客户端基于负载均衡策略挑选一个实例发送服务请求。

优点:

  • 直接,客户端可以灵活的执行负载均衡策略。
  • 去中心化,非网关式,有效避开单点瓶颈和可靠性下降。
  • 服务发现直接SDK集成进客户端,这种语言整合程度很好,程序执行性能也很好,排错方便。

缺点:

  • 客户端与服务注册表耦合,需要为服务客户端使用的每种语言每种框架开发服务发现逻辑。
  • 这种侵入式的集成会导致任何服务发现的变化都需要客户端应用程序重新编译和部署,强绑定违背了独立性原则。
  • 服务上下线会对调用方有影响,导致服务短暂不可用。

服务端发现模式

发现:服务消费者通过负载均衡器发送服务请求,负载均衡器会查询服务注册表,挑选一个服务实例,并将请求转发到服务实例。

注册:服务注册/注销可以跟上述客户端发现模式一致,也可以通过部署平台的内置服务注册和发现机制完成,即容器化部署平台(docker/k8s)能主动发现服务实例并帮助服务实例完成注册注销。

对比客户端发现模式,使用服务端发现模式的客户端本地不保存服务实例列表,客户端不做负载均衡,这个负载均衡器既承担了服务发现的角色,又承担了网关的角色,所以经常叫API网关服务器。

因为负载均衡器是中心式的,所以它也必须是一个集群,单个实例不足以支撑高并发访问,针对负载均衡器本身的服务发现和负载均衡通常借助DNS。

Http服务器,Nginx、Nginx Plus就是此类服务端发现模式的负载均衡器。

优点:

  • 服务发现对于服务消费者是透明的,服务消费者与注册表解耦,服务发现功能的更新对客户端无感知。
  • 服务消费者只需要向负载均衡器发送请求,不需要为每种服务消费者的编程语言和框架,开发服务发现逻辑SDK。

缺点:

  • 由于所有请求都要经负载均衡器转发,所以负载均衡器有可能成为新的性能瓶颈。
  • 负载均衡器(服务网关)是中心式的,而中心式的架构会有稳定性的隐忧。
  • 因为负载均衡器转发请求,所以RT会比客户端直连模式高。

微服务和服务发现

Service Mesh服务网格是服务于微服务应用程序的可配置基础设施层,旨在处理服务之间的大量基于网络的进程间通信。

Service Mesh服务网关解耦调用和通信,在非mesh下,对于协议的感知和服务发现方法的感知需要应用去做,用mesh之后,就只管调用,mesh通过控制面来控制应用的数据流。

Mesh做服务发现其实是客户端发现模式的升级版,基于sidecar和pilot实现,Sidecars,即数据面板(Data Plane),负责发现目标服务实例地址列表并转发请求。Pilots,即控制面板(Control Plane),负责管理服务注册表的所有服务注册信息。

服务注册模式

一个选择是服务实例自注册,即self-registration模式。另一种选择是其它的系统组件来管理服务实例的注册,即third-party registration模式。

自注册模式如前面所述,它足够简单,不需要第三方组件,缺点是必须为服务中用到的每种编程语言与框架实现注册代码。

第三方注册服务实例不会自己完成注册注销,它由另一个叫做Service Registrar的系统组件负责,该组件会轮询部署环境或者跟踪订阅事件去感知服务实例的变化,帮助服务实例完成自动化注册注销。

Third-party registration模式主要的优势在于解耦了服务和服务注册表。不需要为每个语言和框架都实现服务注册逻辑。服务实例注册由一个专用的服务集中实现。缺点是除了被内置到部署环境中,它本身也是一个高可用的系统组件,需要被启动和管理。

其他

如果某个服务对于的服务实例特别多,比如在一些头部公司,一个服务名可能对应几千几万个服务实例,这样,服务变更的查询和对比会很慢,IO的量会大得超过想象,通常,会用version num去解决这个问题。

以上就是浅谈服务发现和负载均衡的来龙去脉的详细内容,更多关于服务发现和负载均衡的来龙去脉的资料请关注我们其它相关文章!

(0)

相关推荐

  • 服务器负载均衡是什么意思(服务器负载均衡的基本功能和实现原理)

    什么是负载均衡? 负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外供应效力而无须其他服务器的辅助.经过某种负载分管技术,将外部发送来的央求均匀分配到对称结构中的某一台服务器上,而接收到央求的服务器独登时回应客户的央求.均衡负载可以平均分配客户央求到服务器列阵,籍此供应快速获取重要数据,解决很多并发访问效力问题.这种群集技术可以用最少的出资取得接近于大型主机的性能. 负载均衡的类型 根据DNS的负载均衡 经过DNS效力中的随机姓名解析来完结负载均衡,

  • Spring Cloud 系列之负载均衡 Ribbon的示例代码

    1.1 简介 1.1.1 概述   Ribbon 是 Netflix 发布的负载均衡器,它有助于控制 HTTP 和 TCP 客户端的行为.为 Ribbon 配置服务提供者地址列表后,Ribbon 就可基于某种负载均衡算法,自动地帮助服务消费者去请求.Ribbon 默认为我们提供了很多的负载均衡算法,例如轮询.随机等.当然,我们也可为 Ribbon 实现自定义的负载均衡算法.Ribbon 现在已经进入维护状态,但目前仍在大规模使用,Spring Cloud 准备使用 LoadBalancer 作为

  • 详解Docker Swarm服务发现和负载均衡原理

    本文将介绍基于 DNS 的负载均衡.基于 VIP 的负载均衡和路由网格(Routing Mesh). 使用的技术 Docker 使用了 Linux 内核 iptables 和 IPVS 的功能来实现服务发现和负载均衡. iptables 是 Linux 内核中可用的包过滤技术,它可用于根据数据包的内容进行分类.修改和转发决策. IPVS 是 Linux 内核中可用的传输级负载均衡器. 准备工作 swarm 集群: [Manager]node1.[Worker]node2 客户端镜像: regis

  • Nginx 负载均衡是什么以及该如何配置

    什么是负载均衡 负载均衡主要通过专门的硬件设备或者通过软件算法实现.通过硬件设备实现的负载均衡效果好.效率高.性能稳定,但是成本比较高.通过软件实现的负载均衡主要依赖于均衡算法的选择和程序的健壮性.均衡算法也是多种多样的,常见的有两大类:即静态负载均衡算法和动态负载均衡算法.静态算法实现比较简单,在一般网络环境下也能达到比较好的效果,主要有一般轮询算法.基于比率的加权轮询算法以及基于优先级的加权轮询算法等.动态负载均衡算法在较为复杂的网络环境中适应性更强,效果更好,主要有基于任务量的最少连接优先

  • 采用软件负载均衡器实现web服务器集群(iis+nginx)

    我用nginx实现网站负载均衡测试的例子,windows下IIS做负载实测. 如果你的网站访问量(pv)越来越高,一台服务器已经没有办法承受流量压力,那就增多几台WEB服务器来做负载吧. 做网站负载可以买硬件设备来实现,我们公司用的是F5,不过价格就几十万到上百万,太贵了, 目前好多门户网站与大访问量的网站都在使用nginx做为HTTP服务器,所以nginx是非常优秀的,下面我亲手做这个负载测试吧. 软/硬件环境: (2台服务器) 第一台:  CPU:Inter(R) 酷睿 i5 CPU 2.2

  • Nginx + consul + upsync 完成动态负载均衡的方法详解

    前置知识 DNS域名解析过程 在浏览器输入域名,访问后 在浏览器缓存中查找是否有对应的ip和端口,如果有直接访问对应ip和端口 浏览器缓存中没有则在本地host文件中查找是否有对应的~~ 本地host文件中没有则去DSN服务器上查找 外网映射 顾名思义,就是将本地的ip地址,映射出一个公网ip,可以供所有主机(连接到互联网的计算机)访问 疑问:为什么需要使用外网映射 例如做微信支付时的第三方接口回调,微信回调你的接口必须是一个公网ip地址,不然他根本无法给你回调,导致你本地无法测试.这个时候你就

  • Nginx+SpringBoot实现负载均衡的示例

    负载均衡介绍 在介绍Nginx的负载均衡实现之前,先简单的说下负载均衡的分类,主要分为硬件负载均衡和软件负载均衡,硬件负载均衡是使用专门的软件和硬件相结合的设备,设备商会提供完整成熟的解决方案,比如F5,在数据的稳定性以及安全性来说非常可靠,但是相比软件而言造价会更加昂贵:软件的负载均衡以Nginx这类软件为主,实现的一种消息队列分发机制. 简单来说所谓的负载均衡就是把很多请求进行分流,将他们分配到不同的服务器去处理.比如我有3个服务器,分别为A.B.C,然后使用Nginx进行负载均衡,使用轮询

  • ASP.NET Core3.1 Ocelot负载均衡的实现

    1.负载均衡 Ocelot可以在每个路由的可用下游服务中实现负载均衡,这使我们更有效地选择下游服务来处理请求.负载均衡类型: LeastConnection:根据服务正在处理请求量的情况来决定哪个服务来处理新请求,即将新请求发送到具有最少现有请求的服务去处理.算法状态没有分布在Ocelot集群中. RoundRobin:遍历可用服务并发送请求.算法状态没有分布在Ocelot集群中. NoLoadBalancer:从配置或服务发现中获取第一个可用服务来处理新请求. CookieStickySess

  • 浅谈服务发现和负载均衡的来龙去脉

    问题缘由 随着时代发展,单机程序遇到了计算力和存储的双重瓶颈,分布式架构应运而生.单体应用通过函数名(标识)便可轻松完成本地函数调用,在分布式系统中,服务(RPC/RESTful API)承担了类似的角色,但请求服务单靠服务名还不够,服务名只是服务能力(服务类型)的标识,还需要指示服务位于网络何处,而部署在云中的服务实例IP是动态分配的,扩缩容.失败和更新则让问题变得更加复杂,静态配置服务实例适应不了新变化,需要更精细化的服务治理能力,为了解决或者说简化这个问题,服务发现作为一种基础能力被抽象和

  • 服务发现与负载均衡机制Service实例创建

    目录 什么是Service? 创建一个Service实例 集群外部访问svc 创建代理外部应用的Service实例 Service反代外部域名 Service 的类型: 什么是Service? Service是逻辑上的一组Pod,一种可以访问Pod的策略,而且其他Pod可以通过Service访问到这个Service代理的Pod,可以把它理解为传统架构中的反向代理. 相对于Pod而言,Service有一个固定的名称,不会发生改变,并且提供了负载均衡的功能. 通过Service的定义,可以对客户端应

  • Spring Cloud Alibaba Nacos服务治理平台,服务注册、RestTemplate实现微服务之间访问负载均衡访问的问题

    目录 Nacos简介 ☘Spring Cloud 组件依赖版本 ☘Nacos部署 ☘访问Nacos平台 Nacos服务注册.微服务访问.负载均衡实现 nacos-consumer微服务创建 ☘nacos-provider微服务创建 测试 Nacos简介 Github:https://github.com/alibaba/nacos官网文档:https://nacos.io/zh-cn/docs/what-is-nacos.htmlNacos 提供了发现.配置和管理微服务能力,能快速实现动态服务发

  • springcloud中Ribbon和RestTemplate实现服务调用与负载均衡

    文件目录结构 文件目录结构很重要,特别注意的是rule文件要放在主启动类上一级位置,才能够扫描. 写pom <dependencies> <!--springboot 2.2.2--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependenc

  • PHP解耦的三重境界(浅谈服务容器)

    阅读本文之前你需要掌握:PHP语法,面向对象 在完成整个软件项目开发的过程中,有时需要多人合作,有时也可以自己独立完成,不管是哪一种,随着代码量上升,写着写着就"失控"了,渐渐"丑陋接口,肮脏实现",项目维护成本和难度上升,到了难以维持的程度,只有重构或者重新开发. 第一重境界 假设场景:我们需要写一个处理类,能够同时操作会话,数据库和文件系统.我们或许会这么写. 境界特征:可以运行,但是严重耦合 class DB{ public function DB($arg1

  • k8s 中的 service 如何找到绑定的 Pod 及实现 Pod 负载均衡的方法

    目录 k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡 前言 endpoint kube-proxy userspace 模式 iptables ipvs kernelspace 服务发现 环境变量 DNS 总结 参考 k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡 前言 Service 资源主要用于为 Pod 对象提供一个固定.统一的访问接口及负载均衡的能力. service 是一组具有相同 label pod 集合的抽

  • 浅谈Spring Cloud Ribbon的原理

    Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起.Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等.简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器.我们也很容易使用Ribbon实现自定义的负载均衡算法. 说起负载均衡一般都会想到服务端的负载均衡,常用产品包括LBS硬件或云服务.Nginx等,都是

  • Windows下使用Nginx+Tomcat做负载均衡的完整步骤

    前言 今天,王子与大家闲谈一下如何在Windows下使用Nginx+Tomcat做负载均衡的完整步骤,小伙伴们可以试着自己动手实践一下哦. 另外说明一点,本篇文章是纯实操文章,不涉及太多原理的解读,后期可能单独开一个专栏来深入讨论Nginx的原理. 好了那我们直接开始. 下载Nginx 首先我们去官网下载一个Windows稳定版本的Nginx,官网地址:http://nginx.org/en/download.html 下载后解压到想要的位置,小伙伴们要注意了,千万不要把它解压到带有中文的文件夹

随机推荐