手写一个客户端负载均衡器

1.前提准备

本文是在使用nacos的基础上进行的简单讲解,如果nacos了解的不多的朋友可以先了解下nacos的基本用法,传送地址:【Nacos的介绍和使用】

2.关于服务端负载均衡

手写一个客户端负载均衡器_第1张图片

单体架构模式下,一个应用会用多个实例,通过nginx做反向代理,将请求过来的数据通过负载均衡算法确定好指定实例进行转发,而nginx是部署是在服务器端的,这种方式就叫做服务端的负载均衡

3.关于客户端负载均衡

手写一个客户端负载均衡器_第2张图片
内容中心通过discoveryClient获取到用户中心的所有实例,我们通过手写一个负载均衡的规则确定好请求哪个实例,通过RestTemplate进行请求这样就实现了手写的一个客户端负载均衡器。

4.启动服务

准备2个服务content-center和user-center,user-center准备2个实例,后面使用content-center选择user-center的实例进行调用。可参考:【Nacos的介绍和使用】
在这里插入图片描述

5 content-center 编码

5.1 ShareController.java
package com.ding.contentcenter.controller.content;

import com.ding.contentcenter.domain.dto.content.ShareDTO;
import com.ding.contentcenter.service.content.ShareService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/shares")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ShareController {
    private final ShareService shareService;
    @GetMapping("/{id}")
    public ShareDTO findById(@PathVariable Integer id){
        return this.shareService.findById(id);
    }
}
5.2 ShareService.java
package com.ding.contentcenter.service.content;

import com.alibaba.nacos.client.naming.utils.ThreadLocalRandom;
import com.ding.contentcenter.dao.share.ShareMapper;
import com.ding.contentcenter.domain.dto.content.ShareDTO;
import com.ding.contentcenter.domain.dto.user.UserDTO;
import com.ding.contentcenter.domain.entity.share.Share;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
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.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ShareService {
    private final ShareMapper shareMapper;
    private final RestTemplate restTemplate;
    private final DiscoveryClient discoveryClient;
    public ShareDTO findById(Integer id){
        Share share = this.shareMapper.selectByPrimaryKey(id);
        Integer userId = share.getUserId();
        List<ServiceInstance> instances = discoveryClient.getInstances("user-center");
        // 获取一个用户中心地址
        /*String targetURL = instances.stream()
                .map(instance -> instance.getUri().toString()+"/users/{id}")
                .findFirst()
                .orElseThrow(()->new IllegalArgumentException("当前没有实例"));*/


        // 所有用户中心的请求地址
        List <String> targetURLS = instances.stream()
                .map(instance -> instance.getUri().toString()+"/users/{id}")
                        .collect(Collectors.toList());

        int i = ThreadLocalRandom.current().nextInt(targetURLS.size());


        log.info("请求的目标地址:{}",targetURLS.get(i));

        UserDTO userDTO = this.restTemplate.getForObject(
                targetURLS.get(i),  // 随机取出一个用户中心的请求地址
                UserDTO.class,userId
        );

        // 消息的装配
        ShareDTO shareDTO = new ShareDTO();
        BeanUtils.copyProperties(share,shareDTO);
        shareDTO.setWxNickname(userDTO.getWxNickname());

        return shareDTO;
    }
}
5.3 多次调用地址

http://localhost:8082/shares/1

5.4 响应结果:
{
	"id": 1,
	"userId": 1,
	"title": "xxx",
	"createTime": "2022-04-17T16:28:34.000+00:00",
	"updateTime": "2022-04-17T16:28:34.000+00:00",
	"isOriginal": false,
	"author": "earnest",
	"cover": "xxx",
	"summary": "",
	"price": 0,
	"downloadUrl": "",
	"buyCount": 1,
	"showFlag": false,
	"auditStatus": "0",
	"reason": "",
	"wxNickname": "212aa"
}
5.6 查看随机请求实例:

手写一个客户端负载均衡器_第3张图片
总结:客户端content-center每次生成随机的user-center服务端请求地址进行请求实现了简单的客户端负载均衡。

提示:@LoadBalanced记得注释,这个注解是RestTemplate用来整合Ribbon,不注解以上请求会失效

(此文完)

你可能感兴趣的:(+,Nacos,负载均衡,java)