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,一经查实,立即删除!

相关文章

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

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

<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 长短期记忆网…

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

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

【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;运行时异常也…

鲁教版六年级数学下册-笔记

文章目录 第五章 基本平面图形1 线段、射线、直线2 比较线段的长短3 角4 角的比较5 多边形和圆的初步认识第六章 整式的乘除1 同底数幂的乘法2 幂的乘方与积的乘方3 同底数幂的除法4 零指数幂与负整数指数幂5 整式的乘法6 平方差公式7 完全平方公式8 整式的除法 第七章 相交线与…

全域运营是割韭菜吗?常见套路有哪些?

随着全域运营赛道的全面开启&#xff0c;全域运营服务商和全域运营系统的数量迅速增加&#xff0c;持续激发赛道活力的同时&#xff0c;也让一些试图用全域运营割韭菜的人有了可趁之机。 值得庆幸的是&#xff0c;由于当前全域运营赛道刚兴起不久&#xff0c;因此&#xff0c;割…

Python | Leetcode Python题解之第110题平衡二叉树

题目&#xff1a; 题解&#xff1a; class Solution:def isBalanced(self, root: TreeNode) -> bool:def height(root: TreeNode) -> int:if not root:return 0leftHeight height(root.left)rightHeight height(root.right)if leftHeight -1 or rightHeight -1 or a…

C++青少年简明教程:If选择语句

C青少年简明教程&#xff1a;If选择语句 C中选择语句的语法是&#xff1a; if (条件) { 条件成立时需要执行的语句... } [else { 条件不成立时需要执行的语句... }] 说明&#xff1a; if后面使用一个括号&#xff0c;括号里是条件——关系表达式。 所谓的关系表达式就是判…

5.24学习记录

[FSCTF 2023]ez_php2 比较简单的pop链 <?php highlight_file(__file__); Class Rd{public $ending;public $cl;public $poc;public function __destruct(){echo "All matters have concluded";die($this->ending);}public function __call($name, $arg){for…

E1载波:一种2.048Mbps速率的PCM载波

E1载波的基本帧由32个子信道组成 帧长为256个bit,分为32个相等时隙&#xff0c;一个时隙为8个bit。256/328 时隙的编号为CH0~CH31 全帧包含256位,且每一帧用 125us时间传送 E1载波支持的数据传输效率为2.048Mbps&#xff0c;用PCM编码&#xff08;即 256bit/125us2.048Mbps…

微信小程序源码-基于Java后端的小区租拼车管理信息系统毕业设计(附源码+演示录像+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设…