阅读的书籍为《Spring Cloud 微服务实战》。
服务治理可以说是微服务架构中最为核心和基础的模块,主要用来实现各个微服务实例的自动化注册与发现。
早期微服务系统中,服务不多,可以通过静态配置来完成服务的调用。但是随着业务的发展,系统功能越来越复杂,相应的微服务应用也不断增加,静态配置就越来越难以维护,故需要实现微服务实例的自动化注册与发现。
在服务治理框架中,通常都会构建一个注册中心,每个服务单元都向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。 服务注册中心还需要以心跳的方式去监测清单中的服务是否可用,若不可用,从服务清单中剔除,达到排除故障服务的效果。
在服务治理框架下运作,服务间的调用不再通过指定具体的实例地址来实现,而是通过向服务名发起请求调用实现。
即为服务注册中心。 如果以集群模式部署,当集群中有分片出现故障时,Eureka就会转入自我保护模式。它允许在分片故障期间继续提供服务的发现与注册,当故障分片恢复运行的时候,集群中的其他分片会把它们的状态再次同步回来。 不同可用区域的服务注册中心通过异步模式互相复制各自的状态,这意味着任意给定的时间点,每个实例关于所有服务的状态是有细微差别的。
主要处理服务的注册与发现,在应用程序运行时,客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。 同时它也能从服务端查询当前注册的服务信息,并把它们缓存到本地并周期性地刷新服务状态。
@EnableEurekaServer
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
server.port=1111
eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
#关闭保护机制
eureka.server.enable-self-preservation=false
eureka.client.register-with-eureka设置为false代表不向注册中心注册自己。 eureka.client.fetch-registry设置为false,代表不需要去检索服务。 eureka.server.enable-self-preservation=false,代表关闭保护机制。
Eureka会因为15分钟内超过85%的实例丢失心跳而触发保护机制,触发保护机制后,Eureka Server会将当前实例注册信息保护起来,让这些实例不会过期。但在保护期内,可能实例出现了问题,那么客户端就很容易拿到实际已经不存在的实例,出现调用失败的情况。生产环境,需要客户端有容错机制,比如请求重试、断路器等。在此,本地调试时关闭保护机制,确保注册中心可以将不可用的实例正确剔除。
其中Instances currently registered with Eureka栏为空,说明该注册中心还没有注册任何服务。
package com.example.helloworld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
}
package com.example.helloworld.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.apache.log4j.Logger;
import java.util.List;
@RestController
public class HelloworldController {
private final Logger log = Logger.getLogger(getClass());
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping(value = "/helloworld", method = RequestMethod.GET)
public String helloworld() {
System.out.println("discoveryClient.getServices().size() = " + discoveryClient.getServices().size());
for (String s : discoveryClient.getServices()) {
System.out.println("services " + s);
List<ServiceInstance> serviceInstances = discoveryClient.getInstances(s);
for (ServiceInstance si : serviceInstances) {
System.out.println(" services:" + s + ":getHost()=" + si.getHost());
System.out.println(" services:" + s + ":getPort()=" + si.getPort());
System.out.println(" services:" + s + ":getServiceId()=" + si.getServiceId());
System.out.println(" services:" + s + ":getUri()=" + si.getUri());
System.out.println(" services:" + s + ":getMetadata()=" + si.getMetadata());
}
}
return "hello world";
}
}
spring.application.name=hello-world-service
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
可以在该服务的控制台看到如下输出:
可以在服务注册中心的控制台看到如下输出:
访问Eureka的信息面板
可以在注册服务的控制台查看到它从服务注册中心获取到的服务相关信息。