这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战
一、服务注册 - Provider 搭建
Nacosdocker启动,版本1.3.2spring boot版本2.2.1.RELEASEspring cloud alibaba版本2.2.0.RELEASE
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 配置文件
spring.application.name=my-provider
server.port=8080
spring.cloud.nacos.discovery.server-addr=192.168.226.36:8848
- 代码
@SpringBootApplication
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
@RestController
class EchoController {
@GetMapping("/echo")
public String echo(HttpServletRequest request) {
return "echo: " + request.getParameter("name");
}
}
}
启动后,服务正常。
可以查看 Nacos,服务发现,如图:
二、服务发现 - Consumer 搭建
pom配置,如同provider
- 配置文件
spring.application.name=nacos-consumer
server.port=8081
spring.cloud.nacos.discovery.server-addr=localhost:8848
- 代码
@SpringBootApplication
@EnableDiscoveryClient(autoRegister = false) // 设置不自动注册到注册中心
public class NacosConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@RestController
class HelloController {
@Autowired
private DiscoveryClient discoveryClient; // 服务发现
@Autowired
private RestTemplate restTemplate;
private String serviceName = "my-provider";
@GetMapping("/info")
public String info() {
// 使用 DiscoveryClient 获取 my-provider 服务对应的所有实例
List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);
StringBuilder sb = new StringBuilder();
sb.append("All services: " + discoveryClient.getServices() + "<br/>");
sb.append("my-provider instance list: <br/>");
serviceInstances.forEach(instance -> {
sb.append("[ serviceId: " + instance.getServiceId() +
", host: " + instance.getHost() +
", port: " + instance.getPort() + " ]");
sb.append("<br/>");
});
return sb.toString();
}
@GetMapping("/hello")
public String hello() {
List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);
ServiceInstance serviceInstance = serviceInstances.stream()
.findAny().orElseThrow(() ->
new IllegalStateException("no " + serviceName + " instance available"));
return restTemplate.getForObject(
"http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() +
"/echo?name=nacos", String.class);
}
}
}
访问 http://localhost:8081/info:
All services: [my-provider]
my-provider instance list:
[ serviceId: my-provider, host: 192.168.226.36, port: 8080 ]
访问 http://localhost:8081/hello:
echo: nacos
三、配置管理 - Provider 搭建
在 一、服务 - Provider 搭建 的基础上,搭建。
pom.xml中添加
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 在
resources添加bootstrap.properties
spring.application.name=my-provider
server.port=8080
spring.cloud.nacos.config.server-addr=192.168.226.36:8848
spring.cloud.nacos.discovery.server-addr=192.168.226.36:8848
- 在
NacosProviderApplication.java中添加代码
@SpringBootApplication
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
@RestController
class EchoController {
@Autowired
ApplicationContext applicationContext;
@GetMapping("/echo")
public String echo(HttpServletRequest request) {
return "echo: " + request.getParameter("name");
}
// 添加如下
@GetMapping("/config")
public String config() {
return "env.get('book.category')=" +
applicationContext.getEnvironment().getProperty("book.category", "unknown");
}
}
}
- 在
Nacos里新建配置,并发布。 如图:
启动服务,服务运行正常。
访问 http://localhost:8080/config :
env.get('book.category')=spring cloud
修改Nacos 里的配置文件,访问 http://localhost:8080/config:
可以发现配置动态更新了。
env.get('book.category')=spring cloud nacos
bootstrap.properties 文件,该文件配置了 Nacos 配置中心的地址,这个文件会让 Spring Cloud 启动 Bootstrap 阶段在 Nacos 配置中心获取配置。
Spring Cloud 的 Bootstrap 阶段的概念:
在
Bootstrap阶段会构造ApplicationContext,这个ApplicationContext加载配置的过程会基于bootstrap.properties或bootstrap.yaml文件(spring.config.name为bootstrap)去加载文件。 在加载文件的过程中,Spring Cloud有一套机制(PropertySourceLocator接口的定义)来u构造数据源PropertySource,其余跟Spring Boot一致的。
BootStrap 阶段构造的 ApplicationContext 会作为正常阶段的 ApplicationContext 的父类(parent),有了这一层父子关系之后,如果不能从子 ApplicationContext 获取配置,就会从父 ApplicationContext 获取。
Spring Cloud Bootstrap 阶段优先级高,会先读取配置中心的配置,这些配置在下一次正常的 ApplicationContext 启动时作用。
spring-cloud-context 模块内部的 META-INF/spring.factories 添加了一个 Bootstrap-ApplicationListener (实现了 ApplicationListener 接口),用于监听 ApplicationEnvironmentPreparedEvent 事件(Environment 刚创建,ApplicationContext 未创建时会触发事件),收到该事件后进入 Bootstrap 阶段,从配置中心加载配置。