当前位置:网站首页>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
边栏推荐
猜你喜欢

Nowcodertop1-6 - continuous updating

Learn NLP with Transformer (Chapter 6)

Esp8266 uses drv8833 drive board to drive N20 motor

Learn NLP with Transformer (Chapter 5)

NowCoderTOP12-16——持续更新ing

NB-IOT控制液晶屏(日期的设置与读取)

Flask framework - session and cookies
Learn NLP with Transformer (Chapter 2)

Learn NLP with Transformer (Chapter 5)

HCIP(12)
随机推荐
[flask advanced] solve the classic error reporting of flask by combining the source code: working outside of application context
【IJCAI 2022】参数高效的大模型稀疏训练方法,大幅减少稀疏训练所需资源
倍增Floyd「建议收藏」
Learn NLP with Transformer (Chapter 7)
Esp32c3 based on the example tutorial of esp32 Rainmaker development under Arduino framework
MySQL advanced statement (I) (there is always someone who will make your life no longer bad)
redis 哨兵,高可用的执行者
HCIP(12)
Learn NLP with Transformer (Chapter 1)
C# Newtonsoft. Jason advanced usage
一文读懂小程序的生命周期和路由跳转
Last week's hot review (7.18-7.24)
Code representation learning: introduction to codebert and other related models
二合一的集度,任重道远
从开源的视角,解析SAP经典ERP “三十年不用变”的架构设计
syncronized锁升级的过程
Shell 脚本参数传递时有 \r 换行符问题
HCIA experiment (09)
大佬们,flink cdc table api , mysql to mysql,一个应用程序,可以
SQL语言(二)