Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理。
在传统的 rpc 远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间的依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
Eureka 采用了 CS 的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka Client 客户端连接到 Eureka Server 并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统各个微服务是否运行正常。
在服务注册与发现中,有一个注册中心,当服务启动时会把自己当前的服务信息,比如服务通讯地址等以别名的方式注册到注册中心去,而另一个服务则可以以该别名的方式去注册中心上获取实际的服务通讯地址,然后实现本地 RPC 调用远程 RPC。远程调用框架的的核心设计思想在于注册中心,因为注册中心管理每个服务与服务之间的依赖关系。
Eureka 包含两个组件:Eureka Server和Eureka Client
Eureka Server:提供服务注册。各个微服务节点通过配置启动后,会在 Eureka Server 中进行注册,这样 Eureka Server 中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在洁面中直观看到。Eureka Client:可以通过注册中心进行访问的 Java 客户端,用于简化 Eureka Server 的交互,其具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,客户端将会想 Eureka Server 发送心跳(默认周期为30秒)。如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认90秒)。注意:Eureka 依赖有两个版本 1.x和2.x:
1.x 老版本中服务端和客户端都使用同一个依赖包:
<!--eureka-server--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency>2.x 新版中把服务端和客户端的依赖分开来了:
<!--eureka-server--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!--eureka-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>在 SpringBoot 主启动类中添加 @EnableEurekaServer 注解
修改完后启动服务,然后访问配置文件中的服务地址:localhost:7001/eureka/ 即可看到 Eureka 服务注册中心页面。
在 SpringBoot 主启动类中添加 @EnableEurekaClient 和 @EnableDiscoveryClient 注解,其中 @EnableEurekaClient 是专门用于 Eureka 的,而 @EnableDiscoveryClient 是所有微服务发现都要用的。
微服务 RPC 远程调用最核心的就是:高可用。为了避免单机突然故障而导致服务不可用,我们需要搭建 Eureka 注册中心集群,实现负载均衡 + 故障容错。
Eureka Server 集群的原理就是互相注册、相互守望,说白了就是多台机器的 Eureka Server 可以互相访问并共享注册信息。
假如有两台单机版的 Eureka Server 微服务模块,想要集群需要修改其 yml 配置信息。
机器1的配置信息:
server: port: 7001 spring: application: name: cloud-eureka-service-1 eureka: instance: hostname: eureka7001.com client: register-with-eureka: false fetch-registry: false service-url: # 注册到另一台 Eureka Server 中 defaultZone: http://eureka7002.com:7002/eureka/机器2的配置信息:
server: port: 7002 spring: application: name: cloud-eureka-service-2 eureka: instance: hostname: eureka7002.com client: register-with-eureka: false fetch-registry: false service-url: # 注册到另一台 Eureka Server 中 defaultZone: http://eureka7001.com:7001/eureka/Eureka Serve 集群搭建好启动并可以访问之后需要修改客户端的服务注册地址为:
eureka: client: register-with-eureka: true fetch-registry: true service-url: # Eureka Server 集群服务地址 defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka客户端注册好后,集群的 Eureka Serve 注册中心的注册列表都可以看到该服务。
所谓 Eureka Client 客户端集群,指的是多个提供相同的功能的微服务通过注册中心集合在一起,比如有5台机器都是提供支付服务的,然后把这5台机器集群注册到注册中心,当远程调用该服务的时,注册中心就会通过负载均衡算法去调用其中一台机器服务接口。
构建 Eureka Client 服务集群需要修改微服务面模块中的 yml 配置文件内容如下:
# 设置服务端口 server: port: 8001 # 设置微服务名称 spring: application: name: cloud-payment-service # 配置 eureka eureka: client: register-with-eureka: true fetchRegistry: true service-url: # 注册中心服务地址,集群版 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka instance: # 设置集群服务的实例名称 instance-id: payment8001 # 访问路径可以显示IP地址 prefer-ip-address: true这里需要注意的是,集群中的每个 Eureka Client 需要使用同一个服务名称,端口可以不一样,注册到注册中心时也需要使用注册中心的集群地址。
当 Eureka Client 都成功集群到注册中心时,注册中心就会看到服务列表的 cloud-payment-service 服务下有多个实例服务,我们可以通过 eureka.instance.instance-id 来设置服务实例名称,通过 eureka.instance.prefer-ip-address 设置点击服务实例时可以显示服务的IP地址。
我们使用 RestTemplate 来进行服务调用:
// 创建 RestTemplate 实例 @Configuration public class ApplicationContextConfig { @Bean @LoadBalanced // 提供负载均衡能力 public RestTemplate getRestTemplate() { return new RestTemplate(); } } // 远程调用服务时只需要填写注册中心的服务名即可 @RestController @Slf4j 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); } }注意:要远程调用其它服务,自己本身也要注册到注册中心去。