笔记

万物寻其根,通其堵,便能解其困。
  博客园  :: 新随笔  :: 管理

Spring colud的构建

Posted on 2024-04-20 20:07  草妖  阅读(7)  评论(0)    收藏  举报

一、创建空的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

 

待续。。。