这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战
一、服务注册 - Provider
搭建
Nacos
docker
启动,版本1.3.2
spring boot
版本2.2.1.RELEASE
spring 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
阶段,从配置中心加载配置。