nacos+openfeign实现负载均衡+openfeign降级

参考:https://www.cnblogs.com/liconglong/p/15408858.html#_label2

9090和9091都起名为business配置到nacos上
nacos+openfeign实现负载均衡+openfeign降级_第1张图片

nacos+openfeign实现负载均衡+openfeign降级_第2张图片
如图建立微服务项目!!
pom meaven参考:
https://blog.csdn.net/qq_43470725/article/details/123101494

父pom:

"1.0" encoding="UTF-8"?>
"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">
    4.0.0</modelVersion>
    
        org.springframework.boot</groupId>
        spring-boot-starter-parent</artifactId>
        2.3.5.RELEASE</version>
<!--        /> <;!&ndash; lookup parent from repository &ndash;>;-->
    </parent>
    com.example</groupId>
    demo</artifactId>
    0.0.1-SNAPSHOT</version>
    cloud</name>
    Demo project for Spring Boot</description>

    pom</packaging>

    
        .version>1.8</java.version>
        -boot.version>2.3.5.RELEASE</spring-boot.version>
        .version>8.0.22</mysql.version>
        .version>2.1.3</mybatis.version>
        -plus.version>3.3.2</mybatis-plus.version>
        .version>1.18.16</lombok.version>
        -kafka.version>2.5.7.RELEASE</spring-kafka.version>
        -amqp-client.version>5.9.0</rabbit-amqp-client.version>
    </properties>

    

        

            
                com.example</groupId>
                dtestcommon</artifactId>
                0.0.1-SNAPSHOT</version>
            </dependency>

            
                org.springframework.boot</groupId>
                spring-boot-starter-web</artifactId>
                ${spring-boot.version}</version>
            </dependency>

            
                org.springframework.boot</groupId>
                spring-boot-starter-test</artifactId>
                ${spring-boot.version}</version>
                test</scope>
            </dependency>

            
                mysql</groupId>
                mysql-connector-java</artifactId>
                ${mysql.version}</version>
                runtime</scope>
            </dependency>

            
                org.mybatis.spring.boot</groupId>
                mybatis-spring-boot-starter</artifactId>
                2.1.3</version>
            </dependency>

            
                org.projectlombok</groupId>
                lombok</artifactId>
                ${lombok.version}</version>
                true</optional>
            </dependency>

            
                org.springframework.integration</groupId>
                spring-integration-mqtt</artifactId>
                5.4.6</version>
            </dependency>

            
                io.netty</groupId>
                netty-all</artifactId>
                4.1.42.Final</version>
            </dependency>

            
                cn.hutool</groupId>
                hutool-all</artifactId>
                5.2.3</version>
            </dependency>
            <!---->
            
                com.gexin.platform</groupId>
                gexin-rp-fastjson</artifactId>
                1.0.0.7</version>
            </dependency>


            
                com.gexin.platform</groupId>
                gexin-rp-sdk-base</artifactId>
                4.0.0.38</version>
            </dependency>
            
                com.gexin.platform</groupId>
                gexin-rp-sdk-http</artifactId>
                4.1.2.0</version>
            </dependency>
            
                com.gexin.platform</groupId>
                gexin-rp-sdk-template</artifactId>
                4.0.0.30</version>
            </dependency>
            
                com.google.protobuf</groupId>
                protobuf-java</artifactId>
                2.5.0</version>
            </dependency>

            <!---->

            
                com.fasterxml.jackson.core</groupId>
                jackson-core</artifactId>
                2.12.3</version>
            </dependency>


            
                com.alibaba.cloud</groupId>
                spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                2.2.4.RELEASE</version>
            </dependency>

            
                org.springframework.boot</groupId>
                spring-boot-starter-data-redis</artifactId>
                ${spring-boot.version}</version>
            </dependency>


            
                org.apache.ibatis</groupId>
                ibatis-core</artifactId>
                3.0</version>
            </dependency>

            


                net.sf.json-lib</groupId>

                json-lib</artifactId>

                2.4</version>

                jdk15</classifier>

            </dependency>

            
                org.springframework.boot</groupId>
                spring-boot-starter-thymeleaf</artifactId>
                ${spring-boot.version}</version>
            </dependency>

            
                org.springframework.cloud</groupId>
                spring-cloud-starter-openfeign</artifactId>
                2.2.3.RELEASE</version>
            </dependency>
            <!--阿里云-->
            
                com.aliyun.oss</groupId>
                aliyun-sdk-oss</artifactId>
                3.10.2</version>
            </dependency>

            <!-- servlet依赖 -->
            
                javax.servlet</groupId>
                javax.servlet-api</artifactId>
            </dependency>
            
                javax.servlet</groupId>
                jstl</artifactId>
            </dependency>
            <!-- tomcat的支持-->
            
                org.apache.tomcat.embed</groupId>
                tomcat-embed-jasper</artifactId>
                provided</scope>
            </dependency>

            <!--mongodb依赖-->
            
                org.springframework.boot</groupId>
                spring-boot-starter-data-mongodb</artifactId>
                ${spring-boot.version}</version>
            </dependency>

            <!--引入kafak和spring整合的jar-->
            
                org.springframework.kafka</groupId>
                spring-kafka</artifactId>
                ${spring-kafka.version}</version>
            </dependency>

            <!--        rabbitmq-->
            
                com.rabbitmq</groupId>
                amqp-client</artifactId>
                ${rabbit-amqp-client.version}</version>
            </dependency>

            <!-- cloudStream  rabbit-->
            
                org.springframework.cloud</groupId>
                spring-cloud-starter-stream-rabbit</artifactId>
                3.0.8.RELEASE</version>
            </dependency>
            <!-- cloudStream  kafka-->
            
                org.springframework.cloud</groupId>
                spring-cloud-starter-stream-kafka</artifactId>
                3.0.12.RELEASE</version>
            </dependency>

            
                org.apache.commons</groupId>
                commons-lang3</artifactId>
                3.8</version>
            </dependency>
            <!--        elasticsearch-->

            
                org.springframework.boot</groupId>
                spring-boot-starter-data-elasticsearch</artifactId>
                2.3.12.RELEASE</version>
            </dependency>
            <!--        spring  ConfigurationProperties注解包   -->
            
                org.springframework.boot</groupId>
                spring-boot-configuration-processor</artifactId>
                true</optional>
            </dependency>

            <!-- 用于矩阵运算 -->
            
                org.ujmp</groupId>
                ujmp-core</artifactId>
                0.3.0</version>
            </dependency>
            <!-- 用于显示散点图-->
            
                org.jfree</groupId>
                jfreechart</artifactId>
                1.5.3</version>
            </dependency>


            <!--xls(03)对应jia包-->
            
                org.apache.poi</groupId>
                poi</artifactId>
                4.1.2</version>
            </dependency>

            <!--xlsx(07)对应jia包-->
            
                org.apache.poi</groupId>
                poi-ooxml</artifactId>
                4.1.2</version>
            </dependency>

            <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
            
                com.alibaba</groupId>
                easyexcel</artifactId>
                2.1.7</version>
            </dependency>


            <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
            
                org.apache.dubbo</groupId>
                dubbo-spring-boot-starter</artifactId>
                2.7.8</version>
            </dependency>


            <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
            
                io.springfox</groupId>
                springfox-swagger2</artifactId>
                2.9.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
            
                io.springfox</groupId>
                springfox-swagger-ui</artifactId>
                2.9.2</version>
            </dependency>


            <!-- https://mvnrepository.com/artifact/log4j/log4j -->
            
                log4j</groupId>
                log4j</artifactId>
                1.2.17</version>
            </dependency>


            <!-- Base64编码需要  -->
            
                org.apache.directory.studio</groupId>
                org.apache.commons.codec</artifactId>
                1.8</version>
            </dependency>

            <!--        springdata-->
            
                org.springframework.boot</groupId>
                spring-boot-starter-data-jpa</artifactId>
                2.6.2</version>
            </dependency>

            <!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
            
                org.redisson</groupId>
                redisson</artifactId>
                3.16.6</version>
            </dependency>

            <!-- https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter -->
            
                org.redisson</groupId>
                redisson-spring-boot-starter</artifactId>
                3.16.4</version>
            </dependency>

            <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel -->
            
                com.alibaba.cloud</groupId>
                spring-cloud-starter-alibaba-sentinel</artifactId>
                2.2.1.RELEASE</version>
            </dependency>


        </dependencies>

    </dependencyManagement>


    
        
            
                org.springframework.boot</groupId>
                spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

建立9090项目:

pom:

"1.0" encoding="UTF-8"?>
"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">
    4.0.0</modelVersion>
    
        com.example</groupId>
        demo</artifactId>
        0.0.1-SNAPSHOT</version>
<!--        /> <;!&ndash; lookup parent from repository &ndash;>;-->
    </parent>
    com.example</groupId>
    business9090</artifactId>
    0.0.1-SNAPSHOT</version>
    business9090</name>
    Demo project for Spring Boot</description>
<!--    -->
<!--        .version>1.8</java.version>-->
<!--    </properties>-->


    

        
            org.springframework.boot</groupId>
            spring-boot-starter-web</artifactId>
        </dependency>

        
            org.springframework.boot</groupId>
            spring-boot-starter-test</artifactId>
            test</scope>
        </dependency>

<!--        -->
<!--            mysql</groupId>-->
<!--            mysql-connector-java</artifactId>-->
<!--            runtime</scope>-->
<!--        </dependency>-->

<!--        -->
<!--            org.mybatis.spring.boot</groupId>-->
<!--            mybatis-spring-boot-starter</artifactId>-->
<!--        </dependency>-->

        
            org.projectlombok</groupId>
            lombok</artifactId>
            true</optional>
        </dependency>

        
            cn.hutool</groupId>
            hutool-all</artifactId>
        </dependency>

        
            com.alibaba.cloud</groupId>
            spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        
            org.springframework.boot</groupId>
            spring-boot-starter-data-redis</artifactId>
        </dependency>

        
            org.springframework.cloud</groupId>
            spring-cloud-starter-openfeign</artifactId>
        </dependency>

        
            org.redisson</groupId>
            redisson</artifactId>
        </dependency>

        
            org.redisson</groupId>
            redisson-spring-boot-starter</artifactId>
        </dependency>


    </dependencies>

    
        
            
                org.springframework.boot</groupId>
                spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

yml配置:

server:
  port: 9090

spring:
  application:
    name: business

#  datasource:
#    #    url: jdbc:mysql://rm-2vc7l62g4u9rt2l82vo.mysql.cn-chengdu.rds.aliyuncs.com:3306/materialbasecloud?characterEncoding=utf8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
#    #    username: root
#    #    password: jjqhc123456
#    url: jdbc:mysql://49.235.125.47:3306/live?characterEncoding=utf8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
#    username: root
#    password: 123456
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    hikari:
#      max-lifetime: 180000
#      minimum-idle: 20
#      #设置最大线程数量:
#      maximum-pool-size: 30
#      idle-timeout: 120000
#      #      加了之后容易超时
#      #      connection-test-query: SELECT 1

  #redis
  redis:
    # redis数据库索引(默认为0),我们使用索引为3的数据库,避免和其他数据库冲突,通过rdm查看时,在db3的下面
    database: 1
    # redis服务器地址(默认为loaclhost)
    host: 49.235.125.47
    # redis端口(默认为6379)
    port: 6379
    # redis访问密码(默认为空)
    password: 123456
    # redis连接超时时间(单位毫秒)
    timeout: 10000
    # redis连接池配置
    jedis:
      pool:
        # 最大可用连接数(默认为8,负数表示无限)
        max-active: 8
        # 最大空闲连接数(默认为8,负数表示无限)
        max-idle: 8
        # 最小空闲连接数(默认为0,该值只有为正数才有用)
        min-idle: 0
        # 从连接池中获取连接最大等待时间(默认为-1,单位为毫秒,负数表示无限)
        max-wait: -1

  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

controller:

package com.example.business9090.controller;

import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/cloud")
@Slf4j
public class CloudController {

    @Autowired
    private RedissonClient redisson;

    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/test")
    public String cloudTest(){

        String lockKey = "product_001";
        String clientId = UUID.randomUUID().toString();

//        ridisson分布式锁  获取锁对象
        RLock rLock = redisson.getLock(lockKey);

        try{

            //        不具备原则性,宕机时会出现bug
//        Boolean resulet = redisTemplate.opsForValue().setIfAbsent(lockKey,"chunfeng");
//        redisTemplate.expire(lockKey,10, TimeUnit.SECONDS);

//            Boolean resulet = redisTemplate.opsForValue().setIfAbsent(lockKey,clientId,30,TimeUnit.SECONDS);

//            if(!resulet){
//                return "error code";
//            }

//            加分布式锁
            rLock.lock();
            System.out.println("9090 -------访问");


        }catch (Exception e){
            log.error(e.getMessage());
        }finally {
//            释放锁
            rLock.unlock();
//            if(clientId.equals(redisTemplate.opsForValue().get(lockKey))){
//                redisTemplate.delete(lockKey);
//            }
        }


        return "9090";

    }

}

建立9091项目:

pom:

"1.0" encoding="UTF-8"?>
"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">
    4.0.0</modelVersion>
    
        com.example</groupId>
        demo</artifactId>
        0.0.1-SNAPSHOT</version>
        /> <!-- lookup parent from repository -->
    </parent>
    com.example</groupId>
    business9091</artifactId>
    0.0.1-SNAPSHOT</version>
    business9091</name>
    Demo project for Spring Boot</description>
    
        .version>1.8</java.version>
    </properties>
    
        
            org.springframework.boot</groupId>
            spring-boot-starter-web</artifactId>
        </dependency>

        
            org.springframework.boot</groupId>
            spring-boot-starter-test</artifactId>
            test</scope>
        </dependency>

<!--        -->
<!--            mysql</groupId>-->
<!--            mysql-connector-java</artifactId>-->
<!--            runtime</scope>-->
<!--        </dependency>-->

<!--        -->
<!--            org.mybatis.spring.boot</groupId>-->
<!--            mybatis-spring-boot-starter</artifactId>-->
<!--            2.1.3</version>-->
<!--        </dependency>-->

        
            org.projectlombok</groupId>
            lombok</artifactId>
            true</optional>
        </dependency>

        
            cn.hutool</groupId>
            hutool-all</artifactId>
        </dependency>

        
            com.alibaba.cloud</groupId>
            spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        
            org.springframework.boot</groupId>
            spring-boot-starter-data-redis</artifactId>
        </dependency>

        
            org.springframework.cloud</groupId>
            spring-cloud-starter-openfeign</artifactId>
        </dependency>

        
            org.redisson</groupId>
            redisson</artifactId>
        </dependency>

        
            org.redisson</groupId>
            redisson-spring-boot-starter</artifactId>
        </dependency>

    </dependencies>

    
        
            
                org.springframework.boot</groupId>
                spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

yml:

server:
  port: 9091

spring:
  application:
    name: business

#  datasource:
#    #    url: jdbc:mysql://rm-2vc7l62g4u9rt2l82vo.mysql.cn-chengdu.rds.aliyuncs.com:3306/materialbasecloud?characterEncoding=utf8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
#    #    username: root
#    #    password: jjqhc123456
#    url: jdbc:mysql://49.235.125.47:3306/live?characterEncoding=utf8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
#    username: root
#    password: 123456
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    hikari:
#      max-lifetime: 180000
#      minimum-idle: 20
#      #设置最大线程数量:
#      maximum-pool-size: 30
#      idle-timeout: 120000
#      #      加了之后容易超时
#      #      connection-test-query: SELECT 1

  #redis
  redis:
    # redis数据库索引(默认为0),我们使用索引为3的数据库,避免和其他数据库冲突,通过rdm查看时,在db3的下面
    database: 1
    # redis服务器地址(默认为loaclhost)
    host: 49.235.125.47
    # redis端口(默认为6379)
    port: 6379
    # redis访问密码(默认为空)
    password: 123456
    # redis连接超时时间(单位毫秒)
    timeout: 10000
    # redis连接池配置
    jedis:
      pool:
        # 最大可用连接数(默认为8,负数表示无限)
        max-active: 8
        # 最大空闲连接数(默认为8,负数表示无限)
        max-idle: 8
        # 最小空闲连接数(默认为0,该值只有为正数才有用)
        min-idle: 0
        # 从连接池中获取连接最大等待时间(默认为-1,单位为毫秒,负数表示无限)
        max-wait: -1

  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

controller:

package com.example.business9092.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/cloud")
@Slf4j
public class CloudController {

    @PostMapping("/test")
    public String cloudTest(){

        System.out.println("9091 -------访问");
        return "9091";

    }

}

建立openfigen项目9092:

"1.0" encoding="UTF-8"?>
"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">
    4.0.0</modelVersion>
    
        com.example</groupId>
        demo</artifactId>
        0.0.1-SNAPSHOT</version>
        /> <!-- lookup parent from repository -->
    </parent>
    com.example</groupId>
    business9092fengin</artifactId>
    0.0.1-SNAPSHOT</version>
    business9092fengin</name>
    Demo project for Spring Boot</description>
    
        .version>1.8</java.version>
    </properties>
    

        
            com.example</groupId>
            dtestcommon</artifactId>
        </dependency>

        
            org.springframework.boot</groupId>
            spring-boot-starter-web</artifactId>
        </dependency>

        
            org.springframework.boot</groupId>
            spring-boot-starter-test</artifactId>
            test</scope>
        </dependency>

<!--        -->
<!--            mysql</groupId>-->
<!--            mysql-connector-java</artifactId>-->
<!--            runtime</scope>-->
<!--        </dependency>-->

<!--        -->
<!--            org.mybatis.spring.boot</groupId>-->
<!--            mybatis-spring-boot-starter</artifactId>-->
<!--            2.1.3</version>-->
<!--        </dependency>-->

        
            org.projectlombok</groupId>
            lombok</artifactId>
            true</optional>
        </dependency>

        
            cn.hutool</groupId>
            hutool-all</artifactId>
        </dependency>

        
            com.alibaba.cloud</groupId>
            spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        
            org.springframework.boot</groupId>
            spring-boot-starter-data-redis</artifactId>
        </dependency>

        
            org.springframework.cloud</groupId>
            spring-cloud-starter-openfeign</artifactId>
        </dependency>

        
            org.redisson</groupId>
            redisson</artifactId>
        </dependency>

        
            org.redisson</groupId>
            redisson-spring-boot-starter</artifactId>
        </dependency>


    </dependencies>

    
        
            
                org.springframework.boot</groupId>
                spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

yml:

server:
  port: 9092

spring:
  application:
    name: business-9092

  datasource:
    #    url: jdbc:mysql://rm-2vc7l62g4u9rt2l82vo.mysql.cn-chengdu.rds.aliyuncs.com:3306/materialbasecloud?characterEncoding=utf8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
    #    username: root
    #    password: jjqhc123456
    url: jdbc:mysql://49.235.125.47:3306/live?characterEncoding=utf8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      max-lifetime: 180000
      minimum-idle: 20
      #设置最大线程数量:
      maximum-pool-size: 30
      idle-timeout: 120000
      #      加了之后容易超时
      #      connection-test-query: SELECT 1

  #redis
#  redis:
#    # redis数据库索引(默认为0),我们使用索引为3的数据库,避免和其他数据库冲突,通过rdm查看时,在db3的下面
#    database: 1
#    # redis服务器地址(默认为loaclhost)
#    host: 49.235.125.47
#    # redis端口(默认为6379)
#    port: 6379
#    # redis访问密码(默认为空)
#    password: 123456
#    # redis连接超时时间(单位毫秒)
#    timeout: 10000
#    # redis连接池配置
#    jedis:
#      pool:
#        # 最大可用连接数(默认为8,负数表示无限)
#        max-active: 8
#        # 最大空闲连接数(默认为8,负数表示无限)
#        max-idle: 8
#        # 最小空闲连接数(默认为0,该值只有为正数才有用)
#        min-idle: 0
#        # 从连接池中获取连接最大等待时间(默认为-1,单位为毫秒,负数表示无限)
#        max-wait: -1

  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

建立openfeign接口和解析类:
nacos+openfeign实现负载均衡+openfeign降级_第3张图片

建立TestFeignClientInterface接口:

package com.example.business9092fengin.cloud.interfaces;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;

public interface TestFeignClientInterface {



    @PostMapping("/cloud/test")
    String cloudTest();

}

建立TestFeignClient接口继承TestFeignClientInterface接口,并加上FeignClient被feign识别:

package com.example.business9092fengin.cloud.client;

import com.example.business9092fengin.cloud.config.FeignConfiguration;
import com.example.business9092fengin.cloud.interfaces.TestFeignClientInterface;
import org.springframework.cloud.openfeign.FeignClient;

@FeignClient(value = "business",configuration = FeignConfiguration.class)
public interface TestFeignClient extends TestFeignClientInterface {
}

自定义解析类的配置been:

package com.example.business9092fengin.cloud.config;



import com.example.dtestcommon.config.feign.decoder.FeignResDecoder;
import com.example.dtestcommon.config.feign.decoder.token.FeignTokenTransfer;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfiguration {

    @Bean
    public Decoder feignDecoder() {
        return new FeignResDecoder();
    }

    @Bean
    public RequestInterceptor requestInterceptor(){
        return new FeignTokenTransfer();
    }
}

自定义的解析类: FeignResDecoder

nacos+openfeign实现负载均衡+openfeign降级_第4张图片

package com.example.dtestcommon.config.feign.decoder;


import com.example.dtestcommon.utils.JsonUtil;
import com.example.dtestcommon.vo.Res;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.FeignException;
import feign.Response;
import feign.Util;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

@Slf4j
public class FeignResDecoder implements Decoder {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 允许出现特殊字符和转义符
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        // 允许出现单引号
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
    }


    @Override
    public Object decode(Response response, Type type) throws IOException, FeignException {
        if (response.body() == null) {
            throw new DecodeException(response.status(), "没有返回有效的数据", response.request());
        }

        //      如果是String类型
        if(String.class.equals(type)){
            return Util.toString(response.body().asReader());
        }



        String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));



        //第一种情况,如果为Response
        if (type instanceof com.example.dtestcommon.vo.Response || Map.class.equals(type)){
            return JsonUtil.json2obj(bodyStr,type);
        }

        //第二种情况,如果有类型,如Res,或者List
        if (type instanceof ParameterizedType) {
            Type rawType = ((ParameterizedType) type).getRawType();
            //如果为如Res
            if (Res.class.equals(rawType)) {
                return JsonUtil.json2obj(bodyStr, type);
                //或者List
            }
            Res res = JsonUtil.json2obj(bodyStr, Res.class);
            return JsonUtil.json2obj(objectMapper.writeValueAsString(res.getData()), type);

        } else {
            //另一种情况
            //如下可以,但是不完美,Result类可能是Res类,也可能是Response
            Res res = JsonUtil.json2obj(bodyStr, Res.class);
            return JsonUtil.json2obj(objectMapper.writeValueAsString(res.getData()), type);
        }
    }

}

添加拦截器:FeignTokenTransfer

package com.example.dtestcommon.config.feign.decoder.token;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

public class FeignTokenTransfer implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes==null){
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        //添加token
        requestTemplate.header("token", request.getHeader("token"));
    }
}

启动类添加扫描,将配置feign的类扫描到spring 中:

package com.example.business9092fengin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients({"com.example.business9092fengin.cloud.client"})
@SpringBootApplication
public class Business9092fenginApplication {

    public static void main(String[] args) {
        SpringApplication.run(Business9092fenginApplication.class, args);
    }

}

测试:启动9090、9091、9092

9090和9091都起名为business配置到nacos上
nacos+openfeign实现负载均衡+openfeign降级_第5张图片
访问:
127.0.0.1:9092/feign/test
nacos+openfeign实现负载均衡+openfeign降级_第6张图片
nacos+openfeign实现负载均衡+openfeign降级_第7张图片

openfeign负载均衡策略选择

参考:https://www.cnblogs.com/liconglong/p/15408858.html#_label2

1、可以配置yml

2、在FeignConfiguration中配置策略规则,选择已有的:
默认时轮询选择
RandomRule():随机选择

nacos+openfeign实现负载均衡+openfeign降级_第8张图片

package com.example.business9092fengin.cloud.config;



import com.example.dtestcommon.config.feign.decoder.FeignResDecoder;
import com.example.dtestcommon.config.feign.decoder.token.FeignTokenTransfer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfiguration {

    @Bean
    public Decoder feignDecoder() {
        return new FeignResDecoder();
    }

    @Bean
    public RequestInterceptor requestInterceptor(){
        return new FeignTokenTransfer();
    }

    @Bean
    public IRule loadBalancedRule(){
        return new RandomRule();
    }



}

3、自定义负载均衡规则:

创建负载均衡规则类:

package com.example.business9092fengin.cloud.rule;

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;

import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class CustomRule implements IRule {

    private ILoadBalancer lb;
//    用于设置自己要排除掉的端口号!!!!!
    public List<Integer> excludePorts;

//    无参构造
    public CustomRule() {
    }
//      有参构造
    public CustomRule(List<Integer> excludePorts) {
        this.excludePorts = excludePorts;
    }


    @Override
    public void setLoadBalancer(ILoadBalancer iLoadBalancer) {
        this.lb = iLoadBalancer;
    }

    @Override
    public ILoadBalancer getLoadBalancer() {
        return lb;
    }


    /**
     * 目标:自定义负载均衡策略:从所有可用的provider中排除掉指定端口号的provider,
     * 剩余provider进行随机选择
     * 实现步骤:
     * 1.获取到所有Server
     * 2.从所有Server中排除掉指定端口的Server后,剩余的Server
     * 3.从剩余Server中随机选择一个Server
     */
    @Override
    public Server choose(Object o) {
        // 1.获取到所有Server
        List<Server> servers = lb.getReachableServers();

        // 2.从所有Server中排除掉指定端口的Server后,剩余的Server
        List<Server> availableServers = this.getAvailableServers(servers);

        // 3.从剩余Server中随机选择一个Server
        Server server = this.getAvailableRandomServers(availableServers);

        return server;
    }

    private List<Server> getAvailableServers(List<Server> servers) {
        // 若没有指定要排除的port,则返回所有Server
        if(excludePorts == null || excludePorts.size() == 0) {
            return servers;
        }
        List<Server> aservers = servers.stream()
                // filter()
                // noneMatch() 只有当流中所有元素都没有匹配上时,才返回true,只要有一个匹配上了,则返回false
                .filter(server -> excludePorts.stream().noneMatch(port -> server.getPort() == port))
                .collect(Collectors.toList());

        return aservers;
    }

//   随机选择服务
    private Server getAvailableRandomServers(List<Server> availableServers) {
        // 获取一个[0,availableServers.size())的随机数
        int index = new Random().nextInt(availableServers.size());
        return availableServers.get(index);
    }


}

将其配置到FeignConfiguration类中,注入进spring中

nacos+openfeign实现负载均衡+openfeign降级_第9张图片

package com.example.business9092fengin.cloud.config;



import com.example.business9092fengin.cloud.rule.CustomRule;
import com.example.dtestcommon.config.feign.decoder.FeignResDecoder;
import com.example.dtestcommon.config.feign.decoder.token.FeignTokenTransfer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class FeignConfiguration {

    @Bean
    public Decoder feignDecoder() {
        return new FeignResDecoder();
    }

    @Bean
    public RequestInterceptor requestInterceptor(){
        return new FeignTokenTransfer();
    }

//    @Bean
//    public IRule loadBalancedRule(){
//        return new RandomRule();
//    }


    @Bean
    public IRule loadBalancedRule(){
        List<Integer> list = new ArrayList<>();
        list.add(9090);//排除访问端口
        return new CustomRule(list);
    }


}

nacos+openfeign实现负载均衡+openfeign降级_第10张图片
如图,排除后就只会选择9091了!!!
nacos+openfeign实现负载均衡+openfeign降级_第11张图片

openfeign+sentinel降级

 
            com.alibaba.cloud</groupId>
            spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
server:
  port: 9092

spring:
  application:
    name: business-9092

#  datasource:
#    #    url: jdbc:mysql://rm-2vc7l62g4u9rt2l82vo.mysql.cn-chengdu.rds.aliyuncs.com:3306/materialbasecloud?characterEncoding=utf8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
#    #    username: root
#    #    password: jjqhc123456
#    url: jdbc:mysql://49.235.125.47:3306/live?characterEncoding=utf8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
#    username: root
#    password: 123456
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    hikari:
#      max-lifetime: 180000
#      minimum-idle: 20
#      #设置最大线程数量:
#      maximum-pool-size: 30
#      idle-timeout: 120000
#      #      加了之后容易超时
#      #      connection-test-query: SELECT 1

  #redis
  redis:
    # redis数据库索引(默认为0),我们使用索引为3的数据库,避免和其他数据库冲突,通过rdm查看时,在db3的下面
    database: 1
    # redis服务器地址(默认为loaclhost)
    host: 49.235.125.47
    # redis端口(默认为6379)
    port: 6379
    # redis访问密码(默认为空)
    password: 123456
    # redis连接超时时间(单位毫秒)
    timeout: 10000
    # redis连接池配置
    jedis:
      pool:
        # 最大可用连接数(默认为8,负数表示无限)
        max-active: 8
        # 最大空闲连接数(默认为8,负数表示无限)
        max-idle: 8
        # 最小空闲连接数(默认为0,该值只有为正数才有用)
        min-idle: 0
        # 从连接池中获取连接最大等待时间(默认为-1,单位为毫秒,负数表示无限)
        max-wait: -1

  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
        # 为应用开启额外的端口,上报监控信息
        # 默认为8719端口,加入被占用将会自动从8719开始+1扫描,直至找到未被占用的端口地址
        port: 8719

        datasource: #配置流控规则持久化
          ds1:
            nacos:
              server-addr: localhost:8848
              dataId: cloudalibaba-sentinel-service
              groupId: DEFAULT_GROUP
              data-type: json
              rule-type: flow
## 监控相关
anagement:
  endpoints:
    web:
      exposure:
        include: '*'

#开启 sentinel 对 feign 的支持
feign:
  sentinel:
    enabled: true

nacos+openfeign实现负载均衡+openfeign降级_第12张图片

配置feign的熔断降级!!

nacos+openfeign实现负载均衡+openfeign降级_第13张图片
接口关系:
nacos+openfeign实现负载均衡+openfeign降级_第14张图片

package com.example.business9092fengin.cloud.interfaces;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;

public interface TestFeignClientInterface {



    @PostMapping("/cloud/test")
    String cloudTest();



}
package com.example.business9092fengin.cloud.client;

import com.example.business9092fengin.cloud.config.FeignConfiguration;
import com.example.business9092fengin.cloud.interfaces.TestFeignClientInterface;
import com.example.business9092fengin.cloud.interfaces.impl.TestFeignClientIFallbackImpl;
import org.springframework.cloud.openfeign.FeignClient;

@FeignClient(value = "business",configuration = FeignConfiguration.class,fallback = TestFeignClientIFallbackImpl.class)
public interface TestFeignClient extends TestFeignClientInterface {
}
package com.example.business9092fengin.cloud.interfaces.impl;

import com.example.business9092fengin.cloud.client.TestFeignClient;
import com.example.business9092fengin.cloud.interfaces.TestFeignClientInterface;
import org.springframework.stereotype.Component;

@Component
public class TestFeignClientIFallbackImpl implements TestFeignClient {

    @Override
    public String cloudTest() {
        String str = "调用失败,服务被降级";
        return str;
    }

}

controller:

这里需要注意要使用:@Qualifier指定时哪一个类,应为继承testFeignClient接口的类有两个!!
因为有@Component注入的bean的类和主启动扫描注入的bean
nacos+openfeign实现负载均衡+openfeign降级_第15张图片

nacos+openfeign实现负载均衡+openfeign降级_第16张图片
nacos+openfeign实现负载均衡+openfeign降级_第17张图片
在这里插入图片描述

package com.example.business9092fengin.controller;

import com.example.business9092fengin.cloud.client.TestFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/feign")
public class TestFeignController {

    @Qualifier("com.example.business9092fengin.cloud.client.TestFeignClient")
    @Autowired
    TestFeignClient testFeignClient;

    @PostMapping("/test")
    public String test(){

        String str = testFeignClient.cloudTest();
        System.out.println("访问--"+str);

        return str;

    }


}

测试:
nacos+openfeign实现负载均衡+openfeign降级_第18张图片
将9090和9091端口关闭后测试:

nacos+openfeign实现负载均衡+openfeign降级_第19张图片
降级成功!!!!

你可能感兴趣的:(分布式,负载均衡,java,运维)