【Nacos】服务注册

231 阅读2分钟

这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战

一、服务注册 - Provider 搭建

Nacos docker 启动,版本 1.3.2 spring boot 版本 2.2.1.RELEASE spring cloud alibaba 版本 2.2.0.RELEASE

  1. 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>
  1. 配置文件
spring.application.name=my-provider
server.port=8080
spring.cloud.nacos.discovery.server-addr=192.168.226.36:8848
  1. 代码
@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,服务发现,如图:

2021-01-1817-22-54.png



二、服务发现 - Consumer 搭建

  1. pom配置,如同 provider
  1. 配置文件
spring.application.name=nacos-consumer
server.port=8081
spring.cloud.nacos.discovery.server-addr=localhost:8848
  1. 代码
@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 搭建 的基础上,搭建。

  1. pom.xml 中添加
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
  1. 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
  1. 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");
        }
    }
​
}
  1. Nacos 里新建配置,并发布。 如图:2021-01-1817-22-54

启动服务,服务运行正常。

访问 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 CloudBootstrap 阶段的概念:

Bootstrap 阶段会构造 ApplicationContext,这个ApplicationContext 加载配置的过程会基于 bootstrap.propertiesbootstrap.yaml 文件(spring.config.namebootstrap)去加载文件。 在加载文件的过程中,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 阶段,从配置中心加载配置。