什么是 Nacos
Nacos: 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos官网中对它有详细的介绍,这里不过多展示,下面直接进行实操:
安装与运行nacos
我这里使用的版本为 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的服务注册与发现功能。
实现服务提供者
- 引入对应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
- 开启服务注册发现功能
通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能:
@EnableDiscoveryClient
@SpringBootApplication
public class NacosDiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(NacosDiscoveryApplication.class, args);
}
}
- 编写我们自己需要的功能与服务,这里就简单的实现一下:
@RestController
public class TestController {
@GetMapping("/hello/{echo}")
public String echoHello(@PathVariable("echo")String echo){
return "this is service-provider :"+echo;
}
}
- 完成后启动项目,之后就能看到这样一行日志,且在nacos的管理页,也能看到多了一个服务
INFO 10852 --- [ main] c.a.c.n.registry.NacosServiceRegistry : nacos registry, DEFAULT_GROUP service-provider x.x.x.x:8809 register finished
到此,一个简单的服务提供者编写完成。
实现服务消费者
所谓的消费者就是指可以通过 Nacos 从 Nacos server 上获取到它要调用的服务(服务提供者提供的)。
- 导入对应的pom坐标
<!--2020版本就已经不再使用netflix,自然也就没有了ribbon。怎么办?使用Spring Cloud Load Balancer代替-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
这里跟之前服务提供者的pom几乎一样,只是多了一个loadbalancer。如果不加在消费者进行调用时,会出现UnknownHostException
- 在配置文件
application.properties(或application.yml)进行服务的配置
server.port=8088
spring.application.name=service-consumer
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
- 通过 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);
// 调用服务提供者 提供的接口
}
}
- 启动项目并对消费者提供的接口进行调用(提供者跟消费者都要同时启动),
- 调用http://127.0.0.1:8088/print/master接口
- 看到返回内容为:this is service-provider :master
一些注意事项
该项目使用的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的版本对应关系