当前位置:网站首页>Microservice practice | load balancing component and source code analysis
Microservice practice | load balancing component and source code analysis
2022-07-02 09:10:00 【_ Time boiled the rain】
Last one Micro service practice | Teach you how to develop load balancing components
List of articles
Preface
In the last article, we developed a load balancing component by ourselves , Realize the load balancing function of random algorithm , If you want to implement other algorithms , You also need to modify the code to add corresponding functions . This article , We will introduce a simpler implementation of load balancing , Use **@LoadBalanced** Annotation realizes the function of load balancing .
Project practice
Create project
alike , Our project still has one registry Registry Center , One provider Service providers , Next , Let's revise it again consumer Service consumer code :
/** * @Author: official account : The programmer 965 * @create 2022-06-06 **/
@EnableEurekaClient
@SpringBootApplication
@RestController
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
@Autowired
DiscoveryClient discoveryClient;
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello2")
public String hello2(String name) {
String returnInfo = restTemplate.getForObject( "http://provider/hello?name={1}", String.class, name);
return returnInfo;
}
}
In this version , alike , Or create RestTemplate Bean object , The difference is that the above only increases @LoadBalanced annotation .
Start project validation

It still returns the result correctly !
It's amazing , It's much simpler than the load balancing component we developed ourselves , Only in the restTemplate() A method is added above @LoadBalanced annotation , How can it be achieved ? Nonsense , To find out , Pick up the source code !
Source code analysis
First , Click on @LoadBalanced Comment in , Nothing special , So we are thinking ,Spring Creating Bean At instance time , Where does annotation work ? what ? I do not know! ? Turn to this article :
Liver for two weeks , A picture unlocks Spring Core source code
By reviewing Spring Start up and Bean Life cycle creation process , We will find that add @LoadBalancer After the note , When the project starts, it will load LoadBalancerAutoConfiguration This configuration class ( adopt spring-cloud-commons Under the bag spring.factories). Check the source code of this configuration class , It is found that it has a static inner class LoadBalancerInterceptorConfig, A load balancing interceptor is created inside :LoadBalancerInterceptor, The interceptor contains a loadBalancerClient Parameters :
@ConditionalOnMissingClass({
"org.springframework.retry.support.RetryTemplate"})
static class LoadBalancerInterceptorConfig {
LoadBalancerInterceptorConfig() {
}
@Bean
public LoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
}
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
return (restTemplate) -> {
List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
}
Let's continue to click LoadBalancerInterceptor Class entry , Find out intercept Method , The method is called LoadBalancerClient Of execute Method ,
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}
LoadBalancerClient It's an interface , Click in and we find that its implementation class is RibbonLoadBalancerClient, View its inheritance relationship :
Through the method name in the interface , We can guess ,choose The method is to select one of the services in the list ,reconstructURI The method is to reconstruct the request URI.
Choose services
choose The method is in RibbonLoadBalancerClient Implement
public ServiceInstance choose(String serviceId, Object hint) {
Server server = this.getServer(this.getLoadBalancer(serviceId), hint);
return server == null ? null : new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
}
In this method , First call getServer Method get service , This method will eventually call ILoadBalancer Interface chooseServer Method , and ILoadBalancer The implementation class of the interface defaults to ZoneAwareLoadBalancer.
ZoneAwareLoadBalancer Inherited from DynamicServerListLoadBalancer , And in the DynamicServerListLoadBalancer In the construction method of , Called this.restOfInit(clientConfig); stay restOfInit In this method , adopt this.updateListOfServers() To get the list of services ;
And in the chooseServer () In the method , According to the load balancing algorithm , Select one of the services and return :
BaseLoadBalancer zoneLoadBalancer = this.getLoadBalancer(zone);
server = zoneLoadBalancer.chooseServer(key);
Address replacement
Select one of the service information , How to change the interface from http://provider/hello Turn into http://localhost:8003/hello Well ? Remember what we said above reconstructURI Methods? ? By configuring the class LoadBalancerAutoConfiguration After loading , It will inject LoadBalancerInterceptor Interceptor , The interceptor will intercept our request , And process the request address , The specific implementation of the refactoring method is LoadBalancerContext Class reconstructURIWithServer In the method
public URI reconstructURIWithServer(Server server, URI original) {
String host = server.getHost();
int port = server.getPort();
String scheme = server.getScheme();
if (host.equals(original.getHost()) && port == original.getPort() && scheme == original.getScheme()) {
return original;
} else {
if (scheme == null) {
scheme = original.getScheme();
}
if (scheme == null) {
scheme = (String)this.deriveSchemeAndPortFromPartialUri(original).first();
}
try {
StringBuilder sb = new StringBuilder();
sb.append(scheme).append("://");
if (!Strings.isNullOrEmpty(original.getRawUserInfo())) {
sb.append(original.getRawUserInfo()).append("@");
}
sb.append(host);
if (port >= 0) {
sb.append(":").append(port);
}
sb.append(original.getRawPath());
if (!Strings.isNullOrEmpty(original.getRawQuery())) {
sb.append("?").append(original.getRawQuery());
}
if (!Strings.isNullOrEmpty(original.getRawFragment())) {
sb.append("#").append(original.getRawFragment());
}
URI newURI = new URI(sb.toString());
return newURI;
} catch (URISyntaxException var8) {
throw new RuntimeException(var8);
}
}
}
You can see that in this method , Send the original request address original, Replaced by the selected service IP And port . And finally call the interface method of the service .
See here , Think about the content of our last chapter , Is it the same as the same ?
summary
By adding @LoadBalanced annotation , It simply realizes the function of load balancing , Is not so much Ribbon A powerful , than Spring A powerful ,Spring Throughout the context creation process , Open one interface after another at different times , This provides traversal for the inheritance of various components , At the same time, it also further promotes Spring The rapid development of Ecology .
边栏推荐
- gocv图片读取并展示
- 京东面试官问:LEFT JOIN关联表中用ON还是WHERE跟条件有什么区别
- [go practical basis] how to bind and use URL parameters in gin
- [staff] common symbols of staff (Hualian clef | treble clef | bass clef | rest | bar line)
- Kubernetes deploys Loki logging system
- Qt的connect函数和disconnect函数
- C#钉钉开发:取得所有员工通讯录和发送工作通知
- 【Go实战基础】gin 如何验证请求参数
- oracle删除表空间及用户
- 数构(C语言)——第四章、矩阵的压缩存储(下)
猜你喜欢

Cloudreve自建云盘实践,我说了没人能限制得了我的容量和速度

Don't spend money, spend an hour to build your own blog website

Matplotlib swordsman Tour - an artist tutorial to accommodate all rivers

Function ‘ngram‘ is not defined

队列管理器running状态下无法查看通道

commands out of sync. did you run multiple statements at once

Matplotlib剑客行——容纳百川的艺术家教程

Shengshihaotong and Guoao (Shenzhen) new energy Co., Ltd. build the charging pile industry chain

QT -- how to set shadow effect in QWidget

Jd.com interviewer asked: what is the difference between using on or where in the left join association table and conditions
随机推荐
Move a string of numbers backward in sequence
分布式服务架构精讲pdf文档:原理+设计+实战,(收藏再看)
Solution and analysis of Hanoi Tower problem
C nail development: obtain all employee address books and send work notices
[go practical basis] how to bind and use URL parameters in gin
QT -- how to set shadow effect in QWidget
微服务实战|手把手教你开发负载均衡组件
Jingdong senior engineer has developed for ten years and compiled "core technology of 100 million traffic website architecture"
图像变换,转置
Minecraft air Island service
「Redis源码系列」关于源码阅读的学习与思考
Troubleshooting and handling of an online problem caused by redis zadd
commands out of sync. did you run multiple statements at once
长篇总结(代码有注释)数构(C语言)——第四章、串(上)
C # save web pages as pictures (using WebBrowser)
使用IBM MQ远程连接时报错AMQ 4043解决思路
一、Qt的核心类QObject
Count the number of various characters in the string
Cloudreve自建云盘实践,我说了没人能限制得了我的容量和速度
Analysis and solution of a classical Joseph problem