0.1什么是Eureka
Eureka服务注册中心,采用了CS的设计架构,Eureka Server作为服务注册功能的服务器。系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员可以通过Eureka Server来监控系统中各个微服务是否可用。
0.2Eureka两组件
Eureka Server:提供服务注册功能,各个微服务节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中会存储所有可用服务节点的信息。
Eureka Client:通过注册中心进行访问,是一个java客户端,具备一个内置的使用轮询负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期30秒)。如果Eureka Server在多个心跳周期内没有接受到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
0.3Eureka构建步骤
(1)创建Maven工程作为Eureka Server(cloud-eureka-server7001)
(2)添加Eureka-Server依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
(3)application.yml文件
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务端的实例名字
client:
#启动时会有警告,需要加上register-with-eureka和fetch-registry
register-with-eureka: false #表识不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,并不需要去检索服务
service-url:
defaultZone: http://localhost:7001/eureka/ #与eureka server交互的地址,查询服务和注册服务都需要依赖这个地址
(4)在启动类上加@EnableEurekaServer,表示自己是服务注册中心
(5)测试:http://localhost:7001/
(6)创建Maven工程作为Eureka Client(cloud-provider-payment8001服务提供者)
(7)添加Eureka Client依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(8) application.yml
server:
port: 8001 #服务端口号
spring:
application:
name: cloud-payment-service #微服务名称
eureka:
client:
register-with-eureka: true #表示将自己注册进Eureka Server
fetchRegistry: true #是否从Eureka Server抓取已有的注册信息,默认为true。集群必须设置为true才能配合ribbon使用负载均衡
service-url:
defaultZone: http://localhost:7001/eureka #注册进哪个Eureka server
(9)启动类上加@EnableEurekaClient //表示自己是客户端
(10)创建Maven工程作为Eureka Client(cloud-consumer-order80服务消费者)
(11)添加Eureka-Client依赖
(12)application.yml
server:
port: 80
eureka:
client:
register-with-eureka: true #表示将自己注册进Eureka Server
fetch-registry: true #是否从Eureka Server抓取已有的注册信息,默认为true。集群必须设置为true才能配合ribbon使用负载均衡
service-url:
defaultZone: http://localhost:7001/eureka #注册进哪个Eureka server
(13)启动类上加@EnableEurekaClient //表示自己是客户端
0.4消费者访问提供者
目前先使用RestTemplate,提供了多种便携访问远程http服务的方法,是一种简单便携的访问restful服务模板类,是spring提供的用于访问rest服务的客户端模板工具类。
(url,requestMap,ResponseBean.class)这三个参数分别代表rest请求地址、请求参数、http响应后返回的结果的对象类型。
使用:
80消费者往容器中加入RestTemplate
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
80消费者代码
@RestController
public class OrderController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public String create(Integer integer){
return restTemplate.postForObject("http://localhost:8001/payment/create",integer,String.class);
}
@GetMapping("/consumer/payment/get/{id}")
public String getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject("http://localhost:8001/payment/get/"+id,String.class);
}
}
8001提供者代码
@RestController
public class PaymentController {
@PostMapping(value = "/payment/create")
public String create(@RequestBody Integer id){
return "新增成功";
}
@GetMapping(value = "/payment/get/{id}")
public String getPaymentById(@PathVariable("id") Long id){
return "查询成功";
}
测试:访问消费者的Controller层
0.5集群Eureka构建
(1)根据cloud-eureka-server7001创建cloud-eureka-server7002
(2)7001和7002互相注册
7001里的defaultZone:http://localhost:7002/eureka/
7002里的defaultZone:http://localhost:7001/eureka/
(3)将8001和80注册到Eureka集群
defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka
(4)根据8001创建8002,搭建服务提供者集群
(5)80消费者的服务地址不能写死
@GetMapping("/consumer/payment/create")
public String create(Integer integer){
//原先
//return restTemplate.postForObject("http://localhost:8001/payment/create",integer,String.class);
//现在
return restTemplate.postForObject("http://CLOUD-PAYMENT-SERVICE/payment/create",integer,String.class);
//发送的请求会被ribbon拦截,ribbbon从eureka注册中心获取服务列表,然后采用均衡策略进行访问
}
(6)80消费者给容器加入RestTemplate 的方法上加@LoadBalanced(赋予RestTemplate负载均衡的能力)
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced //赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
(7)测试:先后启动7001,7002,8001,8002,80
0.6服务发现DiscoveryClient
注册进eureka里面的微服务,可以获得服务的信息。在8001中
@Resource
private DiscoveryClient discoveryClient;
@GetMapping(value = "/payment/discovery")
public Object discovery(){
List<String> services = discoveryClient.getServices(); //获取到在Eureka上的所有服务
for (String element : services) {
log.info("*******element:"+element);
}
//在服务名CLOUD-PAYMENT-SERVICE下的所有实例
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance : instances) {
// ip地址 端口号
/*log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());*/
}
return this.discoveryClient;
}
启动类上加上@EnableDiscoveryClient,开启服务发现
0.7Eureka自我保护
自我保护:Eureka可视化界面的红字
保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下,一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不会注销任何微服务。
默认情况下,Eureka Server在一定时间内没有接收到某个微服务实例的心跳,将会注销该实例(默认90秒),但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险——因为微服务本身其实是健康的,此时不应该注销这个服务。Eureka通过"自我保护模式"来解决这个问题。
一句话:某时刻某一个微服务不可用了,eureka不会立刻清除,依旧会对该服务的信息进行保护,属于CAP里的AP分支。
禁止自我保护
在7001在yml中的eureka下加:
server:
enable-self-preservation: false #关闭自我保护机制,保证不可用服务被及时剔除
eviction-interval-timer-in-ms: 2000 #清理无效节点的时间间隔,默认60000毫秒,即60秒 (此处时间间隔设置为2s)
在8001在yml中的eureka下加:
instance:
lease-renewal-interval-in-seconds: 1 #Client端向Server端发送心跳的时间间隔,单位为秒(默认是30s)
lease-expiration-duration-in-seconds: 2 #server收到最后一次心跳后的等待时间上限,单位为秒(默认90s),超时将移除服务