远程调用负载均衡LoadBalancer

1. 什么是负载均衡

负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。

根据负载均衡发生位置的不同,一般分为服务端负载均衡客户端负载均衡
服务端负载均衡 :指的是发生在服务提供者一方,比如常见的Nginx负载均衡
客户端负载均衡 : 指的是发生在服务请求的一方,也就是在发送请求之前已经选好了由哪个实例处理请求

微服务调用关系中一般会选择客户端负载均衡,也就是在服务调用的一方来决定服务由哪个提供者执行。

2. 自定义负载均衡

1.通过idea再启动一个 shop-product 微服务,设置其端口为8082

java 复制代码
-Dserver.port=8082

2.通过nacos查看微服务的启动情况

3.修改 OrderServiceImpl 的代码,实现负载均衡

java 复制代码
package com.sun.service.impl;

import com.alibaba.fastjson.JSON;
import com.sun.dao.OrderDao;
import com.sun.pojo.Order;
import com.sun.pojo.Product;
import com.sun.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Random;

/**
 * @author lk
 * @version 1.0.0
 * @Description TODO
 * @createTime 2025/5/8 4:25
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService{

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;

    @Override
    public Order createOrder(Long productId, Long userId) {
        log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", productId);
        //从nacos中获取服务地址
        //自定义规则实现随机挑选服务
        List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
        int index = new Random().nextInt(instances.size());
        ServiceInstance instance = instances.get(index);
        String url = instance.getHost()+":"+instance.getPort();
         log.info(">>从nacos中获取到的微服务地址为:" + url);
        //远程调用商品微服务,查询商品信息
        Product product = restTemplate.getForObject(
                "http://"+url+"/product/get?pid="+productId,Product.class);
        log.info("查询到{}号商品的信息,内容是:{}", productId, JSON.toJSONString(product));
        //创建订单并保存
        Order order = new Order();
        order.setUid(userId);
        order.setUsername("叩丁狼教育");
        order.setPid(productId);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        orderDao.save(order);
        log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));
        return order;
    }
}

4.启动两个服务提供者和一个服务消费者,多访问几次消费者测试效果

3.基于LoadBalancer实现负载均衡

Spring Cloud 2020版本以后,默认移除了对Netflix的依赖,其中就包括Ribbon,官方默认推荐使用
Spring Cloud LoadBalancer正式替换Ribbon,并成为了Spring Cloud负载均衡器的唯一实现。

1.添加相关依赖(订单服务)

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

2.在RestTemplate 的生成方法上添加@LoadBalanced注解

java 复制代码
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
	return new RestTemplate();
}

3.修改OrderServiceImpl服务调用的方法

java 复制代码
package com.sun.service.impl;

import com.alibaba.fastjson.JSON;
import com.sun.dao.OrderDao;
import com.sun.pojo.Order;
import com.sun.pojo.Product;
import com.sun.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Random;

/**
 * @author lk
 * @version 1.0.0
 * @Description TODO
 * @createTime 2025/5/8 4:25
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService{

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public Order createOrder(Long productId, Long userId) {
        log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", productId);
        //从nacos中获取服务地址
        //自定义规则实现随机挑选服务
        //远程调用商品微服务,查询商品信息
        Product product = restTemplate.getForObject(
                "http://product-service/product/get?pid="+productId,Product.class);
        log.info("查询到{}号商品的信息,内容是:{}", productId, JSON.toJSONString(product));
        //创建订单并保存
        Order order = new Order();
        order.setUid(userId);
        order.setUsername("叩丁狼教育");
        order.setPid(productId);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        orderDao.save(order);
        log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));
        return order;
    }
}

4.通过日志可以查看到,请求在8081和8082轮询的访问

4.修改负载均衡策略

LoadBalancer默认提供了两种负载均衡策略。

  • 1.RandomLoadBalancer-随机分配策略
  • 2.RoundRobinLoadBalancer-轮询分配策略(默认)

通过配置的方式修改默认的负载均衡策略

java 复制代码
@LoadBalancerClient(name = "product-service",configuration = RandomLoadbalancerConfig.class)
public class RandomLoadbalancerConfig {
    @Bean
    public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }
}
相关推荐
Coder码匠20 分钟前
Dockerfile 优化实践:从 400MB 到 80MB
java·spring boot
Mr_sun.1 小时前
Day03——微服务网关与配置中心
微服务·云原生·架构
李慕婉学姐8 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆9 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin10 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model200510 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉10 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国10 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_9418824810 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈11 小时前
两天开发完成智能体平台
java·spring·go