当前位置:网站首页>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 boundary fill
- Taking the upgrade of ByteDance internal data catalog architecture as an example, talk about the performance optimization of business system
- [staff] common symbols of staff (Hualian clef | treble clef | bass clef | rest | bar line)
- C# 高德地图 根据经纬度获取地址
- 寻找链表中值域最小的节点并移到链表的最前面
- Introduction to the basic concept of queue and typical application examples
- Move a string of numbers backward in sequence
- 《统计学习方法》——第五章、决策树模型与学习(上)
- Right click menu of QT
- Openshift container platform community okd 4.10.0 deployment
猜你喜欢

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

以字节跳动内部 Data Catalog 架构升级为例聊业务系统的性能优化

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

微服务实战|手把手教你开发负载均衡组件

I've taken it. MySQL table 500W rows, but someone doesn't partition it?

win10使用docker拉取redis镜像报错read-only file system: unknown

数构(C语言)——第四章、矩阵的压缩存储(下)

【Go实战基础】gin 高效神器,如何将参数绑定到结构体

Qt——如何在QWidget中设置阴影效果

Cloudreve自建云盘实践,我说了没人能限制得了我的容量和速度
随机推荐
C#钉钉开发:取得所有员工通讯录和发送工作通知
Qt QTimer类
C4D quick start tutorial - Chamfer
The channel cannot be viewed when the queue manager is running
win10使用docker拉取redis镜像报错read-only file system: unknown
Webflux responsive programming
Finishing the interview essentials of secsha system!!!
Oracle delete tablespace and user
Use of libusb
【Go实战基础】gin 如何自定义和使用一个中间件
[staff] time sign and note duration (full note | half note | quarter note | eighth note | sixteenth note | thirty second note)
C nail development: obtain all employee address books and send work notices
"Interview high frequency question" is 1.5/5 difficult, and the classic "prefix and + dichotomy" application question
将一串数字顺序后移
图像变换,转置
Solution of Xiaomi TV's inability to access computer shared files
Select sort and insert sort
Analysis and solution of a classical Joseph problem
西瓜书--第六章.支持向量机(SVM)
队列管理器running状态下无法查看通道