当前位置:网站首页>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 .
边栏推荐
- Mirror protocol of synthetic asset track
- Cartoon rendering - average normal stroke
- [go practical basis] how to install and use gin
- Connect function and disconnect function of QT
- [go practical basis] how to set the route in gin
- C nail development: obtain all employee address books and send work notices
- Redis sorted set data type API and application scenario analysis
- Solution and analysis of Hanoi Tower problem
- Right click menu of QT
- Using recursive functions to solve the inverse problem of strings
猜你喜欢

Minecraft install resource pack

Solution of Xiaomi TV's inability to access computer shared files

《统计学习方法》——第五章、决策树模型与学习(上)

Matplotlib剑客行——布局指南与多图实现(更新)
![[staff] common symbols of staff (Hualian clef | treble clef | bass clef | rest | bar line)](/img/ae/1ecb352c51a101f237f244da5a2ef7.jpg)
[staff] common symbols of staff (Hualian clef | treble clef | bass clef | rest | bar line)

Installing Oracle database 19C RAC on Linux

知识点很细(代码有注释)数构(C语言)——第三章、栈和队列

How to realize asynchronous programming in a synchronous way?

Ora-12514 problem solving method

微服务实战|手把手教你开发负载均衡组件
随机推荐
概率还不会的快看过来《统计学习方法》——第四章、朴素贝叶斯法
What is the future value of fluorite mine of karaqin Xinbao Mining Co., Ltd. under zhongang mining?
京东面试官问:LEFT JOIN关联表中用ON还是WHERE跟条件有什么区别
Minecraft plug-in service opening
gocv opencv exit status 3221225785
commands out of sync. did you run multiple statements at once
【Go实战基础】gin 如何绑定与使用 url 参数
[go practical basis] how to set the route in gin
[staff] time mark and note duration (staff time mark | full note rest | half note rest | quarter note rest | eighth note rest | sixteenth note rest | thirty second note rest)
Multi version concurrency control mvcc of MySQL
西瓜书--第五章.神经网络
Qt的connect函数和disconnect函数
Matplotlib剑客行——布局指南与多图实现(更新)
cmd窗口中中文呈现乱码解决方法
C language - Blue Bridge Cup - 7 segment code
2022/2/14 summary
以字节跳动内部 Data Catalog 架构升级为例聊业务系统的性能优化
【Go实战基础】gin 如何设置路由
"Interview high frequency question" is 1.5/5 difficult, and the classic "prefix and + dichotomy" application question
C# 高德地图 根据经纬度获取地址