SpringCloud系列(23)--手写实现负载轮询算法

前言:在上一篇文章中我们介绍了关于负载轮询算法的原理以及看了源代码,而本章节内容则是着重于我们自己手写一个负载轮询算法

1、分别编写provider-payment8001、provider-payment8002这两个子项目的PaymentController类,增加一个/payment/lb接口

provider-payment8001

package com.ken.springcloud.controller;import com.ken.springcloud.entities.CommonResult;
import com.ken.springcloud.entities.Payment;
import com.ken.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.List;@RestController
@Slf4j
public class PaymentController {@Resourceprivate PaymentService paymentService;@Value("${server.port}")private String serverPort;@Resourceprivate DiscoveryClient discoveryClient;@PostMapping("/payment/insert")public CommonResult insert(@RequestBody Payment payment) {int result = paymentService.insert(payment);log.info("插入结果{}",result);if(result > 0) {return new CommonResult(200,"插入数据库成功,提供服务的端口号为" + serverPort,result);}else {return new CommonResult(500,"插入数据库失败",result);}}@GetMapping("/payment/get/{id}")public CommonResult insert(@PathVariable("id") Long id) {Payment payment = paymentService.getPaymentById(id);log.info("查询结果{}",payment);if(payment != null) {return new CommonResult(200,"查询成功,提供服务的端口号为" + serverPort,payment);}else {return new CommonResult(500,"没有对应的数据,查询失败,查询id" + id,payment);}}@GetMapping("/payment/discovery")public Object discovery() {//获取eureka内的服务List<String> services = discoveryClient.getServices();for (String service : services) {log.info("***service:" + service);}//获取服务名为CLOUD-PAYMENT-SERVICE下的实例List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");for (ServiceInstance instance : instances) {log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());}return this.discoveryClient;}@GetMapping("/payment/lb")public String getPaymentLB() {//返回当前服务的端口号return serverPort;}}

provider-payment8002 

package com.ken.springcloud.controller;import com.ken.springcloud.entities.CommonResult;
import com.ken.springcloud.entities.Payment;
import com.ken.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;@RestController
@Slf4j
public class PaymentController {@Resourceprivate PaymentService paymentService;@Value("${server.port}")private String serverPort;@PostMapping("/payment/insert")public CommonResult insert(@RequestBody Payment payment) {int result = paymentService.insert(payment);log.info("插入结果{}",result);if(result > 0) {return new CommonResult(200,"插入数据库成功,提供服务的端口号为" + serverPort,result);}else {return new CommonResult(500,"插入数据库失败",result);}}@GetMapping("/payment/get/{id}")public CommonResult insert(@PathVariable("id") Long id) {Payment payment = paymentService.getPaymentById(id);log.info("查询结果{}",payment);if(payment != null) {return new CommonResult(200,"查询成功,提供服务的端口号为" + serverPort,payment);}else {return new CommonResult(500,"没有对应的数据,查询失败,查询id" + id,payment);}}@GetMapping("/payment/lb")public String getPaymentLB() {//返回当前服务的端口号return serverPort;}}

2、在com.ken.springcloud包下新建名为lb的包,用于存储负载均衡相关的代码 

效果图:

3、在lb包下新建一个名为LoadBalancer的接口类

效果图:

4、编写LoadBalancer接口类
package com.ken.springcloud.lb;import org.springframework.cloud.client.ServiceInstance;import java.util.List;public interface LoadBalancer {ServiceInstance instances(List<ServiceInstance> sserviceINstances);}

5、在lb包下新建一个名为MyBL的类

效果图:

6、编写MyLB类,使其实现LoadBalancer接口类
package com.ken.springcloud.lb;import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;@Component
public class MyLB implements LoadBalancer{private AtomicInteger atomicInteger = new AtomicInteger(0);/*** 获取当前是第几次的请求* @return*/public final int getAndIncrement() {//atomicInteger的期望值int current;int next;do {current = this.atomicInteger.get();next = current >= Integer.MAX_VALUE ? 0 : current + 1;}while (!this.atomicInteger.compareAndSet(current,next));//比较atomicInteger对象当前的值和期望值current,如果atomicInteger对象当前的值和期望值current相同,则把atomicInteger对象当前的值修改为next,并返回trueSystem.out.println("next:" + next);return next;}@Overridepublic ServiceInstance instances(List<ServiceInstance> serviceInstances) {//通过请求数模以提供服务的服务数获取需要提供服务的服务实例下标int index = getAndIncrement() % serviceInstances.size();//返回提供服务的服务实例return serviceInstances.get(index);}
}

7、编写consumer-order80这个子项目的OrderController类,增加一个/payment/lb接口
package com.ken.springcloud.controller;import com.ken.springcloud.entities.CommonResult;
import com.ken.springcloud.entities.Payment;
import com.ken.springcloud.lb.LoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;
import java.net.URI;
import java.util.List;@RestController
@Slf4j
public class OrderController {//public static final String PAYMENT_URL = "http://localhost:8001";public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";@Resourceprivate RestTemplate restTemplate;@Resourceprivate LoadBalancer loadBalancer;@Resourceprivate DiscoveryClient discoveryClient;@PostMapping("/consumer/insert")public CommonResult<Payment> insert(Payment payment) {log.info("payment:{}",payment);return restTemplate.postForObject(PAYMENT_URL + "/payment/insert",payment,CommonResult.class);}/*** 返回对象为响应体中数据转化成的对象,基本上可以理解为Json* @param id* @return*/@GetMapping("/consumer/get/{id}")public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id,CommonResult.class);}/*** 返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头、响应状态码、响应体等* @param id* @return*/@GetMapping("/consumer/getForEntity/{id}")public CommonResult<Payment> getPayment2(@PathVariable("id") Long id) {ResponseEntity<CommonResult> entity =  restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id,CommonResult.class);if(entity.getStatusCode().is2xxSuccessful()) {return entity.getBody();}else {return new CommonResult<>(500,"异常");}}@GetMapping("/consumer/payment/lb")public String getPaymentLB() {//获取服务名为CLOUD-PAYMENT-SERVICE下的实例List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");if (instances == null || instances.size() <= 0) {return null;}//获取提供接口服务的服务实例ServiceInstance serviceInstance = loadBalancer.instances(instances);//获取接口地址URI uri = serviceInstance.getUri();//请求服务接口return restTemplate.getForObject(uri + "/payment/lb",String.class);}}

8、分别启动eureka-server7001、eureka-server7002、provider-payment8001、provider-payment8002、consumer-order80,然后在浏览器地址栏输入
http://localhost/consumer/payment/lb 并回车调用接口,可以看到接口调用成功,并会按照预想的那样轮询地分别访问provider-payment8001和provider-payment8002服务

效果图:

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

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

相关文章

C++中引用的全面解析与实战应用

C中的引用作为一种强大的特性&#xff0c;不仅能够提升代码的效率和清晰度&#xff0c;还能在一定程度上保障数据的安全性。本文将深入探讨引用的各个方面&#xff0c;包括其定义、使用场景、类型、与指针的区别&#xff0c;并通过实例加以说明。 引用的定义与基本概念 引用可…

探究Python中的元组:不可变性与多重用途

元组是 Python 中的另一种重要数据结构&#xff0c;与列表相似&#xff0c;但具有一些关键区别。让我们来详细了解一下 Python 中的元组&#xff0c;包括基本语法、常用命令、示例代码、应用场景、注意事项和总结。 基本语法 创建元组 在 Python 中&#xff0c;元组使用圆括…

Py之llama-parse:llama-parse(高效解析和表示文件)的简介、安装和使用方法、案例应用之详细攻略

Py之llama-parse&#xff1a;llama-parse(高效解析和表示文件)的简介、安装和使用方法、案例应用之详细攻略 目录 llama-parse的简介 llama-parse的安装和使用方法 1、安装 2、使用方法 第一步&#xff0c;获取API 密钥 第二步&#xff0c;安装LlamaIndex、LlamaParse L…

AI爆文写作:经常做这四个小练习,让你解锁爆文标题的秘籍,让你的标题炸裂吸晴!

文章目录 一、无法吸引眼球的标题二、标题炸裂的秘籍练习1:洞察受众的渴望与恐惧。练习2:运用感官语言,用生动的描述和具体细节,在读者心中勾勒出一幅画面。练习3:展示变化。练习4:用意外转折激发好奇心。一、无法吸引眼球的标题 这样的标题: [如何通过阅读改变人生」「…

LeetCode 1542.找出最长的超赞子字符串:前缀异或和(位运算)

【LetMeFly】1542.找出最长的超赞子字符串&#xff1a;前缀异或和&#xff08;位运算&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/find-longest-awesome-substring/ 给你一个字符串 s 。请返回 s 中最长的 超赞子字符串 的长度。 「超赞子字符串」需…

<string.h>中部分库函数的模拟实现

前言 嗨&#xff0c;我是firdawn&#xff0c;本章将简单介绍&#xff0c;<string.h>中部分库函数的模拟实现&#xff0c;如strncpy&#xff0c;strncat&#xff0c;memcpy&#xff0c;memmove。在本文片末&#xff0c;还讲简单介绍判断机器大小端的函数实现&#xff0c;…

VSCode SAP Systems配置HTTPS访问SAP

第一次访问提示&#xff0c;Self-Signed 证书 解决办法&#xff1a;https访问SAP Fiori网站&#xff0c;导出SSL证书为DER格式保存到硬盘上 双击DER文件&#xff0c;导入到系统 退出VSCode&#xff0c;再次启动 Test Connection, 提示 The system URL is using a hostname …

服务器攻防-中间件安全,weblogic(没怎么搞懂)

1.weblogic-工具 jboss 1.弱口令 直接输入admin就就去了 2.反序列化&#xff08;不是很懂java) jenkins glassfish 读密码文件 读取 就可以知道它的密码 我们就可以写脚本

使用DataGrip连接跳板机后再连接远程服务器的mysql数据库

相比配置本地数据库就是多了一步SSH/SSL配置。 添加新的mysql连接&#xff0c;选择SSH/SSL&#xff0c;勾选Use SSH tunnel&#xff1a; 点击右边的…配置跳板机连接&#xff0c;输入账号密码&#xff0c;然后保存&#xff1a; 接着配置General&#xff0c;里面填上要连接的数…

一款数字化管理平台源码:云MES系统(附架构图、流程)技术架构:springboot + vue-element-plus-admin

制造生产企业打造数字化生产管控的系统&#xff0c;从原材料、生产报工、生产过程、质检、设备、仓库等整个业务流程的管理和控制&#xff0c;合理安排生产计划、实时监控生产、优化生产工艺、降低不良产出和运营成本&#xff1b; 技术架构&#xff1a;springboot vue-elemen…

DHT11获取数据传输到PC端

1.DHT11的时序数据 a : dht 1 b &#xff1a;dht 0延时30ms c&#xff1a; dht 1 卡d点&#xff1b;while(dht1); 卡e点 while(!dht) 卡f点&#xff1a;while(dht) 卡g点&#xff1a;while(!dht) 有效数据都是高电平&#xff0c;持续时间不一样&#xff0c;50us读&#…

Go语言实现人脸检测(Go的OpenCV绑定库)

文章目录 OpenCVGithub官网安装环境变量 Go的OpenCV绑定库Github文档安装搜索视频设备ID显示视频检测人脸 OpenCV Github https://github.com/opencv/opencv/ 官网 https://opencv.org/ 安装 brew install opencv brew upgrade opencv安装目录 cd /usr/local/opt/opencv…

子比主题ACG美化插件[全开源]

WordPress插件是一种可以扩展和增强WordPress网站功能的应用程序。子比主题ACG美化插件听起来像是一个专门为ACG&#xff08;动画、漫画、游戏&#xff09;爱好者设计的美化插件&#xff0c;它可能包含多种功能来改善网站的外观和用户体验。 内置功能开关100意味着这个插件提供…

基于CNN卷积神经网络的金融数据预测matlab仿真,对比BP,RBF,LSTM

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 反向传播网络&#xff08;BP&#xff0c;多层感知器MLP&#xff09; 4.2 径向基函数网络&#xff08;RBF&#xff09; 4.3 卷积神经网络&#xff08;CNN&#xff09; 4.4 长短期记忆网…

六(1)、RTKLIB源码解析 — rnx2rtkp.c

目录 一、前言 二、main中的参数说明 三、main中的代码解读 3.1 总体逻辑框架

计算机网络套接字知识(非常详细)从零基础入门到精通

本节重点 认识IP地址, 端口号, 网络字节序等网络编程中的基本概念; 学习socket api的基本用法; 一、预备知识 1.理解源IP地址和目的IP地址 ⭐在IP数据包头部中&#xff0c;有两个IP地址&#xff0c;分别叫做源IP地址和目的IP地址。 思考: 我们光有IP地址就可以完成通信了…

Kotlin Flow应用举例,launchIn 和collect用法及区别

launchIn 和 collect 都可以用于处理 MutableStateFlow<Message> 消息流&#xff0c;但它们有不同的用途和使用场景。 collect 用于在协程中收集消息流的最新值。它会一直监听消息流&#xff0c;并在每次消息流的值发生变化时执行指定的代码块。 launchIn 用于在协程作…

【30天精通Prometheus:一站式监控实战指南】第7天:postgres_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们&#x1f44b;   欢迎加入【30天精通Prometheus】专栏&#xff01;&#x1f4da; 在这里&#xff0c;我们将探索Prometheus的强大功能&#xff0c;并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。&#x1f680;   Prometheus是云原生和DevOps的…

Java基础之异常(简单易懂)

异常 1.JAVA异常体系 &#xff08;1&#xff09;Throwable类(表示可抛)是所有异常和错误的超类&#xff0c;两个直接子类为Error和Exception,分别表示错误和异常;其中异常类Exception又分为运行时异常和非运行时异常&#xff0c;这两个异常有很大区别&#xff0c;运行时异常也…

代码随想录算法训练营第三十一天| 贪心算法理论基础、LeetCode455.分发饼干、LeetCode376. 摆动序列 、LeetCode53. 最大子序和

贪心算法理论基础&#xff1a; 贪心算法没有类似递归、回溯的套路。主要的思想可以理解为&#xff1a;用局部最优找全局最优。 #LeetCode 455. Assign Cookies #LeetCode 455. 视频讲解&#xff1a;贪心算法&#xff0c;你想先喂哪个小孩&#xff1f;| LeetCode&#xff1a;4…