服务治理
服务的治理可以说是微服务架构种最为核心和基础的模块,他主要用来各个微服务的自动化注册与发现。那么问题来了,我们为什么需要服务治理模块,没有这个模块会有什么不好的地方?
最开始构建微服务系统的时候,可能服务并不多,可以做一些静态配置来完成服务的调用,例如:有两个服务A,B。其中A服务需要调用B服务来完成一个业务逻辑。为了实现B服务的高可用,则需要采取客户端或者服务端负载均衡,但是都要手动维护服务B的具体实例列表。但是随着业务不断的发展,系统功能越来越复杂,对应的服务应用越来越多,手动静态配置变的越来越难维护了。并且搭建的集群规模,服务位置,服务命名等都可能发生变化,这时候的手动维护就非常容易发生错误或者命名冲突等问题,同时我感觉维护的人面对大片大片的配置估计也得喝一壶了。因此为了解决微服务架构中的这些问题
服务注册
在服务治理框架中,通常都会构建一个注册中心没给服务向注册中心登记自己提供的服务。当这些服务均启动,并注册后,注册中心就会维护如下清单:
服务名 | 位置 |
---|---|
服务A | 192.168.100:8080,192.168.101:8080 |
服务B | 192.168.100:8081,192.168.101:8081,192.168.102:8081 |
注册中心还需要以心跳的方式去检测清单中的服务,是否运行正常,如果某个服务挂了,那么将会从清单种剔除,达到排除故障的效果。
服务发现
微服务在服务治理框架中运行,各个服务中的调用将不以具体服务地址来实现,而是通过服务名去注册中心取对应的服务地址再调用,所以服务调用方并不知道服务提供方的实际地址。例如:如上有两个服务,现在服务A要调用服务B,那么首先服务A将从注册中心获取服务B的位置清单。上面三个地址可用,那么这时候便从清单中通过某种策略的轮询算法取出一个位置,提供给服务A调用,这就是后面的负载均衡。当然实际中服务调用并不会每次都向注册中心请求地址,而是不同应用场景在缓存和服务剔除等机制上有不同的实现策略。
体验
好的! 理论知识吠了这么多,接下来动手操作一番吧!我们接下来使用IDEA进行操作。
搭建服务注册中心
- new 一个Springboot项目,修改包名,单独勾选如下项目。好下一步
- 修改配置文件
#提供服务端口1111
server.port=1111
#提供服务的域名,这里在hosts文件中修改了
eureka.instance.hostname=peer1
#不向注册中心注册自己
eureka.client.register-with-eureka=false
#由于单注册中心的职责就是维护服务,所以也不需要去检索服务false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
- 再启动类上加入EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaClient1Application {
public static void main(String[] args) {
SpringApplication.run(EurekaClient1Application.class, args);
}
}
-
启动完事收工
浏览器输入:http://peer1:1111/ 就得到如下结果,那么就ok了,就是如此easy。
搭建服务提供者
- 新建项目,勾选Eureka Discovery 和web模块(用于测试)
- 启动类加上@EnableEurekaClient注解
- 配置文件修改
# 设置服务名
spring:
application:
name: hello-service
# 设置注册中心地址
eureka:
client:
service-url:
defaultZone: http://peer1:1111/eureka
- 启动项目 完工
搭建高可用服务注册中心
WX20180919-093707@2x.png什么是高可用?
高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。
假设系统一直能够提供服务,我们说系统的可用性是100%。
如果系统每运行100个时间单位,会有1个时间单位无法提供服务,我们说系统的可用性是99%。很
多公司的高可用目标是4个9,也就是99.99%,这就意味着,系统的年停机时间为8.76个小时。
百度的搜索首页,是业内公认高可用保障非常出色的系统,甚至人们会通过www.baidu.com
能不能访问来判断“网络的连通性”,百度高可用的服务让人留下啦“网络通畅,百度就能访问”,“
百度打不开,应该是网络连不上”的印象,这其实是对百度HA最高的褒奖。
那么下面我们将搭建一个高可用服务注册中心。使用两个eureka相互注册。
由于我们是在本地搭建所以我们定义两个域名分别代表两个Eureka
定义了两个域名,当然由于是单机搭建,所以我们得配置本地host文件做转发了。添加如下配置
127.0.0.1 peer1
127.0.0.1 peer2
接下来我们使用上面我们创建好的Eureka server来搭建。
添加两个配置文件
- application-peer1.properties
#应用名
spring.application.name=eureka-server
#提供服务端口1111
server.port=1111
#提供服务的域名,这里在hosts文件中修改了
eureka.instance.hostname=peer1
#向第二个注册中心注册自己
eureka.client.service-url.defaultZone=http://peer2:1112/eureka/
- application-peer2.properties
#应用名称与第一个注册中心一样
spring.application.name=eureka-server
#提供服务端口1112
server.port=1112
#提供服务的域名,这里在hosts文件中修改了
eureka.instance.hostname=peer2
#向第一个注册中心注册自己
eureka.client.service-url.defaultZone=http://peer1:1111/eureka/
打包
使用IDEA打包出jar包
3FCD1B75-2E63-4860-89AF-FC977D03249F.png
打出包以后在如下地址,然后就使用两个命令行界面进入target目录,分别运行如下命令
java -jar eureka-server-peer1-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar eureka-server-peer1-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
结果
310B2BD8-8567-4E16-AA1E-7A50548FEDCE.png浏览器输入http://peer1:1111/ 看到如下界面,那么我们的高可用eureka就搭建成功了,我们将上上面的EurekaClient跑起来,其注册到其中一个注册中心,然后去另外一个注册中心查看,发现服务依然在线。
详解
基础架构
我们上面举例的demo虽然非常简单,但是麻雀虽小,但五脏六腑俱全。上已经包含了整个Eureka服务治理基础架构的三个核心要素
- 服务注册中心
- 服务提供者
- 服务消费者
服务提供者
- 服务注册
服务提供者再启动的时候会发送REST请求将自己注册到Eureka Server,Eureka Server接受到请求后,将元数据保存在一个双层Map中,第一层的Key是服务名,第二层Key是具体服务的实例名。
- 服务同步
再使用高可用的注册中心时候,两个服务分别注册到不同的两个注册中心上,当调用者发送调用请求到一个注册中心,由于集群中的注册中心服务同步,那么调用者也能获取到被调用者的实际信息。
- 服务续约
当注册服务完成后,服务提供者会维护一个心跳来持续告诉注册中心(Eureka Server)“我还在线”,防止被剔除任务
服务消费者
- 获取服务
服务消费者会发送一个Rest请求给我服务注册中心。Eureka Server 会维护一份只读的服务清单来返回给客户端,同时该清单会30S更新一下(可以配置)。
- 服务调用
服务消费者获取服务清单后,通过服务名可以获取对于服务的元数据信息。消费者可以根据自己的需求选择具体调用哪个实例,在Ribbon中会默认采用轮询的方式进行调用,从而实现客户端负载均衡。
- 服务下线
再系统的运行过程中必然会关闭或者重启某个服务。再服务关闭期间,它会出发一个Rest请求给Eureka Server,告诉注册中心“我要下线”。注册中心接受到了,于是把服务状态设置微DOWN,并把事件传播出去。
服务注册中心
- 失效剔除
在系统的运行过程中并不少一帆风顺,时常会碰到一些问题比如内存溢出,网络故障导致服务无法正常运行,而注册中心并没有收到下线请求。这时候Eureka Server再启动的时候会创建一个定时任务,每隔一段事件(默认60S)将当前清单中超时(默认90s)没有续约的服务剔除。
- 自我保护
当我们本地运行eureka的时候经常会碰到如下问题:
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
实际上这警告就是触发了Eureka Server的自我保护机制。上面介绍到,服务注册到Eureka Server上后会维持一个心跳连接。那么再运行期间会统计心跳失败比例再15分钟内是否低于百分之85%,如果低于(单机测试的时候很容易满足,生产环境下通常上因为网络不稳定),这时候Eureka Server会将当前的实例注册信息保护起来,让这些信息不会过期,尽可能的保护这些注册信息。但是保护起来了以后,如果实例真的出了问题,那么客户端拿到的实例不存在了,就调用失败了,所以客户端必须要有容错机制,比如请求重试,断路器等。
网友评论