使用 Nacos 作为服务注册中心
认识 Nacos
Nacos
- 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,是阿里巴巴开源的组件。
- 官网文档 https://nacos.io/zh-cn/index.html
功能
-
动态服务配置
-
服务发现和管理
-
动态 DNS 服务
通过访问域名的方式 去访问我的服务 替我们做负载均衡 在一些不能改动的基础设施上 通过这样的域名 去做访问
Config Service(服务的配置服务) 和 Naming Service(服务注册与发现) 是重要部分
服务的消费者和提供者可以通过服务的名字 互相找到对方
使用 Nacos 作为注册中心
Spring Cloud Alibaba
-
引入 spring-cloud-alibaba-dependencies 依赖
-
替换为 spring-cloud-starter-alibaba-nacos-discovery
简单配置
- spring.cloud.nacos.discovery.server-addr
配置地址
通过 Docker 启动 Nacos
官方指引
- https://hub.docker.com/r/nacos/nacos-server
获取镜像
- docker pull nacos/nacos-server
运行 Nacos 镜像
- docker run --name nacos -d -p 8848:8848 -e MODE=standalone nacos/nacos-server
- 用户名密码为 nacos
源码
目录
spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration,\
//进行了NacosDiscovery ribbon 的自动配置
org.springframework.cloud.alibaba.nacos.ribbon.RibbonNacosAutoConfiguration,\
org.springframework.cloud.alibaba.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration
org.springframework.cloud.client.discovery.EnableDiscoveryClient=\
org.springframework.cloud.alibaba.nacos.NacosDiscoveryClientAutoConfiguration
NacosDiscoveryAutoConfiguration
@Configuration
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnClass(
name = {"org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent"}
)
@ConditionalOnProperty(
value = {"spring.cloud.service-registry.auto-registration.enabled"},
matchIfMissing = true
)
@AutoConfigureBefore({AutoServiceRegistrationAutoConfiguration.class, NacosDiscoveryClientAutoConfiguration.class})
public class NacosDiscoveryAutoConfiguration {
public NacosDiscoveryAutoConfiguration() {
}
@Bean
public NacosServiceRegistry nacosServiceRegistry() {
return new NacosServiceRegistry();//做了一个NacosServiceRegistry 进入该方法
}
@Bean
@ConditionalOnBean({AutoServiceRegistrationProperties.class})
public NacosRegistration nacosRegistration() {
return new NacosRegistration();//做了一个NacosRegistration
}
@Bean
@ConditionalOnBean({AutoServiceRegistrationProperties.class})
public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
}//配了一个自动的注册
}
NacosServiceRegistry
public class NacosServiceRegistry implements ServiceRegistry<NacosRegistration> {
private static Logger logger = LoggerFactory.getLogger(NacosServiceRegistry.class);
public NacosServiceRegistry() {
}
public void register(NacosRegistration registration) {
if (!registration.isRegisterEnabled()) {
logger.info("Nacos Registration is disabled...");
} else if (StringUtils.isEmpty(registration.getServiceId())) {
logger.info("No service to register for nacos client...");
} else {
NamingService namingService = registration.getNacosNamingService();
//通过 namingService 取得 registration 的Serviceid
String serviceId = registration.getServiceId();
Instance instance = new Instance();
instance.setIp(registration.getHost());
instance.setPort(registration.getPort());
instance.setWeight((double)registration.getRegisterWeight());
instance.setClusterName(registration.getCluster());
instance.setMetadata(registration.getMetadata());
//配置好Instance
try {
namingService.registerInstance(serviceId, instance);
//将它一起注册上去
logger.info("nacos registry, {} {}:{} register finished", new Object[]{serviceId, instance.getIp(), instance.getPort()});
} catch (Exception var6) {
logger.error("nacos registry, {} register failed...{},", new Object[]{serviceId, registration.toString(), var6});
}
}
}
public void deregister(NacosRegistration registration) {
logger.info("De-registering from Nacos Server now...");
if (StringUtils.isEmpty(registration.getServiceId())) {
logger.info("No dom to de-register for nacos client...");
} else {
NamingService namingService = registration.getNacosNamingService();
String serviceId = registration.getServiceId();
try {
namingService.deregisterInstance(serviceId, registration.getHost(), registration.getPort(), registration.getCluster());
} catch (Exception var5) {
logger.error("ERR_NACOS_DEREGISTER, de-register failed...{},", registration.toString(), var5);
}
logger.info("De-registration finished.");
}
}
public void close() {
}
public void setStatus(NacosRegistration registration, String status) {
}
public <T> T getStatus(NacosRegistration registration) {
return null;
}
}
NacosDiscoveryClient
public class NacosDiscoveryClient implements DiscoveryClient {
private static final Logger LOGGER = LoggerFactory.getLogger(NacosDiscoveryClient.class);
public static final String DESCRIPTION = "Spring Cloud Nacos Discovery Client";
@Autowired
private NacosDiscoveryProperties discoveryProperties;
public NacosDiscoveryClient() {
}
public String description() {
return "Spring Cloud Nacos Discovery Client";
}
public List<ServiceInstance> getInstances(String serviceId) {
try {
List<Instance> instances = this.discoveryProperties.namingServiceInstance().selectInstances(serviceId, true);
//通过 namingServiceInstance 里面 取得 serviceId 对应的所有 Instance 的列表
return hostToServiceInstanceList(instances, serviceId);//将它做了个转换返回
} catch (Exception var3) {
throw new RuntimeException("Can not get hosts from nacos server. serviceId: " + serviceId, var3);
}
}
private static ServiceInstance hostToServiceInstance(Instance instance, String serviceId) {
NacosServiceInstance nacosServiceInstance = new NacosServiceInstance();
nacosServiceInstance.setHost(instance.getIp());
nacosServiceInstance.setPort(instance.getPort());
nacosServiceInstance.setServiceId(serviceId);
Map<String, String> metadata = new HashMap();
metadata.put("instanceId", instance.getInstanceId());
metadata.put("weight", instance.getWeight() + "");
metadata.put("healthy", instance.isHealthy() + "");
metadata.put("cluster", instance.getClusterName() + "");
metadata.putAll(instance.getMetadata());
nacosServiceInstance.setMetadata(metadata);
return nacosServiceInstance;
}
private static List<ServiceInstance> hostToServiceInstanceList(List<Instance> instances, String serviceId) {
List<ServiceInstance> result = new ArrayList(instances.size());
Iterator var3 = instances.iterator();
while(var3.hasNext()) {
Instance instance = (Instance)var3.next();
result.add(hostToServiceInstance(instance, serviceId));
}
return result;
}
public List<String> getServices() {
try {
ListView<String> services = this.discoveryProperties.namingServiceInstance().getServicesOfServer(1, 2147483647);
return services.getData();
} catch (Exception var2) {
LOGGER.error("get service name from nacos server fail,", var2);
return Collections.emptyList();
}
}
}
我们通过springcloud提供的 DiscoveryClient 和 ServiceRegistry 这两层抽象 我们可以通过这两个抽象 去添加一套服务的注册发现机制 只要去实现它对应的接口 去做一个实现就行了
例子
目录
nacos-waiter-service
nacos-customer-service
需要修改的代码
nacos-waiter-service
application.properties
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
info.app.author=DigitalSonic
info.app.encoding=@project.build.aaa@qq.com
server.port=0
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#设置本地地址与端口
pom文件
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<spring-cloud-alibaba.version>0.2.1.RELEASE</spring-cloud-alibaba.version>
<!--设置版本号-->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 替换掉 erueka -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.joda</groupId>
<artifactId>joda-money</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.core</artifactId>
<version>6.0.1.GA</version>
</dependency>
<!-- 增加Jackson的Hibernate类型支持 -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<!-- 引入 spring-cloud-alibaba 支持 -->
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
nacos-customer-service
application.properties
server.port=0
management.endpoint.health.show-details=always
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#设置地址
pom文件
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<spring-cloud-alibaba.version>0.2.1.RELEASE</spring-cloud-alibaba.version>
<!--alibaba版本号-->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--替换掉erueka-->
<dependency>
<groupId>org.joda</groupId>
<artifactId>joda-money</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<!--引入阿里巴巴依赖-->
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
结果分析
通过 Docker 使用 docker run --name nacos -d -p 8848:8848 -e MODE=standalone nacos/nacos-server 命令创建并打开一个nacos
在游览器上输入 localhost:8848/nacos 进入 nacos 页面
使用 用户名 nacos 密码 naocs 登录
这里 我们使用 服务管理
运行 nacos-waiter-service 刷新页面 waiter-service 成功的注册了上去
点击 详情 我们可以看到 waiter-service 的详细信息
运行 nacos-customer-service 从控制台上 我们可以看到 成功的将自己注册进去 并找到 waiter-service 成功的访问到了 里面的数据
上一篇: Spring Cloud Alibaba 教程 | Nacos(六)
下一篇: C语言学习
推荐阅读
-
Nacos(四):SpringCloud项目中接入Nacos作为配置中心
-
Zookeeper作为配置中心使用说明
-
微服务架构下使用Spring Cloud Zuul作为网关将多个微服务整合到一个Swagger服务上
-
springcloud使用之服务的注册发现与消费
-
Spring Cloud Alibaba | Nacos服务中心初探
-
Nacos是什么,利用其实现微服务注册
-
服务注册中心之ZooKeeper系列(一)
-
EclipseEE的Web开发环境配置(使用Tomcat作为Web服务器)
-
SpringCloud微服务实战:一、Eureka注册中心服务端
-
微服务学习笔记(2)——使用Consul 实现 MagicOnion(GRpc) 服务注册和发现