Spring Cloud Commons 主要包括如下模块的接口和默认实现:
其中的限流策略以及重试策略是没有天然带的,但是其他模块的实现一般会带上这些功能。我们先从服务发现相关接口开始分析
服务发现相关
核心接口DiscoveryClient
public interface DiscoveryClient extends Ordered { int DEFAULT_ORDER = 0; //描述 String description(); //通过 serviceId 获取服务实例 List<ServiceInstance> getInstances(String serviceId); //获取所有服务的名称 List<String> getServices(); @Override default int getOrder() { return DEFAULT_ORDER; } }
DiscoveryClient 扩展了 Ordered
接口,这个和之前提到的@Order
注解的作用是一样的。
服务实例的信息包括:
public interface ServiceInstance { //实例id,并不是必须的 default String getInstanceId() { return null; } //服务id,用于区分不同微服务 String getServiceId(); //服务实例提供服务的地址 String getHost(); //服务实例提供服务的端口 int getPort(); //是否使用的是 HTTPS boolean isSecure(); //提供服务的 URI 地址 URI getUri(); //一些元数据信息 Map<String, String> getMetadata(); //使用的传输协议,例如 http,https 等等 default String getScheme() { return null; } }
Spring Cloud 从 Feinchley 版本之后,越来越重视异步 Reactor 编程与 WebFlux,所以所有同步的接口基本上都有对应的异步接口,这里的DiscoveryClient
对应的就是ReactiveDiscoveryClient
:
public interface ReactiveDiscoveryClient extends Ordered { int DEFAULT_ORDER = 0; //描述 String description(); //通过 serviceId 获取服务实例,这里返回的是 Flux,究竟如何使用会在后面的例子中详细阐明 Flux<ServiceInstance> getInstances(String serviceId); //获取所有服务的名称,这里返回的是 Flux,究竟如何使用会在后面的例子中详细阐明 Flux<String> getServices(); @Override default int getOrder() { return 0; } }
如何通过配置文件配置服务实例?
使用 SimpleDiscoveryClient
与 SimpleReactiveDiscoveryClient
假设要调用的微服务的域名是固定的,我们可以直接通过将这些域名写入配置文件。这个场景一般发生在:
- 基于 Kubernetes ingress nginx 与 coredns 的内网域名解析负载均衡
- 外网统一提供服务的域名
我们通过一个例子来说明下 SimpleDiscoveryClient
与 SimpleReactiveDiscoveryClient
,这里的代码可以从这里下载,首先引入依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2020.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
编写application.yml
,这里列举了SimpleDiscoveryClient
与SimpleReactiveDiscoveryClient
所有可能的配置:
spring: cloud: discovery: client: # SimpleDiscoveryClient与SimpleReactiveDiscoveryClient的配置 simple: instances: #微服务1 service1: #实例1 - host: instance1 #地址 port: 8080 #端口 instanceId: 'instance1:8080' #可以不填,实例id #实例2 - uri: 'https://instance2:443' #指定了 scheme 为 https,host 为 instance2,端口为443 #微服务2 service2: #实例3 - host: instance3 #地址 port: 80 #端口 instanceId: ${spring.cloud.discovery.client.simple.instances.service2[0].host}:${spring.cloud.discovery.client.simple.instances.service2[0].port} #可以不填,实例id #实例4 - uri: 'https://instance4:8080' #指定了 scheme 为 https,host 为 instance4,端口为8080 # 指定 SimpleDiscoveryClient的排序顺序为1,默认是0,越小越优先 order: 1 # actuator 配置 management: endpoint: health: # health 接口总是输出详细信息 show-details: always endpoints: jmx: exposure: # jmx 不暴露任何 actuator 接口 exclude: '*' web: exposure: # http 暴露所有 actuator 接口 include: '*'
我们配置了四个不同实例: