使用Nacos实现服务注册与发现

265 阅读4分钟

nacos.io/zh-cn/index… 官网

什么是 Nacos

Nacos: 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台

Nacos官网中对它有详细的介绍,这里不过多展示,下面直接进行实操:

安装与运行nacos

github.com/alibaba/nac…

我这里使用的版本为 1.4.0

Nacos 1.X 是老版本,2.X版本是新版(目前有这2大版本)

2.X在启动时,需要修改部分配置,具体请查看官网

下载 nacos-server-$version.zip 包。完成之后,解压。根据不同平台,执行不同命令,启动单机版Nacos服务:

 unzip nacos-server-$version.zip 
 ## 或者 tar -xvf nacos-server-$version.tar.gz
 cd nacos/bin

启动服务

注:Nacos的运行需要以至少2C4g60g*3的机器配置下运行。

Linux/Unix/Mac

启动命令(standalone代表着单机模式运行,非集群模式):

 sh startup.sh -m standalone

如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

 bash startup.sh -m standalone

Windows

启动命令(standalone代表着单机模式运行,非集群模式):

 startup.cmd -m standalone

启动成功

在日志输出中看到巨大的nacos标志以及

 INFO Nacos started successfully in stand alone mode. use embedded storage

则表示服务启动成功

页面访问

启动完成之后,访问:http://127.0.0.1:8848/nacos/,可以进入Nacos的服务管理页面;

默认用户名密码为:nacos

可能出现的问题

服务启动失败

启动后,页面提示:

 nohup: /Library/Internet: No such file or directory

大概率论是因为jdk没配置对。nacos会使用系统默认的Java_Home,而mac自带的jdk并不满足nacos的要求(路径Internet Plug-Ins中存在一个空格,这个空格会导致shell脚本失效)。

解决方案--2种:

  • 修改nacos的配置文件,将可用的jdk环境配置给nacos
  • 修改系统默认的jdk环境

这里我使用修改nacos配置文件的方式

  • 打开nacos/bin/starup.cmd (windows环境下) 其他环境则是 starup.sh
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
export JAVA="$JAVA_HOME/bin/java"
export BASE_DIR=`cd $(dirname $0)/..; pwd`
export DEFAULT_SEARCH_LOCATIONS="classpath:/,classpath:/config/,file:./,file:./config/"
export CUSTOM_SEARCH_LOCATIONS=file:${BASE_DIR}/conf/,${DEFAULT_SEARCH_LOCATIONS}

#==================================
# JVM Configuration

#============================

以上是文件中的部分内容,将JAVA_HOME后的路径设置成可以用的jdk路径即可,以上路径为我电脑的路径,大家根据自己的实际情况来修改。

编写对应微服务

在成功启动nacos后,我们尝试编写一些简单的应用,来实验nacos的服务注册与发现功能。

实现服务提供者

  1. 引入对应pom坐标
  • 创建一个SpringBoot应用,并引入Nacos的服务注册与发现模块
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>2.6.3</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
     <groupId>com.cogar.nacos</groupId>
     <artifactId>nacosDiscovery</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     <name>nacosDiscovery</name>
     <description>Demo project for Spring Boot</description>
 ​
     <properties>
         <java.version>1.8</java.version>
         <spring.cloud.version>2021.0.1</spring.cloud.version>
         <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
     </properties>
 ​
     <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>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>
     <dependencies>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
         <!-- nacos发现与注册模块-->
         <dependency>
             <groupId>com.alibaba.cloud</groupId>
             <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
         </dependency>
 ​
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <optional>true</optional>
         </dependency>
        
     </dependencies>

由于在dependencyManagement中已经引入了版本,所以这里就不用指定具体版本了

  • application.properties(或 application.yml) 中配置 Nacos server 的地址:
 server.port=8809
 spring.application.name=service-provider
 ​
 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
  1. 开启服务注册发现功能

通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能:

 @EnableDiscoveryClient
 @SpringBootApplication
 public class NacosDiscoveryApplication {
 ​
     public static void main(String[] args) {
         SpringApplication.run(NacosDiscoveryApplication.class, args);
     }
 ​
 }
  1. 编写我们自己需要的功能与服务,这里就简单的实现一下:
 @RestController
 public class TestController {
 ​
     @GetMapping("/hello/{echo}")
     public String echoHello(@PathVariable("echo")String echo){
         return "this is service-provider :"+echo;
     }
 }
  1. 完成后启动项目,之后就能看到这样一行日志,且在nacos的管理页,也能看到多了一个服务
  INFO 10852 --- [ main] c.a.c.n.registry.NacosServiceRegistry    : nacos registry, DEFAULT_GROUP service-provider x.x.x.x:8809 register finished

ar-1.png

到此,一个简单的服务提供者编写完成。

实现服务消费者

所谓的消费者就是指可以通过 Nacos 从 Nacos server 上获取到它要调用的服务(服务提供者提供的)。

  1. 导入对应的pom坐标
 <!--2020版本就已经不再使用netflix,自然也就没有了ribbon。怎么办?使用Spring Cloud Load Balancer代替-->
 <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-loadbalancer</artifactId>
 </dependency>

这里跟之前服务提供者的pom几乎一样,只是多了一个loadbalancer。如果不加在消费者进行调用时,会出现UnknownHostException

  1. 在配置文件 application.properties(或 application.yml)进行服务的配置
 server.port=8088
 spring.application.name=service-consumer
 ​
 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
  1. 通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能。
  • 启动类加注解,开启服务注册与发现
 @EnableDiscoveryClient
 //在启动类出加
  • AppConfig.java
 @Configuration
 public class AppConfig {
 ​
     @LoadBalanced
     @Bean
     public RestTemplate restTemplate() {
         return new RestTemplate();
     }
   // @LoadBalanced :实现了服务名的调用,同时开启基于服务名的负载均衡调用
   // 不加在后续调用其他服务时 则只能通过ip的方式 
 }

定义RestTemplate的时候,增加了@LoadBalanced注解(该注解实现了@LoadBalanced 与 Ribbon 的集成),在真正调用服务接口的时候,原来host部分是通过手工拼接ip和端口的,现在直接采用服务名即可。

在真正调用的时候,Spring Cloud会将请求拦截下来,然后通过负载均衡器选出节点,并替换服务名部分为具体的ip和端口,从而实现基于服务名的负载均衡调用

 @RestController
 public class DemoController {
 ​
     private final RestTemplate restTemplate;
 ​
     @Autowired
     public DemoController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}
   
       @GetMapping(value = "/print/{str}")
     public String test(@PathVariable String str) {
         return restTemplate.getForObject("http://service-provider/hello/" + str, String.class);
       // 调用服务提供者 提供的接口
     }
 }
  1. 启动项目并对消费者提供的接口进行调用(提供者跟消费者都要同时启动),

一些注意事项

该项目使用的SpringBoot及cloud版本信息为:

 <spring.cloud.alibaba.version>2021.0.1.0</spring.cloud.alibaba.version>
 <spring.boot.version>2.6.3</spring.boot.version>
 <spring.cloud.version>2021.0.1</spring.cloud.version>

某些版本可以不用额外引入loadbalancer也能进行服务调用

下面是SpringBoot、SpringCloud以及SpringCloud Alibaba的版本对应关系

版本对应关系

nacos官网