注册中心
关于注册中心的解决方案,dubbo 支持了 Zookeeper、Redis、Multicast 和 Simple,官方推荐 Zookeeper。Spring Cloud 支持了 Zookeeper、Consul 和 Eureka,官方推荐 Eureka。
- ZK 的设计原则是 CP,即强一致性和分区容错性。他保证数据的强一致性,但舍弃了可用性,如果出现网络问题可能会影响 ZK 的选举,导致 ZK 注册中心的不可用。
- Eureka 的设计原则是 AP,即可用性和分区容错性。他保证了注册中心的可用性,但舍弃了数据一致性,各节点上的数据有可能是不一致的(会最终一致)。
Spring Cloud Eureka
Spring Cloud Eureka是Spring Cloud Netflix微服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能。Spring Cloud通过为Eureka增加了Spring Boot风格的自动化配置,我们只需通过简单引入依赖和注解配置就能让Spring Boot构建的微服务应用轻松地与Eureka服务治理体系进行整合。
服务注册
在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。比如,我们有两个提供服务A的进程分别运行于192.168.0.100:8000和192.168.0.101:8000位置上,另外还有三个提供服务B的进程分别运行于192.168.0.100:9000、
192.168.0.101:9000、192.168.0.102:9000位置上。当这些进程均启动,并向注册中心注册自己的服务之后,注册中心就会维护类似下面的一个服务清单。另外,服务注册中心还需要以心跳的方式去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,达到排除故障服务的效果。
服务名 | 位置 |
---|---|
服务A | 192.168.0.100:8000、192.168.0.101:8000 |
服务B | 192.168.0.100:9000、192.168.0.101:9000、192.168.0.102:9000 |
服务发现
由于在服务治理框架下运作,服务间的调用不再通过指定具体的实例地址来实现,而是通过向服务名发起请求调用实现。所以,服务调用方在调用服务提供方接口的时候,并不知道具体的服务实例位置。因此,调用方需要向服务注册中心咨询服务,并获取所有服务的实例清单,以实现对具体服务实例的访问。比如,现有服务C希望调用服务A,服务C就需要向注册中心发起咨询服务请求,服务注册中心就会将服务A的位置清单返回给服务C,如按上例服务A的情况,C便获得了服务A的两个可用位置192.168.0.100:8000和192.168.0.101:8000。
当服务C要发起调用的时候,便从该清单中以某种轮询策略取出一个位置来进行服务调用,这就是客户端负载均衡。。实际的框架为了性能等因素,不会采用每次都向服务注册中心获取服务的方式,并且不同的应用场景在缓存和服务剔除等机制上也会有一些不同的实现策略。
Eureka组件
Eureka包含两个组件:Eureka Server和Eureka Client,它们的作用如下:
- Eureka Server 提供服务发现的能力,各个微服务启动时,会向Eureka Server注册自己的信息(例如IP、端口、微服务名称等),Eureka Server会存储这些信息。
- Eureka Client是一个Java客户端,用于简化与Eureka Server的交互。
- 微服务启动后,会周期性(默认30秒)地向Eureka Server发送心跳以续约自己的“租期”。
- 如果Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。
- 默认情况下,Eureka Server同时也是Eureka Client。多个Eureka Server实例,互相之间通过复制的方式,来实现服务注册表中数据的同步。
- Eureka Client会缓存服务注册表中的信息。这种方式有一定的优势——首先,微服务无须每次请求都查询Eureka Server,从而降低了Eureka Server的压力;其次,即使Eureka Server所有节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者并完成调用。
综上,Eureka通过心跳检查、客户端缓存等机制,提高了系统的灵活性、可伸缩性和可用性。
编与Eureka Server
创建一个eureka项目,加入pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud-demo</artifactId>
<groupId>com.cc.cloud</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-eureka</artifactId>
<dependencies>
<!--eureka server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
注意<artifactId>spring-cloud-starter-eureka-server</artifactId>
已经过期,推荐使用
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
然后加入配置文件
server:
port: 8888
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
简要讲解一下application.yml中的配置属性:
- eureka.client.registerWithEureka:表示是否将自己注册到Eureka Server,默认为true。由于当前应用就是Eureka Server,故而设为false。
- eureka.client.fetchRegistry:表示是否从Eureka Server获取注册信息,默认为true。因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,故而设为false。
- eureka.client.service-url.defaultZone:设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。默认是http://localhost:8888/eureka;多个地址可使用,分隔。 旧版的配置好像是eureka.client.serviceUrl.defaultZone
编写启动类,在启动类上添加EnableEurekaServer 注解,声明这是一个Eureka Server。
package com.cc.cloud.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApp {
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class, args);
}
}
然后启动项目,访问:http://localhost:8888即可
参考
Spring+Cloud微服务实战.pdf
SpringCloud与Docker微服务架构实战-完整版.pdf
Spring Cloud Netflix之Eureka下篇原理