系列文章目录
Nacos快速入门(1):启动Nacos Server
Nacos快速入门(2):整合Spring
Nacos快速入门(3):整合SpringBoot
Nacos快速入门(4):整合SpringCloud
Nacos整合示例完整代码地址:https://github.com/mrKyleWang/nacos_demo
一、springcloud应用接入Nacos
- 启动Nacos Server,参见
Nacos快速入门(1):启动Nacos Server - 项目中需要添加依赖(按需求分别添加)
注意:版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。
<!-- 1. nacos-配置管理功能依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
<!-- 2. nacos-服务发现功能依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
二、配置管理功能示例
示例场景:模拟用户服务获取配置中心的username属性,在getUser接口中返回
- 在bootstrap.properties中配置nacos.config.server的地址以及spring.application.name
- 说明:之所以需要配置 spring.application.name ,是因为它是构成 Nacos 配置管理 dataId字段的一部分,在 Nacos Spring Cloud 中,dataId 的完整格式:
- ${prefix}-${spring.profile.active}.${file-extension}
- prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
- spring.profile.active 即为当前环境对应的 profile,当 spring.profile.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
- file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型
spring.application.name=user-service
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
- 通过Spring原生注解 @Value 注解设置属性值,通过 SpringCloud 原生注解@RefreshScope 实现配置自动更新:
示例中会加载配置中username的值,如果没有则取到的值为"null"
@Controller
@RefreshScope
public class UserController {
@Value("${username:null}")
private String username;
@RequestMapping(value = "/getUser")
@ResponseBody
public String getUser() {
return username;
}
}
- 请求getUser接口,未配置username,返回默认值null
curl -X GET "http://127.0.0.1:8082/user/getUser"
null
- 增加配置,按照dataId格式和此服务的配置,dataId为:user-service.properties。(两种方式示例):
(1). Nacos管理界面添加配置
(2). 调用open api添加配置(注意使用Post方法请求)
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=exampleuser-service.properties&group=DEFAULT_GROUP&content=username=zhangsan"
- 再次调用接口,测试发现配置已更新
curl -X GET "http://127.0.0.1:8082/user/getUser"
zhangsan
三、服务注册
示例场景:将上述用户服务注册到nacos
- 在application.properties中新增配置nacos.discovery.server的地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
- 启动服务后会自动注册到nacos,服务名为之前配置的spring.application.name=user_service
四、服务发现/调用:
示例场景:模拟订单服务在getOrder接口中通过nacos服务发现调用user_server的getUser接口获取username,返回结果
- 在application.properties中配置nacos.discovery.server的地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
- 通过 SpringCloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能,注册一个RestTemplate实例用以发送请求,给RestTemplate实例添加@LoadBalanced注解,开启与Ribbon的集成用于负载均衡:
@SpringBootApplication
@EnableDiscoveryClient
public class NacosCloudOrderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosCloudOrderApplication.class, args);
}
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
- 使用RestTemplate发送请求,由于配置了服务发现,所以不需要使用ip和端口,只需要指定服务名("user-service”)和路径即可自动获取服务集群下某实例地址并发送请求:
@Controller
public class OrderController {
private Logger logger = LoggerFactory.getLogger(OrderController.class);
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/getOrder")
@ResponseBody
public Map<String, Object> getOrder() {
Map<String, Object> order = new HashMap<>();
order.put("username", queryUserName());
order.put("money", 100.00);
return order;
}
private String queryUserName() {
try {
return restTemplate.getForObject("http://user-service/user/getUser", String.class);
} catch (Exception e) {
logger.error("query user error", e);
}
return null;
}
}
- 调用订单服务的getOrder接口:成功调用user_service服务,返回正确结果
curl -X GET "http://127.0.0.1:8081/order/getOrder"
{"money":100.0,"username":"zhangsan"}
可能的问题:
- 启动接入了nacos配置管理功能的springcloud应用时,抛异常:
2019-03-13 19:32:07.019 ERROR 19543 --- [ main] o.s.c.a.nacos.NacosConfigProperties : create config service error!properties=NacosConfigProperties{...},e=,
com.alibaba.nacos.api.exception.NacosException: null
at com.alibaba.nacos.api.config.ConfigFactory.createConfigService(ConfigFactory.java:45) ~[nacos-api-0.6.2.jar:na]
at com.alibaba.nacos.api.NacosFactory.createConfigService(NacosFactory.java:41) ~[nacos-api-0.6.2.jar:na]
at org.springframework.cloud.alibaba.nacos.NacosConfigProperties.configServiceInstance(NacosConfigProperties.java:347) ~[spring-cloud-alibaba-nacos-config-0.2.1.RELEASE.jar:0.2.1.RELEASE]
at org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator.locate(NacosPropertySourceLocator.java:63) [spring-cloud-alibaba-nacos-config-0.2.1.RELEASE.jar:0.2.1.RELEASE]
at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:94) [spring-cloud-context-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:633) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
解决:SprongCloud整合NacosConfig异常:create config service error! (NacosException: null)
- 接入nacos服务发现功能后,调用相应服务时,抛异常:
java.lang.IllegalStateException: Request URI does not contain a valid hostname
可能原因和解决:使用ribbon实现负载均衡的时候,服务名称不能用下划线,换成中划线