自从有了spring-cloud-alibaba的开源之后,springcloud中使用nacos进行服务的注册与发现就已变得非常容易,只需要引入“spring-cloud-starter-alibaba-nacos-discovery”即可,然后开启@EnableDiscoveryClient,便可以做到无缝替换eureka和consul等注册中心。
下面通过给出一个简单的案例来演示springcloud中如何使用nacos。
首先来看一下springcloud中nacos进行服务注册与发现的原理。
spring-cloud-starter-alibaba-nacos-discovery遵循了spring-cloud-common标准,实现了 AutoServiceRegistration、ServiceRegistry、Registration 这三个接口。
在springcloud应用的启动阶段,监听了WebServerInitializedEvent事件,当Web容器初始化完成后,即收到WebServerInitializedEvent 事件后,会触发注册的动作,调用ServiceRegistry的register方法,将服务注册到 Nacos Server。
NacosServerList 实现了 com.netflix.loadbalancer.ServerList 接口,并在 @ConditionOnMissingBean 的条件下进行自动注入,默认集成了Ribbon。
如果需要有更加自定义的可以使用 @Autowired 注入一个 NacosRegistration 实例,通过其持有的 NamingService 字段内容直接调用 Nacos API。
创建一个服务提供者的springcloud项目,引入如下依赖:
Greenwich.SR1
0.2.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.cloud
spring-cloud-alibaba-dependencies
${spring-cloud.alibaba.version}
pom
import
org.springframework.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
在项目的application.yml文件中配置nacos相关的配置信息如下:
如果不想使用 Nacos 作为您的服务注册与发现,可以将 spring.cloud.nacos.discovery 设置为 false。
spring:
application:
name: nacos-service-provider
cloud:
nacos:
discovery:
register-enabled: true
server-addr: 127.0.0.1:8848
weight: 1
namespace: dev
management:
endpoints:
web:
exposure:
include: "*"
server:
port: 8080
接着便是创建一个服务,供调用者使用,勿忘在主函数引入@EnableDiscoveryClient注解。
package com.lazycece.scac.nacos.discovery.provider.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author lazycece
* @date 2019/03/19
*/
@RestController
@RequestMapping("/nacos")
public class NacosProviderController {
@GetMapping("/provider/{name}")
public String provider(@PathVariable String name) {
return "hello," + name;
}
}
创建一个服务消费者的springcloud项目,引入如下依赖,这里多引入了open-feign和ribbon的依赖,是为了同时演示这两种方式的消费。
Greenwich.SR1
0.2.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.cloud
spring-cloud-alibaba-dependencies
${spring-cloud.alibaba.version}
pom
import
org.springframework.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.cloud
spring-cloud-starter-openfeign
在项目的application.yml文件中配置nacos相关的配置信息如下:
如果不想使用 Nacos 作为您的服务注册与发现,可以将 spring.cloud.nacos.discovery 设置为 false.
spring:
application:
name: nacos-service-consumer
cloud:
nacos:
discovery:
register-enabled: true
server-addr: 127.0.0.1:8848
weight: 1
namespace: dev
management:
endpoints:
web:
exposure:
include: "*"
server:
port: 8081
创建服务消费者的代码如下,勿忘在主函数引入@EnableDiscoveryClient注解。
package com.lazycece.scac.nacos.discovery.consumer.controller;
import com.lazycece.scac.nacos.discovery.consumer.api.FeignConsumerApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author lazycece
* @date 2019/03/19
*/
@RestController
@RequestMapping("/nacos/consumer")
public class NacosConsumerController {
private LoadBalancerClient loadBalancerClient;
private RestTemplate restTemplate;
private FeignConsumerApi feignConsumerApi;
@Autowired
public NacosConsumerController(LoadBalancerClient loadBalancerClient, RestTemplate restTemplate,
FeignConsumerApi feignConsumerApi) {
this.loadBalancerClient = loadBalancerClient;
this.restTemplate = restTemplate;
this.feignConsumerApi = feignConsumerApi;
}
@GetMapping("/rest/{name}")
public String rest(@PathVariable String name) {
ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-service-provider");
String url = String.format("http://%s:%s/nacos/provider/%s",
serviceInstance.getHost(), serviceInstance.getPort(), name);
System.out.println("url -> " + url);
return restTemplate.getForObject(url, String.class);
}
@GetMapping("/feign/{name}")
public String feign(@PathVariable String name) {
return feignConsumerApi.provider(name);
}
@GetMapping("/ribbon/{name}")
public String ribbon(@PathVariable String name) {
return restTemplate.getForObject("http://nacos-service-provider/nacos/provider/" +
name, String.class);
}
}
要使用rest方式消费,需要注入RestTemplate,如果需要用ribbon来进行负载均衡,则可以@LoadBalanced注解,否则可以不加。
package com.lazycece.scac.nacos.discovery.consumer.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author lazycece
* @date 2019/03/19
*/
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
使用feign方式消费,需要有feign的client,如下,且项目主函数还需引入@EnableFeignClients
注解。
package com.lazycece.scac.nacos.discovery.consumer.api;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author lazycece
* @date 2019/03/19
*/
@FeignClient("nacos-service-provider")
@RequestMapping("/nacos")
public interface FeignConsumerApi {
@GetMapping("/provider/{name}")
String provider(@PathVariable String name);
}
需要先启动nacos-server服务,安装部署详见 nacos安装部署
spring-cloud-starter-alibaba-nacos-discovery 在实现的时候提供了一个EndPoint,EndPoint的访问地址为 http://ip:port/actuator/nacos-discovery 。因为我们加了 spring-boot-starter-actuator 依赖,所以可以查看endpoint信息。EndPoint 的信息主要提供了两类:
其中一个服务实例访问 EndPoint 的信息如下所示:
{
"subscribe":[
],
"NacosDiscoveryProperties":{
"serverAddr":"127.0.0.1:8848",
"endpoint":"",
"namespace":"dev",
"logName":"",
"service":"nacos-service-provider",
"weight":1,
"clusterName":"DEFAULT",
"namingLoadCacheAtStart":"false",
"metadata":{
},
"registerEnabled":true,
"ip":"192.168.3.8",
"networkInterface":"",
"port":8080,
"secure":false,
"accessKey":"",
"secretKey":""
}
}
访问 http://localhost:8848/nacos/ 进入nacos的管理界面,查看 服务管理->服务列表 模块,便可以看到我们的服务消费者和提供者已经注册到nacos上了,如下图所示:
这里需要先启动nacos服务,然后启动上面两个服务,访问如下地址:
http://localhost:8081/nacos/consumer/rest/lazycece
http://localhost:8081/nacos/consumer/ribbon/lazycece
http://localhost:8081/nacos/consumer/feign/lazycece
输出信息:hello,lazycece
关于 spring-cloud-starter-alibaba-nacos-discovery 中的其他配置信息如下图所示:
案例源码地址:
https://github.com/lazycece/springcloud-actual-combat/tree/master/springcloud-ac-alibaba/springcloud-ac-alibaba-nacos-discovery