当前位置:网站首页>Loadbalancerlife lifecycle requested by feign client
Loadbalancerlife lifecycle requested by feign client
2022-07-25 11:20:00 【Emily】
LoadBalancerLifecycle Interfaces are allowed in load-balancing What should be done before and after execution , We can use this entry to get the real request of the microservice request URL;
One 、LoadBalancerLifecycle Interface source code
public interface LoadBalancerLifecycle<RC, RES, T> {
/** * Determine whether the service instance object allows method callbacks */
default boolean supports(Class requestContextClass, Class responseClass, Class serverTypeClass) {
return true;
}
/** * In execution load-balancing Before ( That is, get real service instances url Before ) The callback method */
void onStart(Request<RC> request);
/** * After selecting a real service instance , Callback method before executing the request */
void onStartRequest(Request<RC> request, Response<T> lbResponse);
/** * stay load-balancing Load balancing is performed after the real service request */
void onComplete(CompletionContext<RES, T, RC> completionContext);
}
Two 、 be based on loadbalance There are two requests for service FeignBlockingLoadBalancerClient( Retry is not supported )、RetryableFeignBlockingLoadBalancerClient( Support retry )
Let's take a look first FeignBlockingLoadBalancerClient Source code :
public class FeignBlockingLoadBalancerClient implements Client {
...
@Override
public Response execute(Request request, Request.Options options) throws IOException {
// Get request URL
final URI originalUri = URI.create(request.url());
// Get micro service instance ID
String serviceId = originalUri.getHost();
Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);
// Get the configuration hit value
String hint = getHint(serviceId);
// Get the request online document object
DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(
new RequestDataContext(buildRequestData(request), hint));
// Get the lifecycle management object that meets the current request instance
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
.getSupportedLifecycleProcessors(
loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
// Call life cycle onStart The callback method
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
// Get the microservice instance object corresponding to the request instance
ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);
// Request response object
org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(
instance);
// If the request instance does not exist , Then directly call the lifecycle completion method 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();
}
// Get the real request object of the instance request
String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();
// structure Request Request object
Request newRequest = buildRequest(request, reconstructedUrl);
// Execute the real request
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;
}
// Get the configuration hit value
private String getHint(String serviceId) {
String defaultHint = properties.getHint().getOrDefault("default", "default");
String hintPropertyValue = properties.getHint().get(serviceId);
return hintPropertyValue != null ? hintPropertyValue : defaultHint;
}
}
executeWithLoadBalancerLifecycleProcessing Request method :
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 {
// Getting the real request URL after , Execute before sending the real request onStartRequest The callback method
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, lbResponse));
try {
// Execute the real request
Response response = feignClient.execute(feignRequest, options);
if (loadBalanced) {
// Execute the declaration cycle callback method onComplete
supportedLifecycleProcessors.forEach(
lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
lbRequest, lbResponse, buildResponseData(response))));
}
return response;
}
catch (Exception exception) {
if (loadBalanced) {
// Execute the declaration cycle callback method onComplete
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
new CompletionContext<>(CompletionContext.Status.FAILED, exception, lbRequest, lbResponse)));
}
throw exception;
}
}
If open spring.cloud.loadbalancer.retry.enabled=true Retry capability , Then it is executed RetryableFeignBlockingLoadBalancerClient, Its implementation process is consistent with the above , No more detailed analysis ;
GitHub Address :https://github.com/mingyang66/spring-parent
边栏推荐
猜你喜欢

Code representation learning: introduction to codebert and other related models

Learn NLP with Transformer (Chapter 7)

Shell 脚本参数传递时有 \r 换行符问题

AI system frontier dynamics issue 43: ONEFLOW V0.8.0 officially released; GPU finds human brain connections; AI doctoral online crowdfunding research topic

只知道预制体是用来生成物体的?看我如何使用Unity生成UI预制体

Nowcodertop12-16 - continuous updating
学习周刊 - 总第 63 期 - 一款开源的本地代码片段管理工具

复习背诵整理版
![[flask advanced] combined with the source code, explain the operation mechanism of flask (in and out of the stack)](/img/a0/9110b83ff5c7965809bbc9f3948956.jpg)
[flask advanced] combined with the source code, explain the operation mechanism of flask (in and out of the stack)

Hcip experiment (04)
随机推荐
从开源的视角,解析SAP经典ERP “三十年不用变”的架构设计
学习路之PHP--TP5.0使用中文当别名,报“不支持的数据表达式”
MLX90640 红外热成像仪测温模块开发笔记(五)
Hcip experiment (04)
ArcMap无法启动解决方法
API supplement of JDBC
Redis 入门
SQL语言(六)
[递归] 938. 二叉搜索树的范围和
Ue4.26 source code version black screen problem of client operation when learning Wan independent server
shell- 第七章练习
How to notify users of wechat applet version update?
SQL语言(四)
Reinforcement Learning 强化学习(四)
100W了!
Flask framework - Message flash
web移动端:touchmove实现局部滚动
倍增Floyd「建议收藏」
Google Earth engine -- Statistics on the frequency of land classification year by year
Learn NLP with Transformer (Chapter 7)