前置内容
(1)、微服务理论入门和手把手带你进行微服务环境搭建及支付、订单业刘丽娜务编写
(2)、springcloud之eureka服务注册与发现
(3)、springcloud之zookeeper进行服务注册与发现
(4)、springcloud之consul进行服务注册与发现
(1)、ribbon是什么?
springcloud-ribbon
是基于netflix ribbon
实现的一套客户端负载均衡的工具。简单来说,ribbon
是netflix
发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。ribbon
客户给水排水工程师端组件提供一系列完善的配置如连接超时、重拾等。简单的说,就是在配置文件中列出load balancer
(简称lb
)后面的所有机器,ribbon
会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们很容易使用ribbon
实现自定义的负载均衡算法。一句话就是 负载均衡+resttemplate调用。(2)、ribbon的官网
官网地址
且目前也进入了维护模式
(3)、负载均衡(lb)
负载均衡就是将用户的请求平摊的分配到多个服务上,从而达到系统的ha
(高可用)。常见的负载均衡由软件nginx
、lvs
、f5
。1.集中式lb:就是在服务的消费方和提供方之间使用独立的lb
设施(可以是硬件,如f5
,也可以是软件,如nginx
),由该设施负责把访问请求通过某种策略转发至服务的提供方。
2.进程内lb:将lb
逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。ribbon
就属于进程内lb
,它只是一个类库,集成于消费方进程,消费方通过它来获取服务提供方的地址。
(4)、ribbon本地负载均衡客户端和nginx服务端负载均衡的区别
nginx
是服务器负载均衡,客户端所有请求都会交给nginx
实现转发请求。即负载均衡是由服务端实现的。ribbon
本地负载均衡,在调用微服务接口的时候,会在注册中心获取注册信息列表之后缓存到jvm
本地,从而在本地实现rpc
远程服务调用技术。(1)、架构说明
ribbon
其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka
结合只是其中的一个实例。
ribbon在工作时分为两步
第一步先选择eurekarver
,他优先选择在同一个区域内负载较少的rver
。第二步再根据用户指定的策略,在从rver
取到的服务注册列表中选择一个地址。其中ribbon
提供了多种策略:比如轮询、随机和根据响应时间加权。(2)、pom文件
所以在引入eureka
的整合包中就包含了整合ribbon
的jar
包。
所以我们前面实现的8001和8002
交替访问的方式就是所谓的负载均衡。
(3)、resttemplate的说明
getforobject:返回对象为响应体中数据转化成的对象,基本上可以理解为json
。getforentity:返回对象为responentity
对象,包含了响应中的一些重要信息,比如响应头、响应状态码、响应体等。postforobjectpostforentity
1. 主要的负载规则
roundrobinrule
:轮询randomrule
:随机retryrule
:先按照roundrobinrule的策略获取服务,如果获取服务失败则在指定时间内会进行重试weightedrespontimerule
:对roundrobinrule的扩展,响应速度越快的实例选择权重越大,越容易被选择bestavailablerule
:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务availabilityfilteringrule
:先过滤掉故障实例,再选择并发较小的实例zoneavoidancerule
:默认规则,复合判断rver所在区域的性能和rver的可用性选择服务器2. 如何替换负载规则
对cloud-consumer-order80
包下的配置进行修改。我们自己自定义的配置类不能放在@componentscan
所扫描的当前包以及子包下,否则我们自定义的这个配置类就会被所有的ribbon
客户端所共享,达不到特殊化定制的目的了。在com.xiao
的包下新建一个myrule
的子包。在myrule
的包下新建一个mylfrule
配置类
import com.netflix.loadbalancer.irule;import com.netflix.loadbalancer.randomrule;import org.springframework.context.annotation.bean;import org.springframework.context.annotation.configuration;@configurationpublic class mylfrule { @bean public irule getrandomrule(){ return new randomrule(); // 新建随机访问负载规则 }}对主启动类进行修改,修改为如下:
import com.xiao.myrule.mylfrule;import org.springframework.boot.springapplication;import org.springframework.boot.autoconfigure.springbootapplication;import org.springframework.cloud.netflix.eureka.enableeurekaclient;import org.springframework.cloud.netflix.ribbon.ribbonclient;@springbootapplication@enableeurekaclient@ribbonclient(name = "cloud-payment-rvice",configuration = mylfrule.class)public class ordermain80 { public static void main(string[] args) { springapplication.run(ordermain80.class,args); }}
6.测试结果 结果就是以我们最新配置的随机方式进行访问的。
rest
接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标,每次服务重新启动后rest
接口计数从1
开始。
import com.netflix.client.config.iclientconfig;import java.util.list;import java.util.concurrent.atomic.atomicinteger;import org.slf4j.logger;import org.slf4j.loggerfactory;public class roundrobinrule extends abstractloadbalancerrule { private atomicinteger nextrvercycliccounter; private static final boolean available_only_rvers = true; private static final boolean all_rvers = fal; private static logger log = loggerfactory.getlogger(roundrobinrule.class); public roundrobinrule() { this.nextrvercycliccounter = new atomicinteger(0); } public roundrobinrule(iloadbalancer lb) { this(); this.tloadbalancer(lb); } public rver choo(iloadbalancer lb, object key) { 主持人开场白 if (lb == null) { log.warn("no load balancer"); return null; } el { rver rver = null; int count = 0; while(true) { if (rver == null && count++ < 10) { // 获取状态为up的服务提供者 list<rver> reachablervers = lb.getreachablervers(); // 获取所有的服务提供者 list<rver> allrvers = lb.getallrvers(); int upcount = reachablervers.size(); int rvercount = allrvers.size(); if (upcount != 0 && rvercount != 0) { // 对取模获得的下标进行获取相关的服务提供者 int nextrverindex = this.incrementandgetmodulo(rvercount); rver = (rver)allrvers.get(nextrverindex); if (rver == null) { thread.yield(); } el { if (rver.isalive() && rver.isreadytorve()) { return rver; } rver = null; continue; } log.warn("no up rvers available from load balancer: " + lb); return null; } if (count >= 10) { log.warn("no available alive rvers after 10 tries from load balancer: " + lb); } return rver; } } } private int incrementandgetmodulo(int modulo) { int current; int next; do { // 先加一再取模 current = this.nextrvercycliccounter.get(); next = (current + 1) % modulo; // cas判断,如果判断成功就返回true,否则就一直自旋 } while(!this.nextrvercycliccounter.compareandt(current, next)); return next; }}
1. 修改支付模块的controller
添加以下内容
@getmapping(value = "/payment/lb")public string getpaymentlb(){ return rverport;}
2. applicationcontextconfig去掉@loadbalanced注解
3. loadbalancer接口
import org.springframework.cloud.client.rviceinstance;import java.util.list;public interface loadbalancer { //收集服务器总共有多少台能够提供服务的机器,并放到list里面 rviceinstance instances(list<rviceinstance> rviceinstances);}
4. 编写mylb类
import org.sprin大连三日游gframework.cloud.client.rviceinstance;import org.springframework.stereotype.component;import java.util.list;import java.util.concurrent.atomic.atomicinteger;@componentpublic class mylb implements loadbalancer { private atomicinteger atomicinteger = new atomicinteger(0); //坐标 private final int getandincrement(){ int current; int next; do { current = this.atomicinteger.get(); next = current >= 2147483647 ? 0 : current + 1; }while (!this.atomicinteger.compareandt(current,next)); //第一个参数是期望值,第二个参数是修改值是 system.out.println("*******第几次访问,次数next: "+next); return next; } @override public rviceinstance instances(list<rviceinstance> rviceinstances) { //得到机器的列表 int index = getandincrement() % rviceinstances.size(); //得到服务器的下标位置 return rviceinstances.get(index); }}
5. 修改ordercontroller类
import com.xiao.cloud.entities.commonresult;import com.xiao.cloud.entities.pay广州美术学院分数线ment;import com.xiao.cloud.lb.loadbalancer;import lombok.extern.slf4j.slf4j;import org.springframework.beans.factory.annotation.autowired;import org.springframework.cloud.client.rviceinstance;import org.springframework.cloud.client.discovery.discoveryclient;import org.springframework.http.responentity;import org.springframework.web.bind.annotation.getmapping;import org.springframework.web.bind.annotation.pathvariable;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@slf4jpublic class ordercontroller { // public static final string payment_url = "http://localhost:8001"; public static final string payment_url = "http://cloud-payment-rvice"; @resource private resttemplate resttemplate; @resource private loadbalancer loadbalancer; @resource private discoveryclient discoveryclient; @getmapping("/consumer/payment/create") public commonresult<payment> create( payment payment){ return resttemplate.postforobject(payment_url+"/payment/create",payment,commonresult.class); //写操作 } @getmapping("/consumer/payment/get/{id}") public commonresult<payment> getpayment(@pathvariable("id") long id){ return resttemplate.getforobject(payment_url+"/payment/get/"+id,commonresult.class); } @getmapping("/consumer/payment/getforentity/{id}") public commonresult<payment> getpayment2(@pathvariable("id") long id){ responentity<commonresult> entity = resttemplate.getforentity(payment_url+"/payment/get/"+id,commonresult.class); if (entity.getstatuscode().is2xxsuccessful()){ // log.info(entity.getstatuscode()+"\t"+entity.getheaders()); return entity.getbody(); }el { return new commonresult<>(444,"操作失败"); } } @getmapping(value = "/consumer/payment/lb") public string getpaymentlb(){ list<rviceinstance> instances = discoveryclient.getinstances("cloud-payment-rvice"); if (instances == null || instances.size() <= 0){ return null; } rviceinstance rviceinstance = loadbalancer.instances(instances); uri uri = rviceinstance.geturi(); return resttemplate.getforobject(uri+"/payment/lb",string.class); }}
6. 测试结果
最后是在8001
和8002
两个之间进行轮询访问。控制台输出如下7. 包结构示意图
到此这篇关于springcloud中的ribbon进行服务调用的文章就介绍到这了,更多相关springcloud ribbon服务调用内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-04 13:31:44,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/a580079e3f94de02e3d14f948c634c6a.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:聊聊SpringCloud中的Ribbon进行服务调用的问题.doc
本文 PDF 下载地址:聊聊SpringCloud中的Ribbon进行服务调用的问题.pdf
留言与评论(共有 0 条评论) |