4.2 RestTemplate 详解

4.2.1 GET 请求

在 RestTemplate 中,对GET请求可以通过如下两个方法进行调用实现。

1.getForEntity函数。

该方法返回的是ResponseEntity,该对象是Spring对HTTP请求响应的封装,其中主要存储了HTTP的几个重要元素,比如HTTP请求状态码的枚举对象Httpstatus(也就是我们常说的404、500这些错误码)、在它的父类HttpEntity中还存储着HTTP请求的头信息对象HttpHeaders 以及泛型类型的请求体对象。

ResponseEntity responseEntity = restTemplate.getForEntity(“http://HELLO-SERVICE/hello?userName={1}”,

String.class, “didi”);

String body = responseEntity.getBody();

ResponseEntity responseEntity = restTemplate.getForEntity(“http://HELLO-SERVICE/hello?userName={1}”,

User.class, “didi”);

User body = responseEntity.getBody();

2.getFor0bject函数。

String result = restTemplate.getForObject(“http://HELLO-SERVICE/hello?userName={1}”,

String.class, “dodo”);

User user=restTemplate.getForObject(“http://HELLO-SERVICE/hello?userName={1}”,

User.class, “dodo”);

4.2.2 POST 请求

有一个最简单有效的办法:postFprObject

User param = new User();

param.setUserName(“ninesun”);

param.setAge(12);

User user1 = (User) restTemplate.postForObject(“http://HELLO-SERVICE/hello”,

param, Object.class);

下面解释一下上面的代码:

param是我们在发送post请求时所携带的参数,Object是我们返回的结果类型

4.3 负载均衡策略

4.3.1 AbstractLoadBalancerRule

负载均衡策略的抽象类,在该抽象类中定义了负载均衡器工LoadBalancer对象,该对象能够在具体实现选择服务策略时,获取到一些负载均衡器中维护的信息来作为分配依据,并以此设计一些算法来实现针对特定场景的高效策略。

首先引入ribbon的两个核心依赖

com.netflix.ribbon

ribbon-loadbalancer

2.3.0

com.netflix.ribbon

ribbon-core

2.3.0

import com.netflix.client.IClientConfigAware;

import com.netflix.client.config.IClientConfig;

import com.netflix.loadbalancer.ILoadBalancer;

import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.Server;

public class AbstractLoadBalancerRule implements IRule, IClientConfigAware {

private ILoadBalancer lb;

@Override

public void initWithNiwsConfig(IClientConfig clientConfig) {

}

@Override

public Server choose(Object key) {

return null;

}

@Override

public void setLoadBalancer(ILoadBalancer lb) {

this.lb = lb;

}

@Override

public ILoadBalancer getLoadBalancer() {

return lb;

}

}

4.3.2 RandomRule

该策略实现了从服务实例清单中随机选择个服务实例的功能。它的具体实现如下,可以看到IRule接口的choose 0bject key)函数实现,委托给了该类中的choose(ILoadBalancer lb,object key),该方法增加了一个负载均衡器对象的参数。

从具体的实现上看,它会使用传入的负载均衡器来获得可用实例列表upList和所有实例列表 allList,并通过rand.nextInt (serverCount)函数来获取一个随机数,并将该随机数作为upList的索引值来返回具体实例。

同时,具体的选择逻辑在一个while(server == null)循环之内,而根据选择逻辑的实现,正常情况下每次选择都应该选出一个服务实例,如果出现死循环获取不到服务实例时,则很有可能存在并发的Bug。

import com.netflix.client.IClientConfigAware;

import com.netflix.client.config.IClientConfig;

import com.netflix.loadbalancer.ILoadBalancer;

import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.Server;

import java.util.List;

import java.util.Random;

public class RandomRule implements IRule, IClientConfigAware {

private ILoadBalancer lb;

@Override

public void initWithNiwsConfig(IClientConfig clientConfig) {

}

@Override

public Server choose(Object key) {

return choose(getLoadBalancer(), key);

}

public Server choose(ILoadBalancer lb, Object key) {

Server server = null;

while (server == null) {

if (Thread.interrupted()) {

return null;

}

List upList = lb.getReachableServers();

List allList = lb.getAllServers();

int serverCount = allList.size();

if (serverCount == 0) {

return null;

}

Random random = new Random();

int index = random.nextInt(serverCount);

server = upList.get(index);

if (server == null) {

Thread.yield();

continue;

}

if (server.isAlive()) {

return server;

}

server = null;

Thread.yield();

}

return server;

}

@Override

public void setLoadBalancer(ILoadBalancer lb) {

this.lb = lb;

}

@Override

public ILoadBalancer getLoadBalancer() {

return lb;

}

}

4.3.3 RoundRobinRule

该策略实现了按照线性轮询的方式依次选择每个服务实例的功能。它的具体实现如下,其详细结构与RandomRule非常类似。除了循环条件不同外,就是从可用列表中获取所谓的逻辑不同。从循环条件中,我们可以看到增加了一个count计数变量,该变量会在每次循环之后累加,也就是说,如果一直选择不到server超过10次,那么就会结束尝试,并打印一个警告信息No available alive servers after 10 tries from load balancer: …。

import com.netflix.client.IClientConfigAware;

import com.netflix.client.config.IClientConfig;

import com.netflix.loadbalancer.ILoadBalancer;

import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.Server;

import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j

public class RoundRobinRule implements IRule, IClientConfigAware {

private ILoadBalancer lb;

private AtomicInteger nextServerCyclicCounter;

public RoundRobinRule() {

nextServerCyclicCounter = new AtomicInteger(0);

}

public RoundRobinRule(ILoadBalancer lb) {

this();

setLoadBalancer(lb);

}

@Override

public void initWithNiwsConfig(IClientConfig clientConfig) {

}

@Override

public Server choose(Object key) {

return choose(getLoadBalancer(), key);

}

public Server choose(ILoadBalancer lb, Object key) {

Server server = null;

int count = 0;

while (server == null && count++ < 10) {

List reachableServers = lb.getReachableServers();

List allServers = lb.getAllServers();

int upCount = reachableServers.size();

int serverCount = allServers.size();

if (upCount == 0 || serverCount == 0) {

log.warn(“No available alive servers after 10 tries from load balancer:” + lb);

return null;

}

int nextServerIndex = incrementAndGetModulo(serverCount);

server = allServers.get(nextServerIndex);

if (server == null) {

Thread.yield();

continue;

}

if (server.isAlive() && server.isReadyToServe()) {

return server;

}

server = null;

}

if (count >= 10) {

log.warn(“No available alive servers after 10 tries from load balancer:” + lb);

}

return server;

}

@Override

public void setLoadBalancer(ILoadBalancer lb) {

this.lb = lb;

}

@Override

public ILoadBalancer getLoadBalancer() {

return lb;

}

private int incrementAndGetModulo(int modulo) {

int current;

int next;

do {

current = this.nextServerCyclicCounter.get(); //nextServerCyclicCounter是AtomicInteger对象,默认值0,可保证线程安全性

next = (current + 1) % modulo; //每次往后移一位,取集合中的下一个server。这里要注意的是从1开始,即数组中的第二个server会被第一个调用。

} while (!this.nextServerCyclicCounter.compareAndSet(current, next)); //操作完成后用CAS操作将next赋值给nextServerCyclicCounter

return next;

}

}

4.3.4 RetryRule

该策略实现了一个具备重试机制的实例选择功能。从下面的实现中我们可以看到,在其内部还定义了一个IRule对象,默认使用了RoundRobinRule实例。而在choose方法中则实现了对内部定义的策略进行反复尝试的策略,若期间能够选择到具体的服务实例就返回,若选择不到就根据设置的尝试结束时间为阈值(maxRetryMillis参数定义的值+ choose方法开始执行的时间戳),当超过该阈值后就返回null。

import com.netflix.loadbalancer.ILoadBalancer;

import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.InterruptTask;

import com.netflix.loadbalancer.Server;

public class RetryRule extends AbstractLoadBalancerRule {

IRule iRule = new RoundRobinRule();

long maxRetryMillis = 500;

@Override

public Server choose(Object key) {

return choose(getLoadBalancer(), key);

}

public Server choose(ILoadBalancer lb, Object key) {

long requestTime = System.currentTimeMillis();

long deadline = requestTime + maxRetryMillis;

Server answer = null;

answer = iRule.choose(key);

if ((answer == null || !answer.isAlive()) && (System.currentTimeMillis() < deadline)) {

InterruptTask task = new InterruptTask(deadline - System.currentTimeMillis());

while (!Thread.interrupted()) {

answer = iRule.choose(key);

if ((answer == null || !answer.isAlive()) && (System.currentTimeMillis() < deadline)) {

Thread.yield();

} else {

break;

}

}

task.cancel();

}

if (answer == null || !answer.isAlive()) {

return null;

} else {

return answer;

}

}

}

4.3.4 WeightedResponseTimeRule

该策略是对RoundRobinRule 的扩展,增加了根据实例的运行情况来计算权重,并根据权重来挑选实例,以达到更优的分配效果,它的实现主要有三个核心内容。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)

最近我根据上述的技术体系图搜集了几十套腾讯、头条、阿里、美团等公司21年的面试题,把技术点整理成了视频(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分

yMS-1711789589719)] [外链图片转存中…(img-MYpR2fMx-1711789589720)] [外链图片转存中…(img-IV4z0JVi-1711789589721)] [外链图片转存中…(img-CVUowYPC-1711789589721)] [外链图片转存中…(img-cKHJXGDF-1711789589722)] [外链图片转存中…(img-icH195LM-1711789589722)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java) [外链图片转存中…(img-VHwUHxv0-1711789589723)]

[外链图片转存中…(img-pxnkOEkx-1711789589723)]

最近我根据上述的技术体系图搜集了几十套腾讯、头条、阿里、美团等公司21年的面试题,把技术点整理成了视频(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分

[外链图片转存中…(img-T8fjwLxR-1711789589724)]

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: