一、创建空的spring Boot项目
1.创建spring boot项目,然后删除src目录,仅保留pom.xml
2.编辑pom.xml
第一步:将打包方式修改为pom;
第二步:引入平时创建spring boot的依赖。
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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath />
</parent>
<groupId>com.namejr</groupId>
<artifactId>LearnSCDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- spring cloud中,父工程使用pom -->
<packaging>pom</packaging>
<name>LearnSCDemo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<!-- 引入依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3.创建子模块
创建后目录:
创建后,父工程的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>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.2</version> <relativePath /> </parent> <groupId>com.namejr</groupId> <artifactId>LearnSCDemo</artifactId> <version>1.0-SNAPSHOT</version> <!-- spring cloud中,父工程使用pom --> <packaging>pom</packaging> <name>LearnSCDemo</name> <url>http://maven.apache.org</url> <modules> <module>SCFirstDemo</module> <module>SCTwoDemo</module> </modules> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
子工程(两个内容除了name/artifactId,其余都一样)
<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.namejr</groupId> <artifactId>LearnSCDemo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>SCFirstDemo</artifactId> <packaging>jar</packaging> <name>SCFirstDemo</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> </dependencies> </project>
SCFirstDemo和SCTwoDemo的application.properties
SCFirstDemo的application.properties # 端口号配置 server.port=8081 SCTwoDemo的application.properties # 端口号配置 server.port=8082
SCFirstDemoStartApplication/SCTwoDemoStartApplication(除了class类名,其余一样)
package com.namejr; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SCTwoDemoStartApplication { public static void main(String[] args) { SpringApplication.run(SCTwoDemoStartApplication.class, args); } }
两个项目的PublicController
SCFirstDemo项目 package com.namejr.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/api/SCFirstPublic") public class PublicController { /** * 获取服务器时间 * */ @RequestMapping(value = "/getStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getStringInfo() { return "SCFirstString"; } } SCTwoDemo项目
package com.namejr.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/api/SCTwoPublic")
public class PublicController {
/**
* 获取服务器时间
* */
@RequestMapping(value = "/getStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
public String getStringInfo() {
return "SCTwoString";
}
}
同时运行两个项目,即可访问到对应的内容
注:至此,spring cloud中关于spring boot相关的项目搭建已完成,剩下的就是将开始 引入spring cloud的相关配件。
二、Nacos注册中心、配置中心和高可用集群配置
注册中心
Nacos的安装和配置如:Nacos下载与安装 - 闪电龟龟 - 博客园 (cnblogs.com)
1.pom.xml
所有子服务均的pom.xml都引入依赖包
SCFirstDemo的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.namejr</groupId> <artifactId>LearnSCDemo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>SCFirstDemo</artifactId> <packaging>jar</packaging> <name>SCFirstDemo</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- nacos注册中心子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies> </project> SCTwoDemo的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.namejr</groupId> <artifactId>LearnSCDemo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>SCTwoDemo</artifactId> <packaging>jar</packaging> <name>SCTwoDemo</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- nacos注册中心子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies> </project>
2.所有配置均配置nacos服务内容
注:网上说的一定要依赖于bootstrap.yml,但不然,如果有多个配置的情况下,了解其顺序加载规则即可。bootstrap.properties -> bootstrap.yml ->application.properties -> application.yml
注意!!!注意!!!注意!!! 上面这句话很重要,因为后面开启权限验证的时候,您会发现这个顺序很重要。
SCFirstDemo的application.properties # 配置nacos # 服务名称 spring.application.name=scFirstDemo # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 SCTwoDemo的application.properties # 配置nacos # 服务名称 spring.application.name=scTwoDemo # Nacos服务注册中心地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
注:此时登录到nacos后台,会发现已经存在两个服务
注:部分文档通过@EnableDiscoveryClient注解进行开启服务注册发现功能,目前发现没有配置仍然可以使用 。有相关文档描述是因为新版本无需使用的缘故,详情请看EnableDiscoveryClient与EnableEurekaClient的区别、Cloud-2.0以后无需增加_enablediscoveryclient有必要加吗-CSDN博客。
3.创建一个(非负载均衡的)不同子服务之间的访问,如:SCTwoDemo访问SCFirstDemo的api/SCFirstPublic/getStringInfo接口
在SCTwoDemoStartApplication.java中,创建RestTemplate的Bean(也可以放在其它地方,这里只是省略了多余步骤)
SCTwoDemoStartApplication.java package com.namejr; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication public class SCTwoDemoStartApplication { public static void main(String[] args) { SpringApplication.run(SCTwoDemoStartApplication.class, args); } @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
在PublicController.java的中访问(同理可以放在其它地方)
PublicController.java package com.namejr.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController @RequestMapping(value = "/api/SCTwoPublic") public class PublicController { @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; /** * 获取服务器时间 * */ @RequestMapping(value = "/getStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getStringInfo() { return "SCTwoString"; } /** * 获取scFirstDemo服务的内容 * */ @RequestMapping(value = "/getSCFirstDemoStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getSCFirstDemoStringInfo() { List<ServiceInstance> list = discoveryClient.getInstances("scFirstDemo"); ServiceInstance serviceInstance = list.get(0); // get请求方式有后缀直接加后面,如:api/SCFirstPublic/getStringInfo?tempA=AAAA return restTemplate.getForObject("http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/api/SCFirstPublic/getStringInfo", String.class); } }
输出内容:
注:至此,nacos的注册中心内容已经完成,配置中心请往下看。
配置中心
1.先到nacos中配置需要依赖的配置文件
发布后即可通过代码获取配置中心配置内容
2.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.namejr</groupId>
<artifactId>LearnSCDemo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>SCFirstDemo</artifactId>
<packaging>jar</packaging>
<name>SCFirstDemo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- nacos注册中心子服务依赖包 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- nacos配置中心子服务依赖包 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 自2.4版本之后,默认bootstrap处于禁用状态,需要手动引入 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
</project>
3.配置文件配置
# 端口号配置 server.port=8081 # 配置nacos # 服务名称 spring.application.name=scFirstDemo # 指定环境 # spring.profiles.active=public # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 # 配置中心 # 配置中心服务地址 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # 指定后缀 spring.cloud.nacos.config.file-extension:properties # 动态刷新配置 # spring.cloud.nacos.config.refresh-enable=true # 指定开发环境 # spring.cloud.nacos.config.namespace=public # 指定分组 # spring.cloud.nacos.config.group:DEFAULT_GROUP
4.配置获取配置中心的Bean
package com.namejr.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties
public class SCFirstDemoConfigModel {
public String getTempIP() {
return tempIP;
}
public void setTempIP(String tempIP) {
this.tempIP = tempIP;
}
@Value(value = "${scfdemo.configuration.ip}")
private String tempIP;
}
5.配置获取接口
package com.namejr.controller;
import com.namejr.bean.SCFirstDemoConfigModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/api/SCFirstPublic")
public class PublicController {
@Autowired
private SCFirstDemoConfigModel tempscfdConfig;
/**
* 获取配置中心配置内容
* */
@RequestMapping(value = "/getConfiguInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
public String getConfiguInfo() {
return tempscfdConfig.getTempIP();
}
/**
* 获取服务器时间
* */
@RequestMapping(value = "/getStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
public String getStringInfo() {
return "SCFirstString";
}
}
访问输出:
至此,配置中心相关配置到此结束。
高可用集群配置--服务提供方
Ncos的高可用集群配置的节点配置具体可查看笔记:Nacos下载与安装 - 闪电龟龟 - 博客园 (cnblogs.com)中的“五、Nacos集群配置”
代码配置方式一:不使用Nginx进行代理,然后通过配置多个集群节点地址
application.properties配置文件
SCFirstDemo的配置文件
# 端口号配置
server.port=8081
# 配置nacos
# 服务名称
spring.application.name=scFirstDemo
# 指定环境
# spring.profiles.active=public
# 配置集群节点地址
spring.cloud.nacos.server-addr=192.168.129.131:8848,192.168.129.131:30101,192.168.129.131:30201,192.168.129.131:30301
# Nacos服务注册中心地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
# 配置中心
# 配置中心服务地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# 指定后缀
spring.cloud.nacos.config.file-extension:properties
# 动态刷新配置
# spring.cloud.nacos.config.refresh-enable=true
# 指定开发环境
# spring.cloud.nacos.config.namespace=public
# 指定分组
# spring.cloud.nacos.config.group:DEFAULT_GROUP
SCFirstDemo的配置文件
# 端口号配置
server.port=8082
# 配置nacos
# 服务名称
spring.application.name=scTwoDemo
# 配置集群节点地址
spring.cloud.nacos.server-addr=192.168.129.131:8848,192.168.129.131:30101,192.168.129.131:30201,192.168.129.131:30301
# Nacos服务注册中心地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
开启多个SCFirstDemo服务并绑定到对应的集群上,开启方式如:运行spring cloud 开启多个服务 - 闪电龟龟 - 博客园 (cnblogs.com),各服务之间虚拟机配置有如下内容:
-Dserver.port=8083 -Dspring.cloud.nacos.config.server-addr=127.0.0.1:30101 -Dspring.cloud.nacos.discovery.server-addr=127.0.0.1:30101 -Dserver.port=8084 -Dspring.cloud.nacos.config.server-addr=127.0.0.1:30201 -Dspring.cloud.nacos.discovery.server-addr=127.0.0.1:30201 -Dserver.port=8085 -Dspring.cloud.nacos.config.server-addr=127.0.0.1:30301 -Dspring.cloud.nacos.discovery.server-addr=127.0.0.1:30301
当通过127.0.0.1:8082/api/SCTwoPublic/getSCFirstDemoStringInfo 进行访问时,会发现有四个SCFirstDemo服务
代码配置方式二:使用Nginx进行代理,然后通过一个代理接口进行访问
不需要配置application.properties的配置文件的spring.cloud.nacos.server-addr,通过nginx进行反向代理/负载均衡到各个服务器即可,修改 ./conf/nginx.conf文件下的http节点配置如下:
http {
...
# 配置集群列表
upstream nacos1 {
# 集群列表
server 192.168.230.129:9848;
server 192.168.230.130:9848;
server 192.168.230.131:9848;
}
....
server {
listen 80;
server_name 集群名称,如nacos1;
...
}
...
}
注:使用nginx,在application.properties的配置文件只要将其spring.cloud.nacos.discovery.server-addr配置成nnginx的服务地址即可,如本例子:配置成:127.0.0.1:80
高可用集群配置--服务消费方
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.namejr</groupId> <artifactId>LearnSCDemo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>SCTwoDemo</artifactId> <packaging>jar</packaging> <name>SCTwoDemo</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- nacos注册子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- 引入负载均衡处理 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> </dependencies> </project>
添加负载均衡的bean
package com.namejr; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication public class SCTwoDemoStartApplication { public static void main(String[] args) { SpringApplication.run(SCTwoDemoStartApplication.class, args); } @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } @Bean @LoadBalanced public RestTemplate getLoadBalancedRestTemplate(){ return new RestTemplate(); } }
通过负载均衡访问接口
服务控制器
package com.namejr.controller; import com.namejr.bean.SCFirstDemoConfigModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/api/SCFirstPublic") public class PublicController { @Value(value = "${server.port}") private Integer port; @Autowired private SCFirstDemoConfigModel tempscfdConfig; /** * 获取配置中心配置内容 * */ @RequestMapping(value = "/getConfiguInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getConfiguInfo() { return tempscfdConfig.getTempIP(); } /** * 获取服务器时间 * */ @RequestMapping(value = "/getStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getStringInfo() { System.out.println(port); // 打印当前服务的端口号 return "SCFirstString"; } }
负载均衡访问控制器
package com.namejr.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController @RequestMapping(value = "/api/SCTwoPublic") public class PublicController { @Autowired private DiscoveryClient discoveryClient; @Qualifier("getRestTemplate") @Autowired private RestTemplate restTemplate;
// 因为和非负载均衡Bean(getRestTemplate)冲突,故使用QualiFier限定 @Qualifier("getLoadBalancedRestTemplate") @Autowired private RestTemplate brestTemplate; /** * 负载均衡获取处理 * */ @RequestMapping(value = "/getStringByLoadBalanced", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getStringByLoadBalanced() {
// 格式: http://服务名称/port return brestTemplate.getForObject("http://scFirstDemo/api/SCFirstPublic/getStringInfo",String.class); } /** * 获取服务器时间 * */ @RequestMapping(value = "/getStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getStringInfo() { return "SCTwoString"; } /** * 获取scFirstDemo服务的内容 * */ @RequestMapping(value = "/getSCFirstDemoStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getSCFirstDemoStringInfo() { List<ServiceInstance> list = discoveryClient.getInstances("scFirstDemo"); ServiceInstance serviceInstance = list.get(0); // get请求方式有后缀直接加后面,如:api/SCFirstPublic/getStringInfo?tempA=AAAA return serviceInstance.getHost()+":"+ serviceInstance.getPort()+" BackInfo:"+restTemplate.getForObject("http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/api/SCFirstPublic/getStringInfo", String.class); } }
访问三次127.0.0.1:8082/api/SCTwoPublic/getStringByLoadBalanced,输出如下
Nacos特别篇--开启权限验证
关于Nacos开启权限验证的配置可查看笔记:Nacos下载与安装 - 闪电龟龟 - 博客园 (cnblogs.com)中的“二、相关配置”
配置文件application.properties
SCFirstDemo的application.properties # 端口号配置 server.port=8081 # 配置nacos # 服务名称 spring.application.name=scFirstDemo # 指定环境 #spring.profiles.active=public # 配置集群节点地址 spring.cloud.nacos.server-addr=192.168.129.131:8848,192.168.129.131:30101,192.168.129.131:30201,192.168.129.131:30301 spring.cloud.nacos.username=nacos spring.cloud.nacos.password=nacos # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 # 配置中心 # 配置中心服务地址 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # 指定后缀 spring.cloud.nacos.config.file-extension=properties # 动态刷新配置 # spring.cloud.nacos.config.refresh-enable=true # 指定开发环境 # spring.cloud.nacos.config.namespace=public # 指定分组 # spring.cloud.nacos.config.group:DEFAULT_GROUP SCTwoDemo的application.properties # 端口号配置 server.port=8082 # 配置nacos # 服务名称 spring.application.name=scTwoDemo # 配置集群节点地址 spring.cloud.nacos.server-addr=192.168.129.131:8848,192.168.129.131:30101,192.168.129.131:30201,192.168.129.131:30301 spring.cloud.nacos.username=nacos spring.cloud.nacos.password=nacos # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
当然,也可以将密码单独配置
上面的 # 配置集群节点地址 spring.cloud.nacos.server-addr=192.168.129.131:8848,192.168.129.131:30101,192.168.129.131:30201,192.168.129.131:30301 spring.cloud.nacos.username=nacos spring.cloud.nacos.password=nacos # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 # 配置中心 # 配置中心服务地址 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # 指定后缀 spring.cloud.nacos.config.file-extension=properties 换成 # 配置集群节点地址 spring.cloud.nacos.server-addr=192.168.129.131:8848,192.168.129.131:30101,192.168.129.131:30201,192.168.129.131:30301 # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.nacos.discovery.username=nacos spring.cloud.nacos.discovery.password=nacos # 配置中心 # 配置中心服务地址 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # 指定后缀 spring.cloud.nacos.config.file-extension=properties spring.cloud.nacos.config.username=nacos spring.cloud.nacos.config.password=nacos
遇到的问题:
1.如果不开启权限验证,功能虽然能够正常使用,但是登录nacos界面,查看 服务管理-服务列表 一直为空,无法正常获取。解决办法:开启权限验证即可。
2.如果开启权限验证,问题1中的管理列表虽然能够正常显示,但是不能使用配置中心,或者说配置中心的内容无法正常获取(直接不能启动)。
2024-04-26 16:49:53.396 ERROR 1472 --- [ main] c.a.c.n.c.NacosPropertySourceBuilder : get data from Nacos error,dataId:scFirstDemo
com.alibaba.nacos.api.exception.NacosException: http error, code=403,msg=user not found!,dataId=scFirstDemo,group=DEFAULT_GROUP,tenant=
at com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient.queryConfig(ClientWorker.java:987) ~[nacos-client-2.2.0.jar:na]
.......
at com.namejr.SCFirstDemoStartApplication.main(SCFirstDemoStartApplication.java:11) [classes/:na]
2024-04-26 16:49:53.402 ERROR 1472 --- [ main] c.a.c.n.c.NacosPropertySourceBuilder : get data from Nacos error,dataId:scFirstDemo.properties
com.alibaba.nacos.api.exception.NacosException: http error, code=403,msg=user not found!,dataId=scFirstDemo.properties,group=DEFAULT_GROUP,tenant=
at com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient.queryConfig(ClientWorker.java:987) ~[nacos-client-2.2.0.jar:na]
...
at com.namejr.SCFirstDemoStartApplication.main(SCFirstDemoStartApplication.java:11) [classes/:na]
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2024-04-26 16:49:54.556 ERROR 1472 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SCFirstDemoConfigModel': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'scfdemo.configuration.ip' in value "${scfdemo.configuration.ip}" at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405) ~[spring-beans-5.3.22.jar:5.3.22] ....... at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) [spring-boot-2.7.2.jar:2.7.2] at com.namejr.SCFirstDemoStartApplication.main(SCFirstDemoStartApplication.java:11) [classes/:na] Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'scfdemo.configuration.ip' in value "${scfdemo.configuration.ip}" at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180) ~[spring-core-5.3.22.jar:5.3.22] ...... at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.22.jar:5.3.22] ... 17 common frames omitted
关于问题2的产生原因:根据“http error, code=403,msg=user not found!,dataId=scFirstDemo.properties,group=DEFAULT_GROUP,tenant=”中的msg可以看出,这是因为用户未查找到,但是配置文件中使用的nacos进行登录后台是没有问题的,所以可以考虑产生的原因是因为:程序在执行的时候,并没有读取到配置文件里面的账号信息,或者说仍然还未加载。
解决方法:application.**属于用户级别的应用参数配置,猜测nacos属于系统级别的读取,所以可以考虑换成bootstrap.**(系统级别的应用参数配置),即:把关于spring cloud的注册中心相关的内容由原来放在application.**配置文件移动到bootstrap.**配置文件中即可。
还得注意哈:如果您喜欢把nacos的全部的东西都丢到bootstap.**中,也不是不行哈,就是如果存在服务消费者/客户端/或者是本例子中的scTwoDemo,不要将其nacos的注册中心配置放到bootstrap.**配置文件中,否则,您将喜提访问微服务失败,例如:访问(http://127.0.0.1:8082/api/SCTwoPublic/getSCFirstDemoStringInfo/http://127.0.0.1:8082/api/SCTwoPublic/getStringByLoadBalanced),将会是403界面
三、Feign组件
SCFirstDemo项目创建服务端需要的端口
添加一个UserModel模型,用来接收post请求 package com.namejr.bean; public class UserModel { public String uname; public Integer age; } PublicController 添加get/post接口 package com.namejr.controller; import com.namejr.bean.SCFirstDemoConfigModel; import com.namejr.bean.UserModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping(value = "/api/SCFirstPublic") public class PublicController { @Value(value = "${server.port}") private Integer port; @Autowired private SCFirstDemoConfigModel tempscfdConfig; /** * 获取配置中心配置内容 * */ @RequestMapping(value = "/getConfiguInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getConfiguInfo() { return tempscfdConfig.getTempIP(); } /** * 获取服务器时间 * */ @RequestMapping(value = "/getStringInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getStringInfo() { System.out.println(port); return "SCFirstString"; } /** * get调用 * */ @RequestMapping(value = "/getUserInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getUserInfo(@RequestParam("uname") String uname) { System.out.println(port); return "接收端port:"+port+",名称:"+uname; } /** * post调用 * */ @RequestMapping(value = "/postUserInfo", method = RequestMethod.POST,produces = "application/json;charset=UTF-8") public String postUserInfo(@RequestBody UserModel model) { System.out.println(port); return "接收端port:"+port+",名称:"+model.uname+"年龄:"+model.age; } }
SCTwoDemo的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.namejr</groupId> <artifactId>LearnSCDemo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>SCTwoDemo</artifactId> <packaging>jar</packaging> <name>SCTwoDemo</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- nacos注册子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- 引入Feign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- 引入负载均衡处理 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> </dependencies> </project>
启动类加上@EnableFeignClients标记
package com.namejr; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableFeignClients public class SCTwoDemoStartApplication { public static void main(String[] args) { SpringApplication.run(SCTwoDemoStartApplication.class, args); } @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } @Bean @LoadBalanced public RestTemplate getLoadBalancedRestTemplate(){ return new RestTemplate(); } }
创建FeignClient客户端调用代码
package com.namejr.bean; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; @Component @FeignClient(name = "scFirstDemo") public interface FeignInterfaceDemo { @GetMapping(value = "/api/SCFirstPublic/getUserInfo") String getUserInfo(@RequestParam("uname") String uname); @PostMapping(value = "/api/SCFirstPublic/postUserInfo") String postUserInfo(@RequestBody UserModel model); }
添加接口访问调用FeignClient代码
package com.namejr.controller; import com.namejr.bean.FeignInterfaceDemo; import com.namejr.bean.UserModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/api/FeignController") public class FeignController { @Autowired private FeignInterfaceDemo feignInterfaceDemo; /** * 访问get接口 * */ @RequestMapping(value = "/getUserInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String getStringInfo(String name) { return feignInterfaceDemo.getUserInfo(name); } /** * 访问post接口 * */ @RequestMapping(value = "/postUserInfo", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String postUserInfo(String name,int age) { UserModel tempUserInfo=new UserModel(); tempUserInfo.uname=name; tempUserInfo.age=age; return feignInterfaceDemo.postUserInfo(tempUserInfo); } }
调用实例:
127.0.0.1:8082/api/FeignController/getUserInfo?name=namejr1 127.0.0.1:8082/api/FeignController/postUserInfo?name=namejr1&age=12
Feign特别处理--添加请求头
具体请查看OpenFeign简介和使用详解-CSDN博客,下文仅作笔记
方式一(不推荐,不灵活):
package com.namejr.bean; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; @Component @FeignClient(name = "scFirstDemo") public interface FeignInterfaceDemo { @GetMapping(value = "/api/SCFirstPublic/getUserInfo") String getUserInfo(@RequestParam("uname") String uname); @PostMapping(value = "/api/SCFirstPublic/postUserInfo",headers = "Content-Type=application/json;charset=UTF-8") String postUserInfo(@RequestBody UserModel model); }
方式二(不推荐,不灵活):
package com.namejr.bean; import feign.Headers; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; @Component @FeignClient(name = "scFirstDemo") public interface FeignInterfaceDemo { @GetMapping(value = "/api/SCFirstPublic/getUserInfo") String getUserInfo(@RequestParam("uname") String uname); @PostMapping(value = "/api/SCFirstPublic/postUserInfo") @Headers("Content-Type:application/json;charset=UTF-8") String postUserInfo(@RequestBody UserModel model); }
方式三(一般推荐,可以统一配置不需要特别处理,不过实际项目一般都是有多种处理方式的):
通过实现拦截器RequestInterceptor 处理
package com.namejr.bean; import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.stereotype.Component; @Component public class FeignRequestInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate requestTemplate) { // 添加请求头 requestTemplate.header("timestamp","0000000"); // 设置请求体 requestTemplate.body(""); } }
方式四(推荐):
package com.namejr.bean; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.*; @Component @FeignClient(name = "scFirstDemo") public interface FeignInterfaceDemo { @GetMapping(value = "/api/SCFirstPublic/getUserInfo") String getUserInfo(@RequestParam("uname") String uname); @PostMapping(value = "/api/SCFirstPublic/postUserInfo") String postUserInfo(@RequestBody UserModel model, @RequestHeader MultiValueMap<String,String> headerInfos); }
Feign特别处理--打印日志处理
举例给下面的接口配置日志
package com.namejr.bean; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; @Component @FeignClient(name = "scFirstDemo") public interface FeignInterfaceDemo { @GetMapping(value = "/api/SCFirstPublic/getUserInfo") String getUserInfo(@RequestParam("uname") String uname); @PostMapping(value = "/api/SCFirstPublic/postUserInfo") String postUserInfo(@RequestBody UserModel model); }
配置请求日志类
package com.namejr.bean; import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 配置Feign的请求日志 * */ @Configuration public class FeignConfigLog { @Bean Logger.Level beanFeignLoggerLevel(){ /** * 日志级别: * NONE:默认的,不显示任何日志; * BASIC:仅记录请求方法、URL、响应状态码及执行时间; * HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息; * FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。 * */ return Logger.Level.FULL; } }
开启对某个接口的日志
# 端口号配置 server.port=8082 # 配置nacos # 服务名称 spring.application.name=scTwoDemo # 配置集群节点地址 spring.cloud.nacos.server-addr=192.168.129.131:8848,192.168.129.131:30101,192.168.129.131:30201,192.168.129.131:30301 spring.cloud.nacos.username=nacos spring.cloud.nacos.password=nacos # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 #spring.cloud.nacos.discovery.username=nacos #spring.cloud.nacos.discovery.password=nacos # 开启Feign日志,feign日志以什么级别监控哪个接口
# logging.level.全限定类名=debug logging.level.com.namejr.bean.FeignInterfaceDemo=debug
请求访问127.0.0.1:8082/api/FeignController/postUserInfo?name=namejr1&age=12,日志打印
2024-04-27 15:56:49.373 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] ---> POST http://scFirstDemo/api/SCFirstPublic/postUserInfo HTTP/1.1 2024-04-27 15:56:49.373 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] Content-Length: 28 2024-04-27 15:56:49.373 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] Content-Type: application/json 2024-04-27 15:56:49.373 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] 2024-04-27 15:56:49.373 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] {"uname":"namejr1","age":12} 2024-04-27 15:56:49.373 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] ---> END HTTP (28-byte body) 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] <--- HTTP/1.1 200 (4ms) 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] connection: keep-alive 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] content-length: 48 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] content-type: application/json;charset=UTF-8 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] date: Sat, 27 Apr 2024 07:56:49 GMT 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] keep-alive: timeout=60 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] 接收端port:8081,名称:namejr1年龄:12 2024-04-27 15:56:49.382 DEBUG 15748 --- [nio-8082-exec-4] com.namejr.bean.FeignInterfaceDemo : [FeignInterfaceDemo#postUserInfo] <--- END HTTP (48-byte body)
四、网关(未完成)
注:后面因为电脑性能问题,后续只开3各nacos
创建子模块
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.namejr</groupId>
<artifactId>LearnSCDemo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>SCGatewayDemo</artifactId>
<packaging>jar</packaging>
<name>SCGatewayDemo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- nacos注册中心子服务依赖包 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- nacos网关依赖包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 如果配置中要使用lb://URL,那么这里的负载均衡需要显示依赖进去 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
</project>
application.properties配置文件相关配置内容
# 端口号配置
server.port=8080
# 配置nacos
# 服务名称
spring.application.name=scGatewayDemo
# 在application.yml中将web应用类型设置为REACTIVE:
spring.main.web-application-type=reactive
# 配置集群节点地址
# Nacos服务注册中心地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
# 配置网关路由配置
spring.cloud.gateway.routes[0].id=scTwoDemo
# 方式一:spring.cloud.gateway.routes[0].uri=http://127.0.0.1:8080
# 方式二:使用负载均衡,格式:lb://+服务名称
spring.cloud.gateway.routes[0].uri=http://127.0.0.1:8082
# 路由断言,也就是路由规则,符合下面的路由规则将会使用对应routes下的uri,如本例子就会路由到routes[0].uri=lb://scTwoDemo
spring.cloud.gateway.routes[0].predicates[0]=Path=/api/FeignController/**
SCGatewayDemoStartApplication.java
package com.namejr; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SCGatewayDemoStartApplication { public static void main(String[] args) { SpringApplication.run(SCGatewayDemoStartApplication.class, args); } }
访问127.0.0.1:8080/api/FeignController/getUserInfo?name=namejr1会通过网关,指向配置的spring.cloud.gateway.routes[0].uri=http://127.0.0.1:8082,输出下面信息:
问题一:如果出现下面错误
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2024-04-27 17:11:55.166 ERROR 19276 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPLICATION FAILED TO START *************************** Description: Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway. Action: Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency. 已与地址为 ''127.0.0.1:52096',传输: '套接字'' 的目标虚拟机断开连接 进程已结束,退出代码为 1
在application.properties配置文件中,加入下面内容即可
# 在application.yml中将web应用类型设置为REACTIVE:
spring.main.web-application-type=reactive
问题二:如果配置文件配置的是spring.cloud.gateway.routes[0].uri=lb://scTwoDemo,出现下面错误
那么将负载均衡显示依赖进去即可
<!-- 如果配置中要使用lb://URL,那么这里的负载均衡需要显示依赖进去 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
错误处理笔记
问题一:如果出现
09:30:24.166 [main] DEBUG org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter - Application failed to start due to an exception org.springframework.cloud.commons.ConfigDataMissingEnvironmentPostProcessor$ImportException: No spring.config.import set
是因为sprint cloud自2.4版本之后,默认将bootstrap进行禁用,只需要将其引入即可
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency>
问题二: 如果出现
2024-04-26 11:04:31,318 ERROR Server check fail, please check server 192.168.129.131 ,port 31102 is available , error ={} java.util.concurrent.ExecutionException: io.grpc.StatusRuntimeException: UNAVAILABLE: io exception at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:592) at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:467) ...
... at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:467) Caused by: io.grpc.StatusRuntimeException: UNAVAILABLE: io exception at io.grpc.Status.asRuntimeException(Status.java:537) ...
... at java.lang.Thread.run(Thread.java:748) Caused by: io.grpc.netty.shaded.io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /192.168.129.131:31102 Caused by: java.net.ConnectException: Connection refused: no further information at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ...
... at java.lang.Thread.run(Thread.java:748) 2024-04-26 11:04:31,320 INFO [Cluster-192.168.129.131:30101] Try to connect to server on start up, server: {serverIp = '192.168.129.131', server main port = 30101}
处理方式如下:Nacos高可用集群搭建与使用 - AlwaysZmx - 博客园 (cnblogs.com)
出现该异常的原因:当nacos客户端升级为2.x版本后,新增了gRPC的通信方式,新增了两个端口。这两个端口在nacos原先的端口上(默认8848),进行一定偏移量自动生成。 端口与主端口的偏移量描述: 9848:客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求 9849:服务端gRPC请求服务端端口,用于服务间同步等 7848:Nacos 集群通信端口,用于Nacos 集群间进行选举,检测等 因此,不难猜出,出现该问题的原因是由于nacos2.x版本新增的这两个端口没有在宿主机开启防火墙白名单,导致nacos实例之间无法进行服务间数据同步,因而在控制台无法查看到所有的服务注册实例信息。只需要在nacos宿主机执行以下命令即可: [root@localhost bin]# firewall-cmd --add-port=9848/tcp --permanent success [root@localhost bin]# firewall-cmd --add-port=9849/tcp --permanent success [root@localhost bin]# firewall-cmd --add-port=7848/tcp --permanent success [root@localhost bin]# firewall-cmd --reload Success
待续。。。