Nacos 服务注册与配置中心
字数: 0 字 时长: 0 分钟
简介
Nacos 是一个易于构建云原生应用的动态服务发现、配置管理和服务管理平台
安装
- docker 安装
shell
docker run -d -p 8848:8848 -p 9848:9848 -e MODE=standalone --name nacos nacos/nacos-server:v2.4.3
- 官方下载地址:https://nacos.io/download/nacos-server/
- 单机模式启动:
startup.cmd -m standalone
服务注册中心
引入依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
整合配置
- 在
application.yml
中配置nacos
地址,默认127.0.0.1:8848
yml
spring:
application:
name: service-order
profiles:
active: dev
cloud:
nacos:
server-addr: 127.0.0.1:8848
- 开启服务注册/发现功能
java
@EnableDiscoveryClient //核心注解
@SpringBootApplication
public class OrderMainApplication {
public static void main(String[] args) {
SpringApplication.run(OrderMainApplication.class, args);
}
}
查看效果
访问 http://127.0.0.1:8848/nacos/
可以看到 service-order
服务注册成功
服务发现
在代码里面可以通过 DiscoveryClient
或 NacosServiceDiscovery
从注册中心获取服务
java
@SpringBootTest(classes = ProductMainApplication.class)
public class DiscoveryTest {
@Resource
private DiscoveryClient discoveryClient;
@Resource
private NacosDiscoveryClient nacosDiscoveryClient;
@Test
void discoveryClientTest() {
for (String service : discoveryClient.getServices()) {
List<ServiceInstance> instances = discoveryClient.getInstances(service);
for (ServiceInstance instance : instances) {
System.out.println("ip:" + instance.getHost());
System.out.println("port:" + instance.getPort());
}
}
}
@Test
void nacosDiscoveryClientTest() {
for (String service : nacosDiscoveryClient.getServices()) {
List<ServiceInstance> instances = nacosDiscoveryClient.getInstances(service);
for (ServiceInstance instance : instances) {
System.out.println("ip:" + instance.getHost());
System.out.println("port:" + instance.getPort());
}
}
}
}
远程调用
版本1:直接调用
- 向容器注册
RestTemplate
java
@Configuration
public class OrderServiceConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
- 先通过
discoveryClient
获取服务信息,再通过RestTemplate
远程调用
java
@Resouce
RestTemplate restTemplate;
// 第一版 获取商品服务信息,远程调用
private Product getProductFromRemote(Long productId) {
// 1、获取商品服务所在的所有机器 IP 和 port
List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
ServiceInstance serviceInstance = instances.get(0);
// http://127.0.0.1:9000/product/1
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/product/" + productId;
log.info("远程请求:{}",url);
return restTemplate.getForObject(url, Product.class);
}
RestTemplate
远程调用
- 使用
RestTemplate
可以进行远程调用 - 必须精确指定调用地址和端口
- 如果远程宕机将不可用
版本2:负载均衡调用
第一种使用 RestTemplate
指定 IP
和 端口号
发送 HTTP 请求的方式,如果远程宕机,则调用失败
所以考虑远程服务启动多个节点,采用负载均衡策略进行访问,保证服务高可用
- 引入
负载均衡
依赖
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
- 使用
LoadBalancerClient
负载均衡客户端
loadBalancerClient.choose("service-product")
会负载均衡地获取 service-product
的服务地址
java
@Resource
LoadBalancerClient loadBalancerClient;
//第二版 通过 loadBalancerClient 负载均衡远程调用
private Product getProductFromRemoteWithLoadBalance(Long productId) {
// 1、获取商品服务所在的所有机器 IP 和 port
ServiceInstance instance = loadBalancerClient.choose("service-product");
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/product/" + productId;
log.info("远程请求:{}",url);
return restTemplate.getForObject(url, Product.class);
}
版本3:基于注解的负载均衡
- 为
RestTemplate
添加注解@LoadBalanced
java
@Configuration
public class OrderServiceConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
- 基于注解的负载均衡,不需要
LoadBalancerClient
java
//第三版 通过 restTemplate 加注解 负载均衡远程调用
public Product getProductFromRemoteWithLoadBalance2(Long productId) {
// restTemplate 负载均衡自动替换 service-product 为服务 IP + port
String url = "http://service-product/product/" + productId;
return restTemplate.getForObject(url, Product.class);
}
如果注册中心宕机,远程调用是否可用?
- 从未调用过,如果宕机,调用直接失败
- 调用过,如果宕机,不影响,因为有缓存名单
- 调用过,如果对方服务也宕机,则调用会阻塞后失败
配置中心
1. 依赖引入
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2. 配置整合
application.yml
中配置spring.config.import
yaml
spring:
config:
import: nacos:service-order.properties
cloud:
nacos:
server-addr: 127.0.0.1:8848
nacos
中编写配置文件
- 3. 编写代码进行测试
java
//用于自动刷新 配置中心配置值
@RefreshScope
@RestController
public class OrderController {
@Value("${order.timeout}")
String orderTimeout;
@Value("${order.auto-confirm}")
String orderAutoConfirm;
@GetMapping("/config")
public String config() {
return "orderTimeout:" + orderTimeout + ",orderAutoConfirm:" + orderAutoConfirm;
}
}
- 成功读取到,而且
@RefreshScope
支持自动刷新
使用 ConfigurationProperties
自动绑定
springboot
的自动绑定功能可以批量读取 nacos
的配置中心配置,而且支持自动刷新
java
@Data
@Component
@ConfigurationProperties(prefix = "order")
public class OrderProperties {
private String timeout;
private String autoConfirm;
}
配置监听
Nacos 中的 NacosConfigManager
可以监听配置文件变化,并拿到变化值
案例: 项目一启动就监听配置文件变化,当配置文件变化时发送邮件
java
@Bean
ApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager) {
return args -> {
ConfigService configService = nacosConfigManager.getConfigService();
configService.addListener("service-order.properties", "DEFAULT_GROUP"
, new Listener() {
@Override
public Executor getExecutor() {
//随便创建一个固定大小的线程池
return Executors.newFixedThreadPool(4);
}
@Override
public void receiveConfigInfo(String s) {
System.out.println("变化的配置信息: " + s);
System.out.println("发送邮件");
}
});
};
}
配置中心的配置文件和微服务的 application.yml
配置文件的优先级谁高?
配置中心的目的是为了统一管理微服务的环境变量,如果配置中心与微服务中的配置冲突,以微服务的配置为准的话, 那么配置中心将无法统一管理各微服务的配置信息,因此配置中心配置文件优先级高
数据隔离
根据环境不同,指定不同的配置文件
yaml
spring:
application:
name: service-order
profiles:
active: dev
cloud:
nacos:
server-addr: 127.0.0.1:8848
---
spring:
config:
import:
- nacos:common.properties?group=order
- nacos:database.properties?group=order
activate:
on-profile: dev
---
spring:
config:
import:
- nacos:common.properties?group=order
- nacos:database.properties?group=order
- nacos:haha.properties?group=order
activate:
on-profile: test
---
spring:
config:
import:
- nacos:common.properties?group=order
- nacos:database.properties?group=order
- nacos:haha.properties?group=order
activate:
on-profile: prod