今天我们来学习 Nacos 注册中心。
我们来新建两个项目,order 跟 user。order 使用 RestTemplate 调用 user。
一、新建项目
1、新建父项目
1.1、使用 Spring Initializer 新建一个父项目 mall4cloud
Dependencies 可以什么都不选,后面自己改。
1.2、删掉 src 目录
1.3、修改父项目 pom.xml
根据 SpringCloud 与 SpringCloudAlibaba 依赖版本说明
选择好 Spring Boot、Spring Cloud、Spring Cloud Alibaba 的版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- parent 继承公司自定义的父maven项目 -->
<groupId>com.study</groupId>
<artifactId>mall4cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mall4cloud</name>
<description>mall4cloud</description>
<!-- 注意是 pom -->
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
<spring.cloud.version>2021.0.5</spring.cloud.version>
<spring.cloud.alibaba.version>2021.0.5.0</spring.cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!--Spring Boot 的版本管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--Spring Cloud 的版本管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--Spring Cloud Alibaba 的版本管理-->
<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>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.study.mall4cloud.Mall4cloudApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
注意:
<scope>import</scope> 只能在 dependencyManagement 中使用,它的作用是将另一个 POM 文件里的 dependencyManagement 信息导入到当前 POM 文件的 dependencyManagement 中。此范围仅适用于 <type>pom</type> 的依赖。
2、新建子模块 user
2.1、使用 Maven Initializer 新建一个子模块 user
2.2、 修改 user 项目 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.study</groupId>
<artifactId>mall4cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>user</artifactId>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--Spring Boot Web 场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Spring Cloud Alibaba Nacos 注册中心客户端 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 新版本的 Nacos 不再依赖 Ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!--Spring Boot 测试场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2.3、 新建 UserApplication
删除 App,新建 UserApplication
package com.study.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
2.4、添加 RestConfig
package com.study.order.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
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;
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
注意 @LoadBalanced 注解没加,远程调用会报错
2.5、添加 application.yml
server:
port: 8020
spring:
cloud:
nacos:
discovery:
username: nacos
password: nacos
group: DEFAULT_GROUP
server-addr: 127.0.0.1
application:
name: user-service
注意:
spring.application.name=user-service
2.6、添加 controller
package com.study.user.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/user")
public class UserController {
@Value("${server.port}")
private String port;
@RequestMapping("/findUserById/{id}")
public String findUserById(@PathVariable String id) {
// 模拟从数据库获取用户
Map<String, String> map = new HashMap<>();
map.put("1", "小林:"+port);
map.put("2", "小王:"+port);
return map.get(id);
}
}
3、新建子模块 order
3.1、使用 Maven Initializer 新建一个子项目 order
3.2、修改 order 项目 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.study</groupId>
<artifactId>mall4cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>order</artifactId>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--Spring Boot Web 场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Spring Cloud Alibaba Nacos 注册中心客户端 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 新版本的 Nacos 不再依赖 Ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!--Spring Boot 测试场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3.3、新建 OrderApplication
删除 App,新建 OrderApplication
package com.study.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
3.4、添加 RestConfig
package com.study.order.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
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;
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
3.5、添加 application.yml
server:
port: 8010
spring:
cloud:
nacos:
discovery:
username: nacos
password: nacos
group: DEFAULT_GROUP
server-addr: 127.0.0.1
application:
name: order-service
注意:
spring.application.name=order-service
3.6、添加 controller
package com.study.order.controller;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/placeOrder/{userId}")
public String placeOrder(@PathVariable String userId) {
// 使用服务名 user-service 调用用户服务
String response = restTemplate.getForObject("http://user-service/user/findUserById/"+userId, String.class);
return "用户[" + response + "]下单成功!";
}
}
二、启动 Nacos
根据 Spring Cloud Alibaba 组件版本关系,到 github 下载 2.2.0 Nacos。
- 修改 nacos\bin\startup.cmd 启动模式为 standalone
- 以管理员身份运行 startup.cmd
出现这一行字,就说明单机启动成功。
如果出现闪退,记得环境变量加 JAVA_HOME
因为 startup.cmd 脚本需要读取这个参数
三、启动服务
启动 order-service、user-service,访问 http://127.0.0.1:8848/nacos/index.html
输入 nacos/nacos,在服务列表就能看到我们启动的两个服务:
四、服务调用
五、负载均衡测试
5.1、复制 UserApplication 配置
在 IDEA Services 里对着 UserApplication 右键;然后点击 Copy Configuration。
添加上一条配置,server.port 8021
5.2、浏览器访问
多次访问,会发现,用户服务在 8020、8021 之间来回切换。
证明默认的负载均衡使用的是 轮询算法。
六、总结
Spring Cloud 项目接入 Nacos 步骤如下:
1、启动 nacos
2、pom.xml 中加入 nacos、loadbalancer 依赖
<dependencies>
<!--Spring Cloud Alibaba Nacos 注册中心客户端 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 新版本的 Nacos 不再依赖 Ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
</dependencies>
3、 application.yml 配置服务名、nacos 地址
spring:
cloud:
nacos:
discovery:
username: nacos
password: nacos
group: DEFAULT_GROUP
server-addr: nacos 地址
application:
name: 服务名
4、RestTemplate 加上 @LoadBalanced 注解
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
5、RestTemplate 用服务名调用
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/placeOrder/{userId}")
public String placeOrder(@PathVariable String userId) {
// 使用服务名 user-service 调用用户服务
String response = restTemplate.getForObject("http://user-service/user/findUserById/"+userId, String.class);
return "用户[" + response + "]下单成功!";
}
}