当前位置:网站首页>feign客户端请求之LoadBalancerLifecycle生命周期
feign客户端请求之LoadBalancerLifecycle生命周期
2022-07-25 10:18:00 【艾米莉Emily】
LoadBalancerLifecycle接口允许在load-balancing执行前后应执行的操作,我们可以借此入口获取微服务请求的真实请求URL;
一、LoadBalancerLifecycle接口源码
public interface LoadBalancerLifecycle<RC, RES, T> {
/** * 判定服务实例对象是否允许执行方法回调 */
default boolean supports(Class requestContextClass, Class responseClass, Class serverTypeClass) {
return true;
}
/** * 在执行load-balancing之前(即获取真实服务实例url之前)的回调方法 */
void onStart(Request<RC> request);
/** * 已经选择一个真实的服务实例之后,在执行请求之前的回调方法 */
void onStartRequest(Request<RC> request, Response<T> lbResponse);
/** * 在load-balancing负载均衡真实服务请求之后执行 */
void onComplete(CompletionContext<RES, T, RC> completionContext);
}
二、基于loadbalance请求服务有两个FeignBlockingLoadBalancerClient(不支持重试)、RetryableFeignBlockingLoadBalancerClient(支持重试)
我们先看下FeignBlockingLoadBalancerClient的源码:
public class FeignBlockingLoadBalancerClient implements Client {
...
@Override
public Response execute(Request request, Request.Options options) throws IOException {
//获取请求URL
final URI originalUri = URI.create(request.url());
//获取微服务实例ID
String serviceId = originalUri.getHost();
Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);
//获取配置命中值
String hint = getHint(serviceId);
//获取请求上线文对象
DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(
new RequestDataContext(buildRequestData(request), hint));
//获取符合当前请求实例的生命周期管理对象
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
.getSupportedLifecycleProcessors(
loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
//调用生命 周期onStart回调方法
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
//获取请求实例对应的微服务实例对象
ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);
//请求响应对象
org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(
instance);
//如果请求实例不存在,则直接调用生命周期完成方法onComplete
if (instance == null) {
String message = "Load balancer does not contain an instance for the service " + serviceId;
if (LOG.isWarnEnabled()) {
LOG.warn(message);
}
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.DISCARD, lbRequest, lbResponse)));
return Response.builder().request(request).status(HttpStatus.SERVICE_UNAVAILABLE.value())
.body(message, StandardCharsets.UTF_8).build();
}
//获取实例请求的真实请求对象
String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();
//构建Request请求对象
Request newRequest = buildRequest(request, reconstructedUrl);
//执行真实请求
return executeWithLoadBalancerLifecycleProcessing(delegate, options, newRequest, lbRequest, lbResponse,
supportedLifecycleProcessors);
}
protected Request buildRequest(Request request, String reconstructedUrl) {
return Request.create(request.httpMethod(), reconstructedUrl, request.headers(), request.body(),
request.charset(), request.requestTemplate());
}
// Visible for Sleuth instrumentation
public Client getDelegate() {
return delegate;
}
// 获取配置命中值
private String getHint(String serviceId) {
String defaultHint = properties.getHint().getOrDefault("default", "default");
String hintPropertyValue = properties.getHint().get(serviceId);
return hintPropertyValue != null ? hintPropertyValue : defaultHint;
}
}
executeWithLoadBalancerLifecycleProcessing请求方法:
static Response executeWithLoadBalancerLifecycleProcessing(Client feignClient, Request.Options options,
Request feignRequest, org.springframework.cloud.client.loadbalancer.Request lbRequest,
org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse,
Set<LoadBalancerLifecycle> supportedLifecycleProcessors, boolean loadBalanced) throws IOException {
//在获取真实请求URL之后,在发送真实请求之前执行onStartRequest回调方法
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, lbResponse));
try {
//执行真实请求
Response response = feignClient.execute(feignRequest, options);
if (loadBalanced) {
//执行声明周期回调方法onComplete
supportedLifecycleProcessors.forEach(
lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
lbRequest, lbResponse, buildResponseData(response))));
}
return response;
}
catch (Exception exception) {
if (loadBalanced) {
//执行声明周期回调方法onComplete
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
new CompletionContext<>(CompletionContext.Status.FAILED, exception, lbRequest, lbResponse)));
}
throw exception;
}
}
如果开启spring.cloud.loadbalancer.retry.enabled=true重试能力,则执行的是RetryableFeignBlockingLoadBalancerClient,其执行流程跟上述一致,不在做详细分析;
边栏推荐
- Leetcode 560 prefix and + hash table
- Tree dynamic programming
- HCIP(11)
- [cloud enjoys freshness] community weekly · Vol 72 - the first opening ceremony of the 2022 Huawei developer competition in China was launched; Huawei cloud koomessage is in hot public beta
- UE4 framework introduction
- UE4 external open EXE file
- 2021 CEC written examination summary
- C class library generation, use class library objects to data bind DataGridView
- HCIA experiment (07) comprehensive experiment
- Learn NLP with Transformer (Chapter 7)
猜你喜欢

哥廷根大学提出CLIPSeg:一个使用文本和图像prompt能同时作三个分割任务的模型

BGP federal experiment

Learn NLP with Transformer (Chapter 7)

HCIP(13)

JS bidirectional linked list 02

微波技术基础实验一 滤波器的设计

【蓝桥杯集训100题】scratch太极图 蓝桥杯scratch比赛专项预测编程题 集训模拟练习题第22题
学习周刊 - 总第 63 期 - 一款开源的本地代码片段管理工具
![[flask advanced] deeply understand the application context and request context of flask from the source code](/img/67/88c21967da28d09694568ebdaae44c.png)
[flask advanced] deeply understand the application context and request context of flask from the source code

Hcip experiment (01)
随机推荐
The University of Gottingen proposed clipseg: a model that can perform three segmentation tasks simultaneously using text and image prompts
异步Servlet在转转图片服务的实践
微波技术大作业课设-分立电容电感+微带单枝短截线+微带双枝短截线
HCIP(12)
【信息系统项目管理师】思维导图系列精华汇总
Microwave technology homework course design - Discrete capacitance and inductance + microstrip single stub + microstrip double stub
UE4 framework introduction
Learn NLP with Transformer (Chapter 7)
【云享新鲜】社区周刊·Vol.72- 2022华为开发者大赛中国区首场开幕式启动;华为云KooMessage火热公测中…
Analysis of event channel principle in Kraken
信号完整性(SI)电源完整性(PI)学习笔记(三十四)100条估计信号完整性效应的经验法则
Openstack skyline component installation
What is MySQL transaction
Reinforcement learning (III)
2021 CEC written examination summary
Understand the life cycle and route jump of small programs
性能测试中TPS的计算【杭州多测师】【杭州多测师_王sir】
Learn NLP with Transformer (Chapter 6)
Nb-iot control LCD (date setting and reading)
[servlet] request parsing