Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理
提示:以下是本篇文章正文内容,下面案例可供参考
服务治理是随着微服务一起出现的。因为每个服务都有自己独立的资源,服务与服务之间的交互就变得复杂多了,因此服务治理应运而生。
怎么知道其他服务(服务发现)
服务怎么管理(服务注册)
服务之间怎么调用(服务调用)
服务调用之间出现问题(熔断,降级,限流)
等等
在服务注册与发现中,有一个注册中心。服务提供者会把自己的信息(服务地址通信地址接口地址)以别名的方式注册到注册中心中,服务消费者,以该别名的方式在注册中心获取到实际的服务通信地址,然后再实现本地RPC调用RPC远程服务。
Eureka系统架构图:
Eureka采用了CS的设计架构

Eureka Server和Eureka Client
生成Eureka Server 服务端,也就是注册中心
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
dependency>
dependencies>
Eureka Server版本问题
<dependency>
<groupid>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己。
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
package com.heng;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class,args);
}
}
启动之后,浏览器输入http://localhost:7001/

cloud-provid-8001payment是提前创建的微服务支付模块
添加spring-cloud-starter-netflix-eureka-client依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
添加eureka client配置
eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
package com.heng;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
启动cloud-provider-8001payment和cloud-eureka-server7001工程
浏览器访问http://localhost:7001/


由架构图我们可以发现,可以实现注册中心集群和某个微服务集群
为什么要搭建集群环境?
只有一个注册中心,当它出现故障会导致整个服务环境不可用
怎么搭建集群环境?
相互注册,相互守望

点击进去发现是空白,而且无法保存—>权限不足

修改 hosts文件并保存

通过ping 测试本地映射

参考cloud-eureka-server7001上面的创建过程
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己。
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka server交互的地址查询服务和注册服务都需要依赖这个地址。
#相互注册,集群指向其他eureka
defaultZone: http://eureka7002.com:7002/eureka/
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己。
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
启动两个注册中心
浏览器 输入http://eureka7002.com:7002;

http://eureka7001.com:7001

eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka

参考cloud-provicer-8001payment支付服务,创建cloud-provicer-8002payment支付服务
修改两个支付服务的控制层,通过查询端口号,我们可以知道调用了那个支付服务
public class PaymentController {
@Value("${server.port}")
private String serverPort;//添加serverPort
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment){
int i = paymentService.create(payment);
log.info("*****插入结果:"+i);
if(i>0){
return new CommonResult(200,"插入数据成功"+serverPort,i);
}else {
return new CommonResult(444,"插入数据失败",null);
}
}
注意:import org.springframework.beans.factory.annotation.Value;
增加订单微服务模块
public class OrderController
{
public static final String PAYMENT_URL="http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
}
package com.heng.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
控制层代码:
测试:
先启动两个注册中心,再启动两个支付服务,最后启动订单服务


浏览器访问:http://localhost/consumer/payment/get/31

再次刷新后


如上图红色的字体所示,说明了Eureka 进入了保护模式
什么是自我保护机制?
默认情况下EurekaClient每30秒向EurekaServer端发送心跳包
如果Eureka在server端在一定时间内(默认90秒)没有收到EurekaClient发送心跳包,便会直接从服务注册列表中剔除该服务
如果网络不通或延迟导致EurekaClient出现宕机,此时如果换做别的注册中心如果一定时间内没有收到心跳会将剔除该服务,这样就出现了严重失误,因为客户端还能正常发送心跳,只是网络延迟问题,而保护机制是为了解决此问题而产生的
默认自我保护机制是开的
eureka:
...
server:
#关闭自我保护机制,保证不可用服务被及时踢除
enable-self-preservation: false
#每隔多久ms触发一次服务剔除
eviction-interval-timer-in-ms: 2000
出现以下红字,说明自我保护机制已经关闭

eureka:
...
instance:
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 2
eureka:
...
instance:
instance-id: payment8002

eureka:
...
instance:
instance-id: payment8002
prefer-ip-address: true #添加

对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
@Resource
private DiscoveryClient discoveryClient;
@GetMapping(value = "/payment/discovery")
public Object discovery()
{
//获得注册中心有哪几个微服务注册进来了
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("*****element: "+element);
}
//具体的微服务下有那几个
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance : instances) {
log.info(instance.getServiceId()+"\t"+"主机名称:"+instance.getHost()+"\t"+"端口号:"+instance.getPort()+"\t"+"url:"+instance.getUri());
}
return this.discoveryClient;
}
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient #增加的
public class PaymentMain8002 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8002.class,args);
}
}
