在前面教程中,我们概括了进行微服务业务开发时需要的三个基础功能:注册服务器、断路器和Feign客户端,有了这三个组件,你基本可以在本地进行微服务开发,但是在正式Spring Cloud生产环境中,还需要配置服务器,这样可以实现动态配置管理,同时需要类似Nginx这样网关路由器Zuul或Spring Cloud Gateway,这两个组件是生产运行配置方面:
1. Spring Cloud Bus
如何将配置推送到分布式微服务节点?本上我在生产中看到了以下解决方案:
- 使用分布式缓存(Hazelcast,Oracle Coherence ...)
- 通过JMS或AMPQ等中间件推送设置。
Spring Cloud中的一个选项是使用Spring Cloud Bus,它或多或少是我列表中的第二个选项。节点之间的信息传输正在通过AMPQ协议完成,但是他们在路线图上有其他传输方式如JMS。现在我们使用AMPQ。
1、使用RabbitMQ和Spring Cloud Bus
需要做的就是:
- 将spring-cloud-starter-bus-amqp依赖项添加到classpath
- 确保消息中间件正在运行。
- 如果你在localhost(测试)上运行它,你不需要做任何事情.。如果您单独运行RabbitMQ,则需要在每个节点上配置以下内容:
spring:
rabbitmq:
host: <broker host>
port: <broker port>
username: <broker user>
password: <broker password>
2、配置Spring Cloud Config Server
Spring Cloud Bus提供的是将指令或配置发送到侦听总线的MicroServices,以通过以下内置HTTP端点触发的AMPQ消息重新加载Spring应用程序属性(它的行为类似于分布式actuator):
代码语言:javascript复制"to invoke the reload of all application.properties of all MicroServices listening on the BUS"
/bus/refresh
"to invoke the reload of application.properties config of specific MicroService"
/bus/refresh?destination=<spring.application.name>:<app port>
"to send a specific key/value pair to MicroService Spring environment"
/bus/env
Spring Cloud Config通常是一个具有存储在GIT仓库中的属性的组件。它们支持许多公共git门户网站,如GitHub,Bitbucket,GitLab ...如果您想使用其他存储如数据库来存储属性,也可以使用Oracle等配置。
现在使用GIT。我们将以下属性保存到此GIT仓库中:
代码语言:javascript复制service.dataBatchSize = 1
在microservice-spring-cloud-bus / config文件夹下,配置pring Cloud Config服务器的地址:
代码语言:javascript复制spring.cloud.config.server.git.uri=https://tomask79@bitbucket.org/tomask79/microservice-spring-cloud-bus.git
spring.cloud.config.server.git.searchPaths=microservice-spring-cloud-bus, config
这个配置在告诉服务器根据spring.cloud.config.server.git.uri属性值获取配置存储库,并尝试搜索几个文件夹以找到配置文件。
我们将使用名为citiesService,personsService的两个MicroServices 来监听RabbitMQ总线。因此config子文件夹将包含citiesService.properties和personsService.properties文件。
文件名对应到客户端的spring.application.name属性值。
2、客户端使用Spring Cloud Config Server
每个MicroService都需要具有以下bootstrap.properties:
代码语言:javascript复制spring.cloud.config.uri=http://localhost:9999
spring.cloud.config.enabled=true
这样,这个微服务就可以到配置服务器找到我之前配置的属性service.dataBatchSize。让我们在以下简单的citiesService使用这个属性。
代码语言:javascript复制@RestController
@RefreshScope
public class CitiesController {
@Value("${service.dataBatchSize:0}")
private int dataBatchSize;
final City[] cities = {
new City("Brno", "Czech republic"),
new City("Bern", "Switzerland"),
new City("Berlin", "Germany"),
new City("London", "England")
};
@RequestMapping("/cities")
public Cities getCities() {
final Cities result = new Cities();
for (int i=0; i < dataBatchSize; i ) {
result.getCities().add(cities[i]);
}
return result;
}
}
测试:
代码语言:javascript复制首先启动RabbitMQ消息系统(启动取决于您安装它的环境)
git clone https://bitbucket.org/tomask79/microservice-spring-cloud-bus.git
mvn clean install(在pom.xml的根文件夹中)
cd spring-microservice-registry
java -jar target / registry-0.0.1-SNAPSHOT.war
验证NetFlix Eureka是否在http:// localhost:9761上运行
cd ..
cd spring-microservice-config
java -jar target / config-0.0.1-SNAPSHOT.war
cd ..
cd spring-microservice-service1
java -jar target / service1-0.0.1-SNAPSHOT.war
在http:// localhost:9761验证citiesService已注册
cd ..
cd spring-microservice-service2
java -jar target / service2-0.0.1-SNAPSHOT.war
在http:// localhost:9761验证personsService已经注册
一切正常后可访问:http://localhost:8081/cities
您应该看到大小等于“service.dataBatchSize”属性的城市列表。现在更改GIT仓库中citiesService.properties文件中的属性。如果您再次点击http:// localhost:8081 / cities,那么您将看不到任何更改...要重新加载citiesService MicroService的Spring上下文,请运行以下命令:
代码语言:javascript复制(you can run this at any node having spring-cloud-starter-bus-amqp dependency)
curl -X POST http://localhost:9999/bus/refresh
也可以使用Postman的REST客户端提交刷新。
2. Spring Cloud Zuul作为微服务网关
在编写微服务时,您将面临以下问题:
- 来自客户端的一个请求跨多个微服务调用
- 你需要如何做金丝雀版本发布机制
- 您需要反向代理来调用微服务
类似Nginx一个总的入口网关。
1、Spring Cloud Zuul作为反向代理
在将微服务部署到Docker时,需要处理多个微服务映射到多个端口的问题。但是,您的API消费者不希望知道这些端口,他们只需要在8080端口调用其他所有端口的所有内容。这里有很多解决方案,但使用Spring Cloud Zuul真的很棒!
让我们在端口8081和8082上运行两个微服务citiesService和personsService的先前演示,并为此做出反向代理,以便可以在一个端口下调用这两个服务:
代码语言:javascript复制http://localhost:8080/cities -> (redirect) -> http://localhost:8081/cities
http://localhost:8080/persons -> (redirect) -> http://localhost:8082/cities
在 Spring Cloud Zuul 下配置:
代码语言:javascript复制spring.application.name=personsService
eureka.client.serviceUrl.defaultZone=http://localhost:9761/eureka
eureka.client.healthcheck.enabled=true
zuul.routes.persons.path=/persons
zuul.routes.persons.serviceId=personsService
zuul.routes.cities.path=/cities
zuul.routes.cities.serviceId=citiesService
ribbon.eureka.enabled=true
server.port=8080
我们在这里有两条路由: /persons 和/cities。每次对路由'/ persons'的调用都将被重定向到在Netflix Eureka服务器上注册的personsService 。每次调用“/ cities”网址都会被重定向到在Eureka注册的cititesService。
测试:
代码语言:javascript复制* Start RabbitMQ broker first (start depends on the environment you've got it installed in)
* git clone https://bitbucket.org/tomask79/microservice-spring-cloud-zuul.git
* mvn clean install (in the root folder with pom.xml)
* cd spring-microservice-registry
* java -jar target/registry-0.0.1-SNAPSHOT.war
verify that NetFlix Eureka is running at http://localhost:9761
* cd ..
* cd spring-microservice-config
* java -jar target/config-0.0.1-SNAPSHOT.war
* cd ..
* cd spring-microservice-service1
* java -jar target/service1-0.0.1-SNAPSHOT.war
verify at http://localhost:9761 that citiesService has been registered
* cd ..
* cd spring-microservice-service2
* java -jar target/service2-0.0.1-SNAPSHOT.war
verify at http://localhost:9761 that personsService has been registered
* cd ..
* cd spring-microservice-zuul
* java -jar target/spring-cloud-zuul-0.0.1-SNAPSHOT.war
(this will start your reverse proxy)
在浏览器运行:
代码语言:javascript复制http://localhost:8080/persons
http://localhost:8080/cities