服务发现的深入研究,不谈理念谈干货

服务发现是怎么“火”起来的

我们知道,在写代码的时候,为了完成服务请求的时候,代码需要知道服务实例的IP地址和端口。所以说,服务发现,发现的是服务实例的IP地址和端口。

那么,为什么服务发现这两年比较火呢?

在小型机和X86虚拟化时代,应用运行在VM或者小型机上,其应用的IP地址和端口相对固定,很少变化。为为了预防可能发生的变化,代码可以从应用的配置文件中读取IP地址和端口。

例如,HAproxy的配置文件,将HAproxy的后端设置为Mysql集群

那么,问题来了,在虚拟机、物理机和小型机里,应用的IP相对是固定的。即使应用被重启甚至破坏,应用重建配置的时候,读取的还是配置文件中的内容,IP是不发生变化的。

但是,在以容器为基础的微服务时代,应用运行的载体是容器。一个pod有业务IP和Service IP。Server IP负责不同Service之间的Pod通讯、东西向流量。Pod自身的IP负责南北向流量(在Openshift中),Routing Layer将应用的FQDN映射到Pod的IP。

而如果一个pod被破坏,发生pod重建,其IP会发生变更。

两个pod的初始IP:

删除pod,自动重建:

pod重建后的IP:

我们发现,IP已经发生了变化。

因此,在以容器为载体的微服务时代,用写配置文件的方法获取IP和端口,显然不太现实。

因此,需要引入服务发现的机制:

服务发现的方式

服务发现的两种实现方式分别是:客户端发现和服务器端发现。

1.客户端发现

当使用客户端发现模式时,客户端负责决定相应服务实例的网络位置,并且对请求实现负载均衡。客户端从一个服务注册服务中查询,其中是所有可用服务实例的库。客户端使用负载均衡算法从多个服务实例中选择出一个,然后发出请求。

服务实例的网络位置是在启动时注册到服务注册表中,并且在服务终止时从注册表中删除。服务实例注册信息一般是使用心跳机制来定期刷新的。

如下图,Service Instance A在启动的时候,将自己的IP和端口自动注册到Service Registry(服务注册表)中。当Service Instance A想要访问其他Service实例的时候(如Service Instance B),首先将会去Service Registry其查询,在获取到IP地址和端口号以后,就可以进行访问了。

非常著名的一种客户端服务端服务发现模式是Netflix OSS。其中,Netflix Eureka是服务注册表,为服务实例注册管理和查询可用实例提供了RESTAPI接口。Netflix Ribbon是一种IPC客户端,与Eureka合同工作实现对请求的负载均衡。

客户端发现的好处比较明显,简单直接。缺点是需要针对不同的编程语言注册不同的服务,在客户端需要为每种语言开发不同的服务发现逻辑(在微服务框架中,这是不现实的。因为每个微服务的编程语言都可能不同)。 2.服务端发现模式

客户端通过负载均衡器向某个服务提出请求,负载均衡器向服务注册表发出请求,将每个请求转发往可用的服务实例。跟客户端发现一样,服务实例在服务注册表中注册或者注销。

最大的优点是客户端无需关注发现的细节,客户端只需要简单的向负载均衡器发送请求,实际上减少了编程语言框架需要完成的发现逻辑()。 这种模式也有缺陷,除非部署环境提供负载均衡器,否则负载均衡器是另外一个需要配置管理的高可用系统功能(etcd本身自带负载均衡功能)。

服务注册表

服务注册表是服务发现很重要的部分,它是包含服务实例网络地址的数据库。服务注册表需要高可用而且随时更新。客户端可以缓存从服务注册表获得的网络地址。

上文已经提到,Netflix OSS是用Eureka做服务注册表,除此之外,还有几种常用的服务注册表:

etcd – 是一个高可用,分布式的,一致性的,键值表,用于共享配置和服务发现。

consul– 是一个用于发现和配置的服务。提供了一个API允许客户端注册和发现服务。Consul可以用于健康检查来判断服务可用性。

Apache ZooKeeper – 是一个广泛使用,为分布式应用提供高性能整合的服务。

上表中:

关于一致性:Paxos和Raft都是为了实现Consensus一致性这个目标,这个过程如同选举一样,参选者需要说服大多数选民(服务器)投票给他,一旦选定后就跟随其操作。Paxos和Raft的区别在于选举的具体过程不同。

在之前,Paxos一直是分布式协议的标准,但是Paxos难于理解,更难以实现。而斯坦福大学提出的新的分布式协议研究称为Raft。

关于CAP:CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性;分区相当于对通信的时限要求),三者不可得兼得。

所以,整体上看,服务注册表各有各的优势。从实际落地的微服务案例看,笔者接触到较多的是etcd和Consul。

服务注册

介绍了服务发现以后,接下来我们看看服务注册。

服务实例必须向注册表(如etcd、Consul、Eureka)中注册和注销,那么,服务实例究竟如何注册到服务注册表呢?有两种方法:

1.服务实例自己注册,也叫自注册模式(self-registration pattern)

当使用自注册模式时,服务实例负责在服务注册表中注册和注销。也就是说,各个服务实例,自己负责自己的注册。

另外,如果需要的话,一个服务实例也要发送心跳来保证注册信息不会过时。下图描述了这种架构:

自注册模式也有优缺点。一个优点是,相对简单,不需要其他系统功能。而一个主要缺点则是,把服务实例跟服务注册表联系起来。必须在每种编程语言和框架内部实现注册代码。

2.第三方注册模式(third party registration pattern)

当使用第三方注册模式时,服务实例并不负责向服务注册表注册,而是由另外一个系统模块,叫做服务管理器,负责注册。服务管理器通过查询部署环境或订阅事件来跟踪运行服务的改变。当管理器发现一个新可用服务,会向注册表注册此服务。服务管理器也负责注销终止的服务实例。下图是这种模式的架构图。

第三方注册模式优点是服务跟服务注册表是分离的,不需要为每种编程语言和架构完成服务注册逻辑,服务实例是通过一个集中化管理的服务进行管理的(etcd和Consul都是服务管理器)。 缺点是,需要保证服务管理器的高可用(OCP中可以配置etcd集群,也可以创建容器化的etcd,通过rc来保证其高可用,不过这个功能目前属于技术预览)。

Openshift的服务发现和服务注册

Openshift使用的服务发现和服务注册是etcd。也就是说,Openshift的服务发现使用的是etcd,服务发现方面:它是服务端的发现模式、服务注册方面:它是属于第三方注册模式。再简单点说,etcd在OCP中,既当服务注册表,又当服务管理器。

一个 etcd 节点的核心由三部分组成:

  • Raft:raft 状态机是对 raft 共识算法的实现
  • WAL:raft 日志存储
  • Storage:数据的存储与索引

在默认设定下,etcd 通过主机的 2379 端口向 Client 提供服务。如下图:

每个主机上的应用程序都可以通过主机的 2379 以 HTTP + JSON 的方式向 etcd 读写数据。写入的数据会由 etcd 同步到集群的其它节点中。

在默认设定下,etcd 通过主机的 2380 端口在各个etcd节点中同步 raft 状态及数据(笔者实验环境只有一个etcd节点,因此不需要多个etcd节点之间的通讯和数据同步)。

etcd的功能,就是下图Master上,做Data store的角色。

在Openshift最新的版本V3.6中,使用的是etcd3 v3 data model。

引入etcd3 v3,对openshift带来的好处有:

  • Larger memory space to enable larger cluster sizes(更大内存空间使OCP集群可以更大).
  • Increased stability in adding and removing nodes in general life cycle actions.(在为OCP增加或者删除节点的时候,整个OCP集群稳定性更好)
  • A significant performance boost(性能更强).

在Openshift中,etcd可以安装在Master节点上,也可以安装在单独的服务器上。

在笔者OCP3.6的实验环境中,etcd是作为程序安装在master节点上的。etcd的版本是3.1.7:

查看etcd的进程:

我们可以看到:

--listen-client-urls=https://192.168.137.10:2379,

其中,192.168.137.10是master节点的IP。也就是说etcd server通过绑定到master节点的2379端口。

etcd支持http RESTful API,支持get查询,post,delete,put等操作。为了便于理解,可将它存储数据的框架看做一个文件系统,可以创建目录和“文件”,每个“文件”名就是一个key,每个“文件”的内容就是它的value,目录没有value只能包含子目录或者“文件”,可以通过RESTful API来获取这些key的值或者设置这些key的值。

查看etcd集群的成员:

查看etcd集群的健康状态:

输出结果:

在etcd数据库中创建一个名为china1003的用户,密码为china1003:

查看创建的用户,创建成功:

目前,etcd以容器的方式安装在OCP3.6中是技术预览的阶段。目前已经有etcd for OCP的docker image了:

通过这个镜像,可以在OCP中以容器的方式部署etcd:

镜像搜索成功:

点击创建。过一会,容器化的etcd创建成功:

我们登录到etcd的容器,查看容器化etcd的成员,查看到10.129.0.42。

实际上这个IP就是etcd的pod IP:

参考链接

http://dockone.io/article/394

http://luyiisme.github.io/2017/04/22/spring-cloud-service-discovery-products/

http://www.jdon.com/artichect/raft.html

http://blog.csdn.net/zzhou1990/article/details/72667659

https://github.com/openshift/origin/tree/master/examples/etcd

http://blog.csdn.net/u010424605/article/details/44592533

http://www.infoq.com/cn/articles/coreos-analyse-etcd

原文发布于微信公众号 - 大魏分享(david-share)

原文发表时间:2017-10-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏运维技术迷

HP DL380服务器配置iLO2

由于BIOS开机密码忘记,所以对这台HP DL380 G6服务器进行BIOS清除操作,刚好看到iLO的选项,就顺手配置了一下,方便以后的管理。 首先,先说明一下...

622120
来自专栏大魏分享(微信公众号:david-share)

高端黑科技系列一:新一代微服务与新一代API管理的集成

版权说明:本文书写过程中参照了红帽的技术文档;本系列文章中的部分测试代码为红帽公司版权所有,因此不能提供源码文件。

20930
来自专栏大魏分享(微信公众号:david-share)

详细描述微服务架构模式 | 微服务系列第三篇

虽然微服务通常是单独部署的,但大多数企业级微服务架构要求服务彼此交互以及与其他外部服务交互。 使用进程间通信(IPC)机制实现该通信。 根据应用程序的要求,微服...

10220
来自专栏数据和云

快速掌握:大型分布式系统中的缓存架构

CDN(Content Delivery Network 内容分发网络)的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中...

10630
来自专栏JAVA高级架构

程序猿的日常——SpringMVC系统架构与流程回顾

web开发经历了很漫长的时间,在国内也快有十几年的时间了。从最开始的进程级到现在的MVC经历了很多的改进和优化,本篇就主要复习了解下Spring MVC相关的知...

36450
来自专栏24k

SpringBoot项目使用JRebel热部署

25240
来自专栏张首富-小白的成长历程

CentOS系统优化脚本,未完结

sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

22620
来自专栏Java技术栈

SpringCloud Eureka自我保护机制

自我保护背景 首先对Eureka注册中心需要了解的是Eureka各个节点都是平等的,没有ZK中角色的概念, 即使N-1个节点挂掉也不会影响其他节点的正常运行。...

413100
来自专栏日常分享

Java Web Action DAO Service层次理解

参考来源:http://blog.csdn.net/inter_peng/article/details/41021727

23720
来自专栏Ryan Miao

Linux文件属性,权限和修改文件权限,所属者和所属组

剩下的三组主要由[rwx]组成,r-read, w-write, x-execute, [-]表示占位符,即没权限。

12430

扫码关注云+社区

领取腾讯云代金券