Spring Cloud Alibaba - 08 Ribbon 两种方式实现细粒度自定义配置控制微服务的负载均衡策略

简介: Spring Cloud Alibaba - 08 Ribbon 两种方式实现细粒度自定义配置控制微服务的负载均衡策略

6735aa4777de402592fbe82e8b40ee3d.png

需求


假设我们有个场景:

Order-Center 需要采用随机算法调用产品中心 , 而采用轮询算法调用其他中心微服务


工程


3d9c6c46eb4f41daa4c0cf4fb47b58f1.png


java代码实现细粒度配置 (不推荐)


注意事项: PayCenterRibbonConfig,ProductCenterRibbonConfig不能被放在我们主启动类所在包以及子包下,不然就起不到细粒度配置

【支付中心对应的Ribbon访问策略】


package com.globalconfig;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2022/2/2 19:42
 * @mark: show me the code , change the world
 */
@Configuration
public class PayCenterRibbonConfig {
    @Bean
    public IRule roundRobinRule() {
        return new RoundRobinRule();
    }
}

【产品中心对应的Ribbon访问策略】

package com.globalconfig;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2022/2/2 19:45
 * @mark: show me the code , change the world
 */
@Configuration
public class ProductCenterRibbonConfig {
    @Bean
    public IRule randomRule() {
        return new RandomRule();
    }
}


【带有@LoadBalanced的RestTemplate

package com.artisan.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2022/2/2 15:47
 * @mark: show me the code , change the world
 */
@Configuration
public class WebConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}


【为每个服务分配 访问策略 】

package com.artisan.config;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Configuration;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2022/2/2 19:51
 * @mark: show me the code , change the world
 */
@Configuration
@RibbonClients(value = {
        @RibbonClient(name = "artisan-product-center",configuration = com.globalconfig.ProductCenterRibbonConfig.class),
        @RibbonClient(name = "artisan-pay-center",configuration = com.globalconfig.PayCenterRibbonConfig.class)
})
public class CustomRibbonConfig {
}


【Controller 】

import com.artisan.common.entity.OrderInfo;
import com.artisan.common.entity.PayInfo;
import com.artisan.common.entity.ProductInfo;
import com.artisan.common.vo.OrderAndPayVo;
import com.artisan.common.vo.OrderVo;
import com.artisan.mapper.OrderInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2022/2/2 03:20
 * @mark: show me the code , change the world
 */
@RestController
@Slf4j
public class OrderInfoController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    /**
     * 调用地址, 注册中心 地址
     */
    public static final String PRODUCT_URI = "http://artisan-product-center/selectProductInfoById/";
    public static final String PAY_URI = "http://artisan-pay-center/selectPayInfoByOrderNo/";
    @RequestMapping("/v2/selectOrderInfoById/{orderNo}")
    public Object selectOrderInfoById(@PathVariable("orderNo") String orderNo) {
        OrderInfo orderInfo = orderInfoMapper.selectOrderInfoById(orderNo);
        if (null == orderInfo) {
            return "根据orderNo:" + orderNo + "查询没有该订单";
        }
        // 发起远程Http调用
        ResponseEntity<ProductInfo> responseEntity = restTemplate.getForEntity(PRODUCT_URI + orderInfo.getProductNo(), ProductInfo.class);
        ProductInfo productInfo = responseEntity.getBody();
        if (productInfo == null) {
            return "没有对应的商品";
        }
        OrderVo orderVo = new OrderVo();
        orderVo.setOrderNo(orderInfo.getOrderNo());
        orderVo.setUserName(orderInfo.getUserName());
        orderVo.setProductName(productInfo.getProductName());
        orderVo.setProductNum(orderInfo.getProductCount());
        return orderVo;
    }
    @RequestMapping("/getOrderAndPayInfoByOrderNo/{orderNo}")
    public Object getOrderAndPayInfoByOrderNo(@PathVariable("orderNo") String orderNo) {
        OrderInfo orderInfo = orderInfoMapper.selectOrderInfoById(orderNo);
        if (null == orderInfo) {
            return "根据orderNo:" + orderNo + "查询没有该订单";
        }
        ResponseEntity<PayInfo> responseEntity = restTemplate.getForEntity(PAY_URI + orderInfo.getProductNo(), PayInfo.class);
        PayInfo payInfo = responseEntity.getBody();
        if (payInfo == null) {
            return "没有对应的支付信息";
        }
        OrderAndPayVo orderAndPayVo = new OrderAndPayVo();
        orderAndPayVo.setOrderNo(orderNo);
        orderAndPayVo.setProductNo(orderInfo.getProductNo());
        orderAndPayVo.setProductCount(orderInfo.getProductCount());
        orderAndPayVo.setPayNo(payInfo.getPayNo());
        orderAndPayVo.setPayTime(payInfo.getPayTime());
        orderAndPayVo.setUserName(orderInfo.getUserName());
        return orderAndPayVo;
    }
}


3a6b9cc05d324da9a29b563556f88c73.png2190f82799c94e0f9c0e476be59b0f4d.png

a42b1b622e3f4655b4184a0933dc7dd6.png

349b3ea0722c4a119b6dda0971e7b19c.png


可以看到,实现了我们最开始的需求 。


配置实现细粒度配置 (推荐)

接着上面的工程,首先屏蔽掉 CustomRibbonConfig

c019a2db2e9841908c268fcbc8e7a83d.png

然后再 artisan-cloud-customcfg-ribbon-order 子模块的配置文件 application.yml

增加

#自定义Ribbon的细粒度配置
artisan-pay-center:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
artisan-product-center:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule


然后启动多个Pay和Product服务进行测试

结果如下:

访问4次

cf83ebc33346468693bd8611e057d3cd.png


访问 10次

de3e250eae5647af8c6f0561ed2c6b74.png


源码

https://github.com/yangshangwei/SpringCloudAlibabMaster

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
6月前
|
人工智能 Java Nacos
基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南
本文将针对 Spring AI Alibaba + Nacos 的分布式多智能体构建方案展开介绍,同时结合 Demo 说明快速开发方法与实际效果。
4661 94
|
6月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
7014 90
|
7月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
6102 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
|
6月前
|
人工智能 监控 Java
Spring AI Alibaba实践|后台定时Agent
基于Spring AI Alibaba框架,可构建自主运行的AI Agent,突破传统Chat模式限制,支持定时任务、事件响应与人工协同,实现数据采集、分析到决策的自动化闭环,提升企业智能化效率。
Spring AI Alibaba实践|后台定时Agent
|
8月前
|
人工智能 Java 开发者
邀您参与 “直通乌镇” Spring AI Alibaba 开源竞技挑战赛!
邀您参与 “直通乌镇” Spring AI Alibaba 开源竞技挑战赛!
|
9月前
|
人工智能 数据可视化 Java
性能提升 10 倍, DIFY 模式迁移至 Spring AI Alibaba 模式 零改造实现
将 Dify 应用迁移至 Spring AI Alibaba,可兼顾可视化开发效率与代码工程灵活性,显著提升系统性能与扩展能力,适用于复杂 AI 业务场景。
1231 0

热门文章

最新文章