前言
所谓服务治理,就是管理服务之间相互依赖调用的混乱。
没有注册中心前,服务之间调用其实是通过配置文件指定需要访问服务的ip、端口等访问信息的,
这样一旦被调用方地址信息发生变化,调用者需及时修改其配置,再重新发布,流程繁琐。
有了注册中心后,服务启动的时候将自己的地址信息以别名的方式注册至注册中心上,想要调用其他服务时,通过
别名的方式去注册中心找到对应的值(地址是支持集群的),进行调用即可
springcloud支持多种注册中心,常用的有eureka,zookeeper和consul
euraka作为注册中心
服务注册
消费者启动的时候,使用服务别名,会发送一个rest请求到服务注册中心获取对应的服务信息,让后会缓存到本地jvm客户端中,
同时客户端每隔30秒从服务器上更新一次。可以通过 fetch-inte vall-seconds=30参数进行修以通过
eureka.client.registry该参数默认值为30, 单位为秒。
服务下线
在系统运行过程中必然会面临关闭或重启服务的某个实例的情况,在服务关闭期有我们自然不希望客户端会继续调用关闭了的实例。
所以在客户端程序中,当服务实例过正常的关闭操作时,它会触发一个服务下线的REST请求给Eureka Server, 告诉服务中心:
“我要下线了”。服务端在接收到请求之后,将该服务状态置为下线(DOWN),井该下线事件传播出去。
失效剔除
有些时候,我们的服务实例并不一定会正常下线,可能由于内存溢出、网络故障气因使得服务不能正常工作,而服务注册中心
并未收到“服务下线”的请求。为了从服务表中将这些无法提供服务的实例剔除,Eureka Server 在启动的时候会创建一个
定时任多默认每隔一一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务除出去
自我保护
服务注册到Eureka Server之后,会维护个心跳连接, 告诉Eureka Server自己还活着。Eureka Server在运行期间,会统计心跳
失败的比例在15分钟之内是否低于85%(如果出现低于的情况单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定
导致),EuServer会将当前的实例注册信息保护起来,让这些实例不会过期,尽可能保护这些注册信息。但是,在这段保护期间内
实例若出现问题,那么客户端很容易拿到实际已经不存服务实例,会出现调用失败的情况,所以客户端必须要有容错机制,比如可以
使用请使用重试、断路器等机制。
###服务端口号
server:
port: 8100
##定义服务名称
spring:
application:
name: yanxiaohui-order-service
eureka:
instance:
###注册中心ip地址
hostname: 127.0.0.1
client:
serviceUrl:
##注册地址
defaultZone: http://${eureka.instance.hostname}:8100/eureka/
####因为自己是注册中心,是否需要将自己注册给自己的注册中心(集群的时候是需要是为true)
register-with-eureka: false
###因为自己是注册中心, 不需要去检索服务信息
fetch-registry: false
server:
# 测试时关闭自我保护机制,保证不可用服务及时踢出
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000
核心配置
server:
# 测试时关闭自我保护机制,保证不可用服务及时踢出
enable-self-preservation: false
##剔除失效服务间隔
eviction-interval-timer-in-ms: 2000
maven
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--SpringCloud eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
配置文件application.yml
###服务端口号
server:
port: 8100
###eureka 基本信息配置
eureka:
instance:
###注册到eurekaip地址
hostname: 127.0.0.1
client:
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
###因为自己是为注册中心,不需要自己注册自己
register-with-eureka: false
###因为自己是为注册中心,不需要检索服务
fetch-registry: false
启动Eureka服务
@EnableEurekaServer
@SpringBootApplication
public class AppEureka {
public static void main(String[] args) {
SpringApplication.run(AppEureka.class, args);
}
}
微服务注册
maven
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot整合eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
配置文件application.yml
###服务启动端口号
server:
port: 8000
###服务名称(服务注册到eureka名称)
spring:
application:
name: yanxiaohui-order-service
###服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka
###因为该应用为注册中心,不会注册自己
register-with-eureka: true
###是否需要从eureka上获取注册信息
fetch-registry: true
registry-fetch-interval-seconds: 30
# 心跳检测检测与续约时间
# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
instance:
###Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)
lease-renewal-interval-in-seconds: 1
####Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)
lease-expiration-duration-in-seconds: 2
服务接口
@RestController
public class OrderController {
@RequestMapping("/index")
public String index() {
return "微服务订单接口首页";
}
}
微服务注册
@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApp {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApp.class, args);
}
}
同理,将用户服务也注册至eureka
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/getOrder")
public String getOrder() {
// order 使用rpc 远程调用技术 调用 订单服务
String url = "http://yanxiaohui-order-service/index";
String result = restTemplate.getForObject(url, String.class);
System.out.println("result:" + result);
return result;
}
}
@SpringBootApplication
@EnableEurekaClient
public class UserrServiceApp {
public static void main(String[] args) {
SpringApplication.run(UserrServiceApp.class, args);
}
@Bean
@LoadBalanced // 以别名方式从注册中心获取对应服务地址列表(可实现本地负载均衡)
RestTemplate restTemplate() {
return new RestTemplate();
}
}
eureka高可用原理
Eureka高可用实际上将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组相互注册的服务注册
中心,从而实现服务清单的互相同步,达到高可用效果。
Eureka集群环境搭建
-------------------------------eureka1配置信息---------------------------------
###服务端口号
server:
port: 8100
###eureka 基本信息配置
spring:
application:
name: eureka-server
eureka:
instance:
###注册到eurekaip地址
hostname: 127.0.0.1
client:
serviceUrl:
defaultZone: http://127.0.0.1:8200/eureka/
###因为自己是为注册中心,不需要自己注册自己
register-with-eureka: true
###因为自己是为注册中心,不需要检索服务
fetch-registry: true
-------------------------------eureka2配置信息-------------------------------
###服务端口号
server:
port: 8200
###eureka 基本信息配置
spring:
application:
name: eureka-server
eureka:
instance:
###注册到eurekaip地址
hostname: 127.0.0.1
client:
serviceUrl:
defaultZone: http://127.0.0.1:8100/eureka/
###因为自己是为注册中心,不需要自己注册自己
register-with-eureka: true
###因为自己是为注册中心,不需要检索服务
fetch-registry: true
-------------------------------客户端集成Eureka集群-------------------------------
server:
port: 8000
spring:
application:
name: yanxiaohui-order-service
###集群地址
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka,http://localhost:8200/eureka
register-with-eureka: true
fetch-registry: true
Consul用作注册中心
Consul环境搭建
官方下载地址下载window版,解压得到一个可执行文件。 (https://www.consul.io/downloads.html)
设置环境变量,让我们直接在cmd里可直接使用consul使命。在path后面添加consul所在目录
例如D:\consul_1.1.0_windows_amd64
启动consul命
consul agent -dev -ui -node=cy
-dev开发服务器模式启动,-node结点名为cy,-ui可以用界面访问,默认能访问。
测试访问地址:http://localhost:8500
客户端注册
maven
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringCloud consul-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
配置文件
###eureka 服务端口号
server:
port: 8502
spring:
application:
name: consul-order
####consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
hostname: 192.168.1.240
DiscoveryClient用法
@SpringBootApplication
@EnableDiscoveryClient
// @EnableDiscoveryClient 开启其他注册中心 比如consul、zookeeper
public class OrderServiceApp {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApp.class, args);
}
}
// discoveryClient接口 可以获取注册中心上的实例信息。
@RequestMapping("/getServiceUrl")
public List<String> getServiceUrl() {
List<ServiceInstance> list = discoveryClient.getInstances("yanxiaohui-order-service");
List<String> services = new ArrayList<>();
for (ServiceInstance serviceInstance : list) {
if (serviceInstance != null) {
services.add(serviceInstance.getUri().toString());
}
}
return services;
}
// @EnableDiscoveryClient注解是基于spring-cloud-commons依赖,并且在classpath中实现;
// 适合于consul、zookeeper注册中心
// @EnableEurekaClient注解是基于spring-cloud-netflix依赖,只能为eureka作用;
zookeeper用作注册中心
Maven
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot整合eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
application.yml
###订单服务的端口号
server:
port: 8002
###服务别名----服务注册到注册中心名称
spring:
application:
name: yanxiaohui-order-service
cloud:
zookeeper:
connect-string: 127.0.0.1:2181
###订单服务的端口号
server:
port: 8003
###服务别名----服务注册到注册中心名称
spring:
application:
name: yanxiaohui-user-service
cloud:
zookeeper:
connect-string: 127.0.0.1:2181
启动zk-member服务和zk-order服务,可以发现在Zk服务器端上有对应的节点信息(临时节点)