至关于服务之间的‘通信录’,记录了服务和服务地址之间的映射关系。在分布式架构中服务会注册到这里。当服务须要调用其余服务时,就在注册中心找到其余服务的地址,进行调用java
注册中心通常有如下的功能:mysql
Eureka是SpringCloud微服务架构中经常使用的注册中心,其架构图以下:web
由其架构图能够看出,Eureka能够分为三部分:Eureka服务端,Eureka服务提供者,Eureka服务消费者。spring
其中Eureka服务端须要做为独立的服务运行,而服务提供者、消费者则是须要使用EurekaClient嵌入咱们本身的服务中。sql
其运行原理是这样的:api
聪明的你这个时候会察觉到。既然消费者使用的是缓存的注册信息。那么必定会存在一种状况就是服务提供者这边已经宕机。这个时候消费者根据缓存的信息没有及时更新就会致使调用失败,Eureka是怎么解决这个问题的呢?且往下看。浏览器
这里推荐使用 Spring Initializer 直接建立。选择 web 和 euraka 便可。主要引入的依赖以下:缓存
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
server: port: 9000 eureka: instance: hostname: localhost client: register-with-eureka: false # 是否将本身注册到注册中心 fetch-registry: false # 是否从Eureka中获取注册信息 service-url: # Eureka Client 的请求地址 defaultZone: http://#{eureka.instance.hostname}:#{server.port}/eureka/
启动类除了常规的 @SpringBootApplication 外,还要添加 @EnableEurekaServer 表示开启 Eureka 服务架构
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
这里须要特别注意:Eureka客户端配置的服务端地址使用的key是 defaultZone,不是 default_zone 若是写错会致使客户端没法注册服务,进而致使客户端没法启动app
server: port: 9001 spring: application: name: SERVICE_PROVIDER # 服务名称 datasource: url: jdbc:mysql://192.168.25.128:3306/mysql?characterEncoding=UTF-8&useSSL=false&serverTimezone=CTT driver-class-name: com.mysql.cj.jdbc.Driver password: 521 username: keats eureka: client: service-url: defaultZone: http://localhost:9000/eureka/ # 刚刚在Eureka Server 配置的请求地址 register-with-eureka: true # 注册到注册中心 fetch-registry: false # 做为服务提供者,能够不用从Eureka获取注册信息。视实际状况而定 instance: prefer-ip-address: true # 使用IP地址注册
Euraka 客户端默认每隔 30 S向服务端发送一次心跳请求,若是服务端 90 S没有收到某客户端发送的请求将视为客户端宕机。会将其从服务列表剔除
搭建服务消费者和提供者的步骤相似,首先是添加 eureka-client 依赖
以后配置 application.yml 以下:
server: port: 9002 spring: application: name: SERVICE_CONSUMER # 服务名称 eureka: client: service-url: # 刚刚在Eureka Server 配置的请求地址 defaultZone: http://localhost:9000/eureka/ fetch-registry: true register-with-eureka: false
这样该服务就具有了从Eureka获取服务的能力,那具体怎么使用呢?
Spring 为咱们提供了一个Bean:DiscoveryClient (注意须要导入:org.springframework.cloud.client.discovery 包下的DiscoveryClient 而不是 netflix 包下的类)
咱们在须要获取服务的类里面注入该类
@Autowired private DiscoveryClient discoveryClient;
接着调用其 getInstances(String instancdName) 方法,经过服务的名称获取服务列表。咱们这里只注册了一个服务提供方没有搭集群因此直接使用列表第0位的服务实体。而实体提供了 getUri() 方法用于获取服务提供者的 url。接着咱们用该方法替换硬编码的 url 便可完成 Eureka 的使用。核心代码以下:
网上的不少其余教程在这里使用的都是 getHost() + ":" + getPort() 拼接,推测多是版本比较老旧。新API既然已经提供了 getUri() 方法咱们就要积极使用。这里建议读者们在使用某Bean的方法时经过打点的方式阅读一下其开放的API,大概了解一下
@GetMapping("teacher/users") public List<User> getAllUser(){ List<ServiceInstance> service_provider = discoveryClient.getInstances("SERVICE_PROVIDER"); ServiceInstance serviceInstance = service_provider.get(0); return restTemplate.getForObject(serviceInstance.getUri() + "/api/v1/users", List.class); }
如上图提示,表示Eureka进入了自我保护模式。自我保护模式的介绍以下:
Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟以内是否高于 85%,若是高于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过时。在我看来能够用一句古成语来形容这种模式---“三人成虎” 即当愈来愈多的服务提供者心跳不能到达时。Eureka开始不在怀疑是提供者GG,而怀疑本身了!
在开发环境中,咱们每每启动一个Eureka服务 + 一个 Eureka 提供者,若是此时提供者正好出了问题。90S未发送心跳。但因为知足自我保护条件(这段时间失败比例为100%),Eureka不会将服务剔除。会直接致使服务消费者没法正确获取服务。所以开发环境中建议关闭其自我保护机制,而在生产环境打开之, yml 配置以下:
eureka: server: enable-self-preservation: false # 关闭自我保护