SpringCloud Alibaba集成 Gateway(自定义负载均衡器)、Nacos(配置中心、注册中心)、loadbalancer

news2024/12/23 1:59:05

文章目录

  • POM依赖
  • 环境准备
  • 配置
    • 配置文件
    • 配置类
  • 案例展示

POM依赖

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.10</version>
        <relativePath/>
    </parent>
      <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <springcloud.version>3.1.6</springcloud.version>
        <springcloudalibaba.version>2021.0.4.0</springcloudalibaba.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
     <dependencies>
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>${springcloudalibaba.version}</version>
            <exclusions>
                <exclusion>
                    <!-- nacos-client2.0.4版本存在官方github上的#6999及#10385号Bug; nacos-client2.2.1版本存在当配置中心配置变化后客户端AsyncAppender进程数不断增加Bug -->
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>${springcloudalibaba.version}</version>
            <exclusions>
                <exclusion>
                    <!-- nacos-client2.0.4版本存在官方github上的#6999及#10385号Bug; nacos-client2.2.1版本存在当配置中心配置变化后客户端AsyncAppender进程数不断增加Bug -->
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>${springcloud.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${springcloud.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>${springcloud.version}</version>
        </dependency>
         <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
                <version>2.2.9.RELEASE</version>
            </dependency>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <version>3.1.5</version>
        </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-webmvc</artifactId>
                </exclusion>
                <exclusion>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
     </dependencies>

环境准备

nacos搭建Nacos standalone单机搭建部署

配置

配置文件

application.yml

server:
  port: 8082
spring:
  profiles:
    active: dev
  main:
    web-application-type: reactive
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: Mes
          uri: lb://Mes
          predicates:
            - Path=/mes/**
        - id: Test
          uri: lb://Test
          predicates:
            - Path=/test/**

bootstrap.properties

spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.discovery.group=dev
spring.cloud.nacos.discovery.namespace=1e6d33e2-5f43-45ec-8c1b-9c883c2c71d9
spring.cloud.nacos.config.group=dev
spring.cloud.nacos.config.prefix=gateway
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.file-extension=properties
spring.cloud.nacos.config.namespace=1e6d33e2-5f43-45ec-8c1b-9c883c2c71d9
spring.profiles.active=dev
spring.cloud.gateway.globalcors.corsConfigurations.[/**].allowedOriginPatterns=*
spring.cloud.gateway.globalcors.corsConfigurations.[/**].allowedHeaders=*
spring.cloud.gateway.globalcors.corsConfigurations.[/**].allowedMethods=*
spring.cloud.gateway.globalcors.corsConfigurations.[/**].allowCredentials=true

bootstrap-dev.properties

# 用于配置中心测试
message.name=lisi

配置类

自定义Gateway负载均衡器,采用nacos所配置的权重进行负载均衡调用,随机权重算法

import com.alibaba.cloud.nacos.balancer.NacosBalancer;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.*;
import reactor.core.publisher.Mono;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class CustomRoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
    private static final Log log = LogFactory.getLog(RoundRobinLoadBalancer.class);
    final AtomicInteger position;
    final String serviceId;
    ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;

    /**
     * @param serviceInstanceListSupplierProvider a provider of
     *                                            {@link ServiceInstanceListSupplier} that will be used to get available instances
     * @param serviceId                           id of the service for which to choose an instance
     */
    public CustomRoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
        this(serviceInstanceListSupplierProvider, serviceId, new Random().nextInt(1000));
    }

    /**
     * @param serviceInstanceListSupplierProvider a provider of
     *                                            {@link ServiceInstanceListSupplier} that will be used to get available instances
     * @param serviceId                           id of the service for which to choose an instance
     * @param seedPosition                        Round Robin element position marker
     */
    public CustomRoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, int seedPosition) {
        this.serviceId = serviceId;
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        this.position = new AtomicInteger(seedPosition);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
        return supplier.get(request).next().map(serviceInstances -> processInstanceResponse(supplier, serviceInstances));
    }

    private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier, List<ServiceInstance> serviceInstances) {
        Response<ServiceInstance> serviceInstanceResponse = getInstanceResponse(serviceInstances);
        if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
            ((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
        }
        return serviceInstanceResponse;
    }

    /**
     * 按nacos权重
     *
     * @return
     */

    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> serviceInstances) {
        Map<String, List<ServiceInstance>> collect = serviceInstances.stream().collect(Collectors.groupingBy(g -> {
                        //nacos在2.0版本之后移除了对实例id查询
//            return g.getMetadata().get("nacos.instanceId");
            return g.getHost() +":"+ g.getPort();
        }));
        if (serviceInstances.isEmpty()) {
            if (log.isWarnEnabled()) {
                log.warn("No servers available for service: " + serviceId);
            }
            return new EmptyResponse();
        }
        List<Instance> instances = serviceInstances.stream().map(i -> {
            Instance instance = new Instance();
            instance.setInstanceId(i.getInstanceId());
            Map<String, String> metadata = i.getMetadata();
            instance.setInstanceId(metadata.get("nacos.instanceId"));
            instance.setWeight(new BigDecimal(metadata.get("nacos.weight")).doubleValue());
            instance.setClusterName(metadata.get("nacos.cluster"));
            instance.setEphemeral(Boolean.parseBoolean(metadata.get("nacos.ephemeral")));
            instance.setHealthy(Boolean.parseBoolean(metadata.get("nacos.healthy")));
            instance.setPort(i.getPort());
            instance.setIp(i.getHost());
            instance.setServiceName(i.getServiceId());
            instance.setMetadata(metadata);
            return instance;
        }).collect(Collectors.toList());
        //采用nacos所配置的权重进行负载均衡调用,随机权重算法
        Instance instance = NacosBalancer.getHostByRandomWeight2(instances);
//        // TODO: enforce order?
//        int pos = Math.abs(this.position.incrementAndGet());
//        ServiceInstance instance = instances.get(pos % instances.size());
        return new DefaultResponse(collect.get(instance.getIp()+":"+ instance.getPort()).stream().findFirst().get());
    }
}

负载均衡配置类,指定使用哪一个负载均衡器

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@Configuration
public class RoundRobinLoadBalancerConfig {
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new CustomRoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }
}


LoadBalancerClient,负载均衡调用客户端,指定负载均衡器配置类,LoadBalancerClient注解中value要对用配置文件中路由的id

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@LoadBalancerClients({@LoadBalancerClient(value = "Mes", configuration = RoundRobinLoadBalancerConfig.class), @LoadBalancerClient(value = "Test", configuration = RoundRobinLoadBalancerConfig.class)})
@Configuration
public class RestTemplateConfig {

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

全局过滤器

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URI;

@Slf4j
@Component
public class RouteRecordGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                URI proxyRequestUri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        long start = System.currentTimeMillis();

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            long end = System.currentTimeMillis();
            log.info("实际调用地址为:{},调用耗时为:{}ms", proxyRequestUri, (end - start));
        }));
    }

    @Override
    public int getOrder() {
        // 优先级设为最低,先让RouteToRequestUrlFilter先调用
        return Ordered.LOWEST_PRECEDENCE;
    }
}

案例展示

Nacos服务列表
在这里插入图片描述
服务权重配置
在这里插入图片描述

服务测试代码
在这里插入图片描述
负载效果
在这里插入图片描述
配置中心测试代码
在这里插入图片描述
本地配置项
在这里插入图片描述
配置中心配置
在这里插入图片描述
效果
在这里插入图片描述
配置中心注意
这三个配置的拼接等于配置中心的配置 Data ID一定要正确

spring.cloud.nacos.config.prefix=gateway
spring.cloud.nacos.config.file-extension=properties
spring.profiles.active=dev

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1246236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux(CentOS7)上安装mysql

在CentOS中默认安装有MariaDB&#xff08;MySQL的一个分支&#xff09;&#xff0c;可先移除/卸载MariaDB。 yum remove mariadb // 查看是否存在mariadb rpm -qa|grep -i mariadb // 卸载 mariadb rpm -e --nodeps rpm -qa|grep mariadb yum安装 下载rpm // 5.6版本 wge…

wagtail-安装配置

系列文章目录 文章目录 系列文章目录安装虚拟环境安装wagtail查看安装后的包 创建wagtail项目安装依赖迁移创建超级用户运行项目 安装虚拟环境 https://blog.csdn.net/gsl371/article/details/117917857 安装wagtail (wagenv) C:\djproject\wagprj>pip list Package V…

编程入门基础知识,编程入门推荐,中文编程工具下载,软件定制开发

编程入门基础知识&#xff0c;编程入门推荐&#xff0c;中文编程工具下载&#xff0c;软件定制开发 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型…

【Git】一文教你学会 submodule 的增、删、改、查

添加子模块 $ git submodule add <url> <path>url 为想要添加的子模块路径path 为子模块存放的本地路径 示例&#xff0c;添加 r-tinymaix 为子模块到主仓库 ./sdk/packages/online-packages/r-tinymaix 路径下&#xff0c;命令如下所示&#xff1a; $ git subm…

SQL Server Profiler基础使用

文章目录 SQL Server Profiler基础使用简介如何打开直接打开Microsoft SQL Server Management Studio工具栏打开 配置跟踪新建跟踪跟踪属性配置常规配置事件选择 启动跟踪跟踪时执行脚本跟踪记录 暂停跟踪停止跟踪 SQL Server Profiler基础使用 简介 一个图形界面工具&#x…

创意设计与个性化定制:酒精壁炉的独特之处

在当今家居装饰的潮流中&#xff0c;人们越来越注重个性化和创意&#xff0c;而酒精壁炉正是在这一趋势中崭露头角。它不仅成为家居的温馨之选&#xff0c;更因其设计的灵活性而成为创意焦点&#xff0c;吸引了越来越多注重家居设计的人群。 酒精壁炉的设计灵活性为家居注入了新…

提供电商数据|带你简单认识天猫API接口相关参数文档调用说明

什么是API接口 API接口(Application Programming Interface Interface)是应用程序与开发人员或其他程序互相通信的方式。它允许开发者访问应用程序的数据和功能。 API接口,软件的“握手”与“交流”之道,软件世界的“好基友”。想让软件聊得来?想开发App却无从下手?API来相救…

Netty实现websocket且实现url传参的两种方式(源码分析)

1、先构建基本的netty框架 再下面的代码中我构建了一个最基本的netty实现websocket的框架&#xff0c;其他个性化部分再自行添加。 Slf4j public class TeacherServer {public void teacherStart(int port) throws InterruptedException {NioEventLoopGroup boss new NioEve…

视频录制工具有哪些?收藏起来,需要的时候用起来

视频录制工具顾名思义&#xff1a;用于捕获视频片段的软件。使用视频录制工具&#xff0c;你可以创建属于自己的视频内容。市面上的录屏工具五花八门&#xff0c;有哪些才是适合自己的呢&#xff1f; 虽然有许多视频录制工具可供选择&#xff0c;甚至有很多是免费的&#xff0…

Linux使用宝塔面板+Discuz+cpolar内网穿透工具搭建可公网访问论坛

Linux宝塔面板搭建Discuz论坛&#xff0c; 并内网穿透实现公网访问 文章目录 Linux宝塔面板搭建Discuz论坛&#xff0c; 并内网穿透实现公网访问前言1.安装基础环境2.一键部署Discuz3.安装cpolar工具4.配置域名访问Discuz5.固定域名公网地址6.配置Discuz论坛 前言 Crossday Di…

圈子社交系统丨论坛丨实名认证丨语音聊天丨VIP会员丨活动报名丨商城丨APP小程序h5丨源码交付,支持二开

圈子社交系统丨论坛丨实名认证丨语音聊天丨VIP会员丨活动报名丨商城丨APP小程序h5 后端下载地址&#xff1a;圈子系统APP源码&#xff0c;婚恋小程序&#xff0c;APP&#xff0c;H5&#xff0c;表白墙源码&#xff0c;恋爱小程序APP&#xff0c;交友APP小程序&#xff0c;社交小…

多线程 02

1.线程的常见构造方法 方法说明Thread()创建线程对象Thread(Runnable target)使用 Runnable 对象创建线程对象Thread(String name)创建线程对象&#xff0c;并命名Thread(Runnable target, String name)使用 Runnable 对象创建线程对象&#xff0c;并命名【了解】Thread(Threa…

数据库实验7

实验报告&#xff08;七&#xff09;数据更新 1、实验目的 &#xff08;1&#xff09; 掌握插入、更新和删除表数据的方法 &#xff08;2&#xff09; 掌握更新操作与子查询结合的用法 2、实验预习与准备 &#xff08;1&#xff09; Update&#xff0c;Delete&am…

内网横向技术

如果拿下了一台机器之后寻找域控机器 ipconfig /all 找到域名 ping 域名或者nslookup域名

拼多多平台全面API接口对接

对接流程&#xff08;支持虚拟商品&#xff09; 拼多多与商家之间数据双向请求&#xff0c;同步更新及相关数据传输。对接主要分为三大部分&#xff1a;准备阶段、对接测试、上线使用&#xff1b;针对每部分具体说明如下&#xff1a; 接口连通性测试重点关注两类接口的连通性&a…

百度ai试用

JMaven Central: com.baidu.aip:java-sdk (sonatype.com) Java sdk地址如上&#xff1a; 文心一言开发者 文心一言 (baidu.com) ERNIE Bot SDK提供便捷易用的接口&#xff0c;可以调用文心一言的能力&#xff0c;包含文本创作、通用对话、语义向量、AI作图等。 pip install…

抖音电商品牌力不足咋办?如何升级或强开旗舰店、官方旗舰店?我们有妙招!

随着抖音电商的发展&#xff0c;越来越多的商家蜂拥而至&#xff0c;入驻经营抖音小店... 然而我们在开店的时候&#xff0c;选择开通官方旗舰店、旗舰店、专营店或专卖店&#xff0c;却被系统提示为你的商标品牌力不足&#xff0c;无法开通官方旗舰店、旗舰店、专营店、专卖店…

【AI考证笔记】NO.1人工智能的基础概念

以下部分内容来自于百度智能云人才认证培训讲义&#xff0c;腾讯等也有人工智能类似的讲义&#xff0c;限时免费&#xff0c;也就是不报考&#xff0c;也能系统学习&#xff0c;课程做的都是不错的。有感兴趣的朋友&#xff0c;可以去检索学习。 本系列是学习笔记&#xff0c;…

Android笔记(十四):JetPack Compose中附带效应(一)

在Android应用中可以通过定义可组合函数来搭建应用界面。应用界面的更新往往是与可组合函数内部定义的状态值相关联的。当界面的状态值发生变更&#xff0c;会导致应用界面进行更新。在Android笔记&#xff08;九&#xff09;&#xff1a;Compose组件的状态&#xff0c;对Compo…

定制嵌入式主板:满足客户的实际需求

随着物联网、智能家居、智能工厂等应用的不断发展&#xff0c;嵌入式系统的应用场景也越来越广泛。嵌入式系统的核心部分是嵌入式主板&#xff0c;而定制化的嵌入式主板已经成为了很多企业和项目的首选。本文将从以下几个方面介绍定制嵌入式主板。 一、定制嵌入式主板的概念 定…