前言
Spring Cloud Eureka是Spring Cloud Netflix微服务套件中的一部分,它是Spring Cloud与Netflix Eureka的的胶水代码,主要负责完成微服务架构中的服务治理功能。
服务治理
服务治理是微服务架构中最为核心和基础的模块,它主要用来实现各个微服务实例的自动化注册于发现。
服务注册
在服务治理框架中,通常会搭建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按照*服务名*****分类组织服务清单。当这些进程启动,并向注册中心注册自己的服务之后,注册中心就会维护一张服务清单表(见-1表格)。另外注册中心还需要以心跳的方式去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,达到排除故障服务的效果。
服务名 | 位置 |
---|---|
SERVICE-A | 192.168.1.1:8080,192.168.1.2:8080 |
SERVICE-B | 192.168.1.3:9000,192.168.1.4:9000,192.168.1.5:9000 |
服务发现
由于在服务治理框架下运作,服务间的调用不再通过指定具体的实例地址来实现,而是通过向服务名发起请求调用实现。所以服务调用方在调用服务提供方接口的时候,并不知道具体的服务实例位置。因此,调用方需要向服务注册中心咨询服务,并获取所有服务的实例清单,以实现对具体服务实例的访问。
Spring Cloud Eureka
Spring Cloud Eureka 使用Netflix Eureka来实现服务注册与发现,它既包含了服务端组件,也包含了客户端组件。Eureka服务端,也即服务注册中心,支持高可用配置。Eureka客户端,主要处理服务的注册于发现。客户端服务通过注解或配置的方式,嵌入客户端应用程序的代码中,在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性的发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态。
搭建服务注册中心
基于Spring Boot的服务搭建起来很快速,废话不多说,直接上代码
- pom.xml文件中引入spring-cloud-starter-eureka-server就行了
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 启动类中添加@EnableEurekaServer注解。
@SpringBootApplication
@EnableEurekaServer
public class MermaidEurekaServer {
public static void main(String[] args) {
new SpringApplicationBuilder(MermaidEurekaServer.class).web(true).run(args);
}
}
- 默认设置下,该服务中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,在application.properties中增加禁用配置即可
server.port=19500
eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
#eureka.client.register-with-erueka:由于该应用为注册中心,所以设置为false,表示不向自己注册自己
#eureka.client.fetch-registry:由于注册中心的职责就是维护服务实例,它并不需要去检索服务,所以也设置为false
- 启动服务,显示界面,(暂无服务)如下:
注册服务提供者
在完成了服务注册中心的搭建后,我们基于Spring Boot创建一个应用,并加入到Eureka的服务治理体系中去。
- pom.xml中增加Spring Cloud Eureka模块依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>${spring.cloud.version}</version>
</dependency>
- 在主类中添加@EnableDiscoveryClient注解,激活Eureka中的DiscoveryClient实现(自动化配置)
@ComponentScan({"com.mermaid.framework"})
@SpringBootApplication
@EnableDiscoveryClient
public class MermaidApplicationEntry {
public static void main(String[] args) {
SpringApplication.run(MermaidApplicationEntry.class,args);
}
}
- 在application.properties配置文件中,添加spring.application.name属性来为服务命名,在通过eureka.client.serviceUrl.defautlZone属性来指定服务注册中心的地址。
spring.application.name=core-service
server.port=19501
eureka.client.service-url.defaultZone=http://localhost:19500/eureka
- 启动服务,查看启动日志,以及注册中心日志如下:
########################服务日志#######################################
com.netflix.discovery.DiscoveryClient : Discovery Client initialized at timestamp 1531021845105 with initial instances count: 0
o.s.c.n.e.s.EurekaServiceRegistry : Registering application core-service with eureka with status UP
com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [timestamp=1531021845157, current=UP, previous=STARTING]
com.netflix.discovery.DiscoveryClient : DiscoveryClient_CORE-SERVICE/DESKTOP-QO73KDA:core-service:19502: registering service...
] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647
d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed
d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s)
com.netflix.discovery.DiscoveryClient : DiscoveryClient_CORE-SERVICE/DESKTOP-QO73KDA:core-service:19502 - registration status: 204
s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references
s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 19502 (http)
s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 19502
c.m.framework.MermaidApplicationEntry : Started MermaidApplicationEntry in 6.786 seconds (JVM running for 7.294)
com.netflix.discovery.DiscoveryClient : Disable delta property : false
com.netflix.discovery.DiscoveryClient : Single vip registry refresh property : null
com.netflix.discovery.DiscoveryClient : Force full registry fetch : false
com.netflix.discovery.DiscoveryClient : Application is null : false
com.netflix.discovery.DiscoveryClient : Registered Applications size is zero : true
com.netflix.discovery.DiscoveryClient : Application version is -1: false
com.netflix.discovery.DiscoveryClient : Getting all instance registry info from the eureka server
com.netflix.discovery.DiscoveryClient : The response status is 200
################注册中心日志#############################
2018-07-08 11:50:45.327 INFO 11240 --- [io-19500-exec-3] c.n.e.registry.AbstractInstanceRegistry : Registered instance CORE-SERVICE/DESKTOP-QO73KDA:core-service:19502 with status UP (replication=false)
- 通过Eureka信息面板查看如下:
- 改造controller,注入discovery
@RestController
public class HelloController {
@Autowired
private DiscoveryClient client;
@RequestMapping(value="/hello",method=RequestMethod.GET)
public String index() {
ServiceInstance instance = client.getLocalServiceInstance();
System.out.println("/hello,host:"+instance.getHost(),+",serviceId:"+instance.getServiceId());
return "Hello,I am OK";
}
}
高可用配置中心
Eureka Server的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用的效果。在注册中心的application.properties文件中添加eureka.client.serviceUrl.defaultZone属性即可
server.port=19500
eureka.instance.hostname=peer1
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://peer2:19505/eureka/
服务发现与消费
服务发现与消费主要是由Ribbon完成,Ribbon是一个基于Http和TCP的客户端负载均衡器,它可以通过客户端配置的ribbonServerList去轮询访问以达到负载均衡的作用。
- 引入ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
- 在启动类中注入RestTemplate
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
- 在Controller中注入RestTemplate
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@RequestMappming(value="/ribbon-cusmer",method=RequestMethod.GET)
public String helloConsumer() {
return restTemplate.getForEntity("http://CODE-SERVICE/hello",String.class).getBody();
}
}
- 在application.properties中配置Eureka服务注册中心的位置
spring.application.name=ribbon-consumer
server.port=9000
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
- 启动ribbon-consumer后,我们可以在Eureka信息面板中看到多了一个RIBBON-CONSUMER服务。通过向‘http://localhost:9000/ribbon-consumer’发起GET请求,成功返回了“Hello,I am OK”。此时表示成功调用到了CORE-SERVICE服务。日志也会有体现。