微服务探索与实践—服务注册与发现

前言

微服务从大规模使用到如今已经有不少年了,从以前的探索到一步步的不断完善与成熟,微服务已经成为众多架构选择中所必须面对的一个选项。服务注册与发现是相辅相成的,因此通常会合起来思索。其依托组件有不少,好比Zookeeper,Consul,Eureka等等。程序员

本文,咱们将探讨服务注册和发现的概念及其使用机制,以使得微服务可以在不知道其确切位置(一般是URL)的状况下消费其余服务。因为本文主要是我的实践的一些总结,总会有不足之处,也但愿各位看官帮忙完善。本系列前一篇文章请移步总述面试

服务注册与发现探讨

为何须要

服务是在具备单独部署周期的不一样计算机上运行的单个或较小的代码库,可明确解决相关的问题域。不正确的服务设计可能致使重复的服务建立,同时也没法进行架构层面的复用。sql

若是没有服务注册与服务发现,那么服务的位置将会耦合到消费者服务里面,最终将会致使整个系统的架构变得死板而又难以维护。事实上,在比较简单的系统架构里,采用静态配置的方式是很是简单而又效果显著的,毕竟全部服务都在同一位置,并且不多发生变动。数据库

而在微服务里,其目标之一就是使系统可以独立开发、部署及升级扩展,随着系统的进一步复杂,服务位置也发生变动,那么静态配置就会变得十分鸡肋,此时咱们须要变动咱们的策略,那就是在消费其余服务的时候采用静态配置。那么核心问题就来了,服务是如何发现它们索要消费的服务的IP地址和端口号的?既是动态配置,在多实例场景下,配置在专门的系统里是最好的选择,ZK和Consul等也就应运而生。缓存

简单的通讯流程

咱们来看一下一个简单的服务通讯流程服务器

透过这张图,咱们能够知道,服务调用时,无需知道目标服务的真实地址,只须要知道服务Key,而后到服务发现系统里获取对应的地址便可。架构

这张图虽然比较简单,可是传递的信息却有不少:并发

  • 服务如何肯定自身的IP地址及端口?
  • 在消费方拿到被消费方的地址之后,应采用何种方式调用?
  • 咱们如何添加新服务并删除已弃用的服务?
  • 若是服务在运行过程当中出现问题,如何快速发现并提早通知?
  • 做为集中化管理的服务注册与发现中心挂了,咋整?

服务信息注册

通常能够建立服务注册表,该服务注册表是服务及其实例及其位置的数据库。服务实例在启动时注册到服务注册表,并在关闭时注销。客户端查询服务注册表以查找服务的可用实例。服务注册表可能会调用服务实例的运行情况检查API来验证它是否可以处理请求。咱们已经有了现成的工具,就是Consul等,那么咱们的关注点就是服务地址的注册了。负载均衡

最简单的解决方案就是手动配置。咱们思考一个问题,若是咱们须要对该服务进行水平扩展,再增长一个实例的时候,仍然须要咱们手动配置,可是咱们已经不想手动配置了,在DevOps时代,再使用手动配置,就显得不那么专业了,并且人工的介入,也增长了系统运维的成本与风险。运维

因此咱们选择,自动获取本机IP地址,可是这里有一个问题,也是我在实际运用中遇到的问题就是本地会有多个网卡的状况,这是比较麻烦的,因此那时候我建议每台机器只配置一个网卡,以减小不肯定性,可是后来,遇到一个新的问题就是,当我想在服务器上安装代理,以获取请求包信息的时候,容易改变系统的运行环境,依然存在着不肯定性。后来我在网上查看是否其余方案的时候,始终没有一个比较好的解决方案,后来有人说,直接往服务注册中心发送一个Socket链接就能够了,经过Socket实例获取本机IP,网上也有人介绍这种方案。

至于端口获取,相对简单一点,咱们使用的就是直接配置在服务里。

服务注册自己就是要在有限人力干预的状况下,支持不一样应用之间的运行与交互。

服务注册扩展至之其余信息的注册

这个地方更多的是考虑服务消费方的负载均衡策略、调用策略以及容错的可配置性。

在被消费方作了集群部署的时候,这就是要求咱们根据实际运行状况及时调整对服务的调用,那么该如何判断呢?在实现上能够考虑权重参数,该参数的设置应该来源于自身以及服务治理系统。

来源于自身,是由于咱们的服务可能部署在相对较差的机器上或者该服务自己只是一个备用系统,不该该承载过大的流量。

来源于服务治理系统,是由于在实际运行中,可能该系统已经出现问题,或者须要暂时下线,咱们能够设置权重系数为0,以从消费服务自己来中止对该服务的调用。

权重参数只是其中一个,也是最容易想到和实现的一个,固然还有其余参数,只要是为了更好的优化服务间的调用,那么就能够注册进去,同时实现相应的调用策略。好比版本号,TTL等等。

一旦信息多了,就须要考虑如何及时获取变动,以调整调用策略。

服务发现

服务发现能够分为客户端发现或服务器端发现来肯定要向其发送请求的服务实例的位置。客户端发现比较简单一些,直接向服务发现中心获取所需的被消费者服务的信息。而服务端发现相对来讲,比较复杂,须要建立一个路由中心,由路由中心去发现被消费者的请求。咱们这边用的比较多的是客户端发现。

确保发现的稳定性,首先就要确保服务注册中心的稳定性,其地址不该该频繁发生变化,因此咱们能够在服务中配置咱们的服务注册中的地址。此处须要多说明一下,就是做为服务注册中心系统,必定要保持高可用性,能够经过集群以及负载均衡来加强可用性。

服务实例的数量及其位置是动态变化的。一般为虚拟机和容器分配动态IP地址。最复杂的问题天然是如何及时得到被消费者服务变化后的地址?咱们能够建立一个路由功能,用户能够客户端查询服务注册中心以查找服务的可用实例。服务注册中心可能会调用服务实例的运行情况检查API来验证它是否可以处理请求。

咱们在系统启动的时候,会作个Reload,以加载最新信息。那么以后如何及时获取最新信息呢?一般状况下有两种,主动轮询和获取推送消息。

主动轮询带有随机性,若是偏偏好,可能会很及时,大多数状况下,可能没那么偏偏好,并且还要增长服务发现中心的负载压力。

推送方式在效果上可能更好一些,在具体实现上可能没有那么简单。

健康检查

通常而言,健康检查包括,客户端心跳和服务端主动探测两种方式,

首先来讲,客户端心跳,就是客户端经过TCP或者HTTP的方式,告诉服务端自身的运行状况,固然客户端通知是有弊端的,好比客户端在某一时间点出现故障时,没法及时通知服务端,过后恢复运行后,告知的也只是当前的运行状态,即使这时再告诉服务端以前的运行情况,也对服务调用没有什么太大意义了,只是对服务自己的运行分析起到了必定做用。即使是保持正常链接的状况下,服务也未必是能够调用的,好比数据库挂掉。

通常而言,采用服务端探测的比较多一些,调用方式和客户端心跳差很少,可是仍然须要咱们注意的是,客户端所提供的探测接口必须具备通用性,好比能够查一下次数据库等等,这样能够比较全面的反应系统的运行状况。

容灾与故障转移

容灾的缘由有不少,好比服务再也不使用、双11大流量的涌进,使得其中一些服务不可用,也就不得不针对性的对一些服务进行容灾处理,以集中资源给核心应用。在容灾过程当中,能够给服务下线功能能够制定一些策略,以丰富功能的使用。.NET Core里面可使用IApplicationLifetime来显示下线功能。固然也须要提供手动下线的接口。

容灾主要考虑方向是客户端容灾和服务端容灾。客户端容灾中,若是服务注册中心挂掉了,恢复运行可能须要一段时间,在这个过程当中若是保证服务正常运行。在实际运行中很是有可能发生这种状况,咱们能够将服务发现中心获取的信息缓存起来,缓存方式有不少,无外乎是本地内存、文件以及外部存储,本地内存还要还要考虑该服务重启过程当中的数据丢失,因此可选的方式就有内存+文件方式。反之,为了达到容灾的要求,咱们能够在获取服务发现中心返回的数据的过程当中将数据存在到内存和文件中,能够采用异步方式存储。

以下图所示,在发现过程当中,使用缓存功能,若是缓存都失效了,那就真的要game over一阵子了。

服务端容灾,就比较简单了,由于如今大多数作的都是服务端容灾,好比集群等水平扩展方式, 可主动从其余节点同步相应的数据,也可等待master的同步。

总结

服务注册与发如今服务生命周期中发挥着重要做用。动态的服务注册和发现变得很是重要,它能够避免服务中断。在处理服务实例的容灾与故障转移时,尽可能实现自动转移,并提供手动方式处理,而对于跨服务调用,尤为是该服务拥有多实例服务的时候,须要考虑负载平衡。

读者福利

分享免费学习资料

针对于Java程序员,我这边准备免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)

为何某些人会一直比你优秀,是由于他自己就很优秀还一直在持续努力变得更优秀,而你是否是还在知足于现状心里在窃喜!但愿读到这的您能点个小赞和关注下我,之后还会更新技术干货,谢谢您的支持!

资料领取方式:加入Java技术交流群963944895点击加入群聊,私信管理员便可免费领取

如何成为一个有逼格的Java架构师

怎么提升代码质量?——来自阿里P8架构师的研发经验总结

阿里P8分享Java架构师的学习路线,第六点尤其重要

每一个Java开发者应该知道的八个工具

想面试Java架构师?这些最基本的东西你都会了吗?

画个图来找你的核心竞争力,变中年危机为加油站

哪有什么中年危机,不过是把定目标当成了有计划

被裁人不是寒冬重点,重点是怎么破解职业瓶颈

相关文章
相关标签/搜索