服务治理
服务治理应该是微服务架构中最核心和基础的模块,他主要用来实现各个微服务实例的自动化注册与发现。
服务注册
在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。服务注册中心还需要以心跳的方式去监测清单中的服务是否可用,如果不可用就需要从服务清单中剔除,达到排除故障服务的效果。
服务发现
Netflix Eureka
简介
SpringCloud Eureka,使用Netflix Eureka来实现服务注册与发现,它既包含了服务端组件也包含了客户端组件。
Eureka服务端 : 称之为服务注册中心,支持高可用配置。如果Eureka以集群的模式部署,当集群中有分片出现故障时,那么eureka会转入自我保护模式,它容许分片在故障期间继续提供服务的注册和发现,当故障分片恢复的时候,集群中其他分片会把他们的状态在同步过来
Eureka客户端 : 主要处理服务的注册与发现。客户端服务通过注解和参数配置的方式,
嵌入在客户端应用程序的代码中,在应用程序运行时,Eureka客户端向注册中心注册自身
提供的服务并周期性地发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注
册的服务信息并把它们缓存到本地并周期性地刷新服务状态
搭建服务注册中心
1.创建maven项目,添加pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.dyc.sprincloud</groupId> <artifactId>eureka-server-dyc</artifactId> <version>0.0.1-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project> |
编写开启类
@EnableEurekaServer //开启eureka服务端 @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class); } } |
创建配置文件application.properties
server.port=1111
eureka.instance.hostname=192.3.4.102 eureka.client.register-with-eureka=false eureka.client.fetch-registery=false eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ |
搭建高可用注册中心
用原来的eureka-server-dyc项目
1.创建文件application-peer1.properties
2.创建文件application-peer2.properties
3.window上在host配置pee1和pee2的映射
4.用原先的hello项目,修改配置文件
5.启动发现,通过192.3.4.102:1111,192.3.4.102:1112,可以观察到hello服务同时被注册到了peer1和peer2上。此时如果断开peer1,peer2也可以正常运行去访问peer2,从而实现服务中心的高可用
服务发现与消费
简介
我们现在有了服务注册中心和服务提供者,下面尝试创建一个服务消费者,他主要实现两个功能:发现服务和消费服务,其中发现服务Eureka的客户端完成,消费服务的任务由Ribbon完成。Ribbon是一个基于HTTP和TCP的客户端负载均衡器,它可以通过客户端z红配置的ribbonServerList服务端列表去轮询访问达到均衡负载的作用。
创建ribbon项目
1.创建maven项目,编写pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.dyc.springcloud</groupId> <artifactId>ribbon-consumer</artifactId> <version>0.0.1-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.7.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent>
<dependencies>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project> |
2.编写配置文件
spring.application.name=ribbon-consumer server.port=9000 eureka.client.serviceUrl.defaultZone=http\://peer1:1111/eureka/,http\://peer2:1112/eureka/
|
3.编写Ctrl类和启动类
package cn.dyc.ctrl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;
@RestController public class ConsumerCtrl { @Autowired RestTemplate restTemplate;
@RequestMapping(value="/helloConsumer",method=RequestMethod.GET) public String helloConsumer(){ //这里的url是注册中心上服务列表的服务名 return restTemplate.getForEntity("http://hello/hello", String.class).getBody(); } }
|
package cn.dyc;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient @SpringBootApplication public class ConsumerApplication {
@Bean @LoadBalanced RestTemplate resulTemplate(){ return new RestTemplate(); }
public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } } |
流程测试
项目准备好之后,把之前准备的eureka-server-dyc和hello项目都启动好,在启动ribbon项目,分别测试6次。测试结果如下:
当访问hello项目的时候log日志如下
通过之前的实例,已经简单的构建了Eureka服务治理体系中的三个核心角色:服务注册中心、服务提供者以及服务消费者
基础架构
服务注册中心 : Eureka提供的服务端,提供服务注册与发现的功能 eureka-server-dyc
服务提供者 : 服务提供者他将自己的服务注册到eureka,以供其他应用发现 hello
服务消费者 : 消费者从服务注册中心获取服务列表,从而使消费者知道去何处调用其 所需的服务 ribbon-consumer
很多时候客户端即是服务提供者也是服务消费者
Eureka实现服务治理体系是如何运转起来的,其中重要几个元素总结一下:
1.“服务注册中心-1”和“服务注册中心-2”他们互相注册组成了高可用集群
2.“服务提供者”启动了两个实例,一个注册到“服务注册中心-1”,一个注册到 “服务注册中心-2”
3.还有两个“服务消费者”,分别指向服务注册中心
配置详解
配置地址
org.springframework.cloud.netflix.eureka.EurekaClientConfigBean 服务注册类配置,查看该类可以获得比官网更详细的配置信息,这些配置都是以eureka.client为前缀
org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean 服务端配置,这些参数均以eureka.server为前缀
org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean 服务实例类配置信息,这些参数均以eureka.instance为前缀
注意事项
1.服务中心有一个自我保护机制,这个机制是会统计心跳失败的比例在15分钟之内是否低于85%,如果低于的情况下,EurekaServer会将当前的实例注册信息保护起来,让这些实例不会过期,在单机调试的时候很容易有这种关闭了服务提供者但是注册中心还有的情况,所以请关闭自我保护机制eureka.server.enable-self-preservation=false,并添加清理间隔时间为:eureka.server.eviction-interval-timer-in-ms=9000(默认为60*1000太长了,不利于单机测试或者开发),而在客户端上需要设置eureka.instance.lease-renewal-interval-in-seconds=30 # 续约更新时间间隔(默认30秒)
eureka.instance.lease-expiration-duration-in-seconds=90 # 续约到期时间(默认90秒)
eureka.client.healthcheck.enabled=true,其实以上两个配置已经可以把心跳停止的服务关掉了,但是如果你的客户端中有比如数据库,mq无法与我们的应用联通时,实际上是不能提供正常服务了,但是心跳机制还在,项目不会剔除,所以在这个时候需要加入健康机制,需要在pom文件里引入:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> |
2.获取服务是服务消费者的基础,所以必须确保eureka.client.fetch-registery=true,该值默认为true
服务注册类配置
org.springframework.cloud.netflix.eureka.EurekaClientConfigBean 查看该类可以获得比官网更详细的配置信息,这些配置都是以eureka.client为前缀
简单配置如下:
参数名 | 说明 | 默认值 |
registryFetchlntervaISeconds | 从Eureka服务端获取注册信息的间隔时间单位为秒 | 30 |
instanceInfoReplicationlntervaISeconds | 更新实例信息的变化到Eureka服务端的间隔时间,单位为秒 | 30 |
initialInstancelnfoReplicationIntervaISeconds | 初始化实例信息到Eureka服务端的间隔时间,单位为秒 | 40 |
eurekaServiceUrIPolllntervaISeconds | 轮询Eureka服务端地址更改的间隔时间,单位为秒。当我们与Spring Cloud Config配合,动态刷新Eureka的serviceURL地址时需要关注该参数 | 300
|
eurekaServerReadTimeoutSeconds | 读取Eureka Server信息的超时时间,单位为秒 | 8 |
eurekaServerC onnectTimeoutSeconds | 连接Eureka Server的超时时间,单位为秒 | 5 |
eurekaServerTotaIConnections | 从Eureka窖户端到所有Eureka服务端的连接总数 | 200 |
eurekaServerTotaIConnectionsPerHost | 从Eureka客户端到每个Eureka服务端主机的连接总数 | 50 |
eurekaConnectionIdleTimeoutSeconds | Eureka服务端连接的空闲关闭时间,单位为秒 | 30 |
heartbeatExecutorThreadPoolSize | 心跳连接池的初始化线程数 | 2 |
heartbeatExecutorExponentiaIBackOffBound | 心跳超时重试延迟时间的最大乘数值 | 10 |
cacheRefreshExecutorThreadPooISize | 缓存刷新线程池的初始化线程数 | 2 |
cacheRefreshExecutorExponentialBackOffBound | 缓存刷新重试延迟时间的最大乘数值 | 10 |
useDnsForFetchingServiceUrls | 使用DNS来获取Eureka服务端的serviceUrl | false |
registerWithEureka | 是否要将自身的实例信息注册到Eureka服务端 | true |
preferSameZoneEureka | 是否偏好使用处于相向Zone的Eureka服务端 | true |
filterOnlyUplnstances | 获取实例时是否过滤,仅保留UP状态的实例 | true |
fetchRegistry | 是否从Eureka服务端获取注册信息 | true |
enabled | 启用Eureka客户端 | true |
服务实例类配置
关于服务实例类的配置信息,我们可以通过查看org. springframework.cloud.
netflix.eureka .EurekaInstanceConfigBean的源码来获取详细内容,这些配置
信息都以eureka.instance为前缀,下面我们针对一些常用的配置信息做一些详细的说
简单配置如下:
参数名 | 说明 | 默认值 |
preferIpAddress | 是否优先使用lP地址作为主机名的标识 | false |
leaseRenewallntervallnSeconds | Eureka客户端向服务端发送心跳的时间间隔,单位为秒 | 30 |
leaseExpirationDurationlnSeconds | Eureka服务端在收到最后一次心跳之后等待的时间上限单位为秒。超过该时间之后服务端会将该服务实例从服务清单中剔除,从而禁止服务调用请求被发送到该实例上 | 90 |
nonSecurePort | 非安全的通信端口号 | 80 |
securePort | 安全的通信端口号 | 443 |
nonSecurePortEnabled | 是否启用非安全的通信端口号 | true |
securePortEnabled | 是否启用安全的通信端口号 |
|
appname | 服务名,默认取spring.application.name的配置值如果没有则为unknown |
|
hostname | 主机名,不配置的时候将根据操作系统的主机名来获取 |
|
|
|
|
在上面的这些配置中,除了前三个配置参数在需要的时候可以做一些调整,其他的参
数配置大多数情况下不需要进行配置,使用默认值即呵。