当前位置:网站首页>Microservice practice | teach you to develop load balancing components hand in hand
Microservice practice | teach you to develop load balancing components hand in hand
2022-07-02 09:10:00 【_ Time boiled the rain】
Last one Micro service practice | The original ecosystem realizes the discovery and invocation of services
Preface
In the last article, we realized the discovery and invocation of services in an original way , But in a clustered environment , The purpose of load balancing is not achieved , This article , We will write our own load balancer , To realize the load balancing function of service invocation .
Custom load balancing
review
First , Let's first review the code in the last article :
@GetMapping("/hello")
public String hello(String name) {
List<ServiceInstance> list = discoveryClient.getInstances("provider");
ServiceInstance instance = list.get(0);
String host = instance.getHost();
int port = instance.getPort();
String returnInfo = restTemplate.getForObject("http://" + host + ":" + port + "/hello?name={1}", String.class, name);
return returnInfo;
}
Let's go through discoveryClient Got one of the services of the registry ip And port , And then use restTemplate Call its getForObjec() Method to call the interface .
By tracing the source code of this method , We find that it will eventually be called doExecute() Method , Source code is as follows :
@Nullable
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "URI is required");
Assert.notNull(method, "HttpMethod is required");
ClientHttpResponse response = null;
Object var14;
try {
ClientHttpRequest request = this.createRequest(url, method);
if (requestCallback != null) {
requestCallback.doWithRequest(request);
}
response = request.execute();
this.handleResponse(url, method, response);
var14 = responseExtractor != null ? responseExtractor.extractData(response) : null;
} catch (IOException var12) {
String resource = url.toString();
String query = url.getRawQuery();
resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource;
throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12);
} finally {
if (response != null) {
response.close();
}
}
return var14;
}
Then can we inherit RestTemplate class , And rewrite doExecute Method , stay doExecute Call in method createRequest Change it before ?
Load balancing
First create our own RestTemplate, Name it MyRestTemplate.java, Examples are as follows :
/** * Custom load balancer * @Author: official account : The programmer 965 * @create 2022-06-06 **/
public class MyRestTemplate extends RestTemplate {
private DiscoveryClient discoveryClient;
public MyRestTemplate (DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
/** * Interface call * @Author: official account : The programmer 965 * @create 2022-06-06 **/
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback,
@Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "URI is required");
Assert.notNull(method, "HttpMethod is required");
ClientHttpResponse response = null;
try {
System.out.println(" Before replacement url :"+url.toString());
url = replaceUrl(url);
System.out.println(" After replacement url :"+url.toString());
ClientHttpRequest request = createRequest(url, method);
if (requestCallback != null) {
requestCallback.doWithRequest(request);
}
response = request.execute();
handleResponse(url, method, response);
return (responseExtractor != null ? responseExtractor.extractData(response) : null);
}
catch (IOException ex) {
String resource = url.toString();
String query = url.getRawQuery();
resource = (query != null ? resource.substring(0,resource.indexOf('?')) : resource);
throw new ResourceAccessException("I/O error on " + method.name() +
" request for \"" + resource + "\": " + ex.getMessage(), ex);
} finally {
if (response != null) {
response.close();
}
}
}
/** * Replace url * @Author: official account : The programmer 965 * @create 2022-06-06 **/
private URI replaceUrl(URI url){
String sourceUrl = url.toString();
String [] httpUrl = sourceUrl.split("//");
int index = httpUrl[1].replaceFirst("/","@").indexOf("@");
String serviceName = httpUrl[1].substring(0,index);
List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances(serviceName);
// Adopt random algorithm , Get one of the service information
Random random = new Random();
Integer randomIndex = random.nextInt(serviceInstanceList.size());
String serviceIp = serviceInstanceList.get(randomIndex).getUri().toString();
String targetSource = httpUrl[1].replace(serviceName,serviceIp);
try {
return new URI(targetSource);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return url;
}
}
stay doExecute In the method , call createRequest Before method , We added a line replaceUrl() Method call , In this method , We analyze Url, Get the service name , Then still get the service information list according to the service name , And through random algorithm , Return the... Of one of the services in the service information list uri And back to , Realize the load balancing of random algorithm .
Interface call
Come back to , Let's modify the call point of the interface , First restTemplate Instead, create our customized MyRestTemplate:
@Bean
RestTemplate restTemplate(DiscoveryClient discoveryClient) {
return new MyRestTemplate(discoveryClient);
}
Then modify the interface , Change the interface address directly to call with the service name :
@GetMapping("/hello2")
public String hello2(String name) {
String returnInfo = restTemplate.getForObject( "http://provider/hello?name={1}", String.class, name);
return returnInfo;
}
Start debugging

The successful running , Our results are returned correctly !
Now , There may be questions : Get one at random directly at the interface call ip Just call the port ? Why bother to pick up the source code and then inherit RestTemplate Class and override its doExecute Methods? ? Isn't that a bit of a fuss ?
friends ? think about it , Why do that ? This problem will be left to us when we use the load balancing component .
summary
In this paper , We use random algorithm to realize the function of load balancing , Of course, you can also implement polling as needed , Various load algorithms such as weight . Have you learned ?
边栏推荐
猜你喜欢

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

【Go实战基础】gin 如何验证请求参数

oracle修改数据库字符集

Hengyuan cloud_ Can aiphacode replace programmers?

Redis zadd导致的一次线上问题排查和处理
![[go practical basis] how can gin get the request parameters of get and post](/img/fd/66074d157d93bcf20a5d3b37da9b3e.png)
[go practical basis] how can gin get the request parameters of get and post

"Redis source code series" learning and thinking about source code reading

将一串数字顺序后移

Minecraft air Island service

WSL installation, beautification, network agent and remote development
随机推荐
There is a problem with MySQL installation (the service already exists)
十年開發經驗的程序員告訴你,你還缺少哪些核心競爭力?
Gocv split color channel
The channel cannot be viewed when the queue manager is running
寻找链表中值域最小的节点并移到链表的最前面
C call system sound beep~
Data type case of machine learning -- using data to distinguish men and women based on Naive Bayesian method
将一串数字顺序后移
一篇详解带你再次重现《统计学习方法》——第二章、感知机模型
C # save web pages as pictures (using WebBrowser)
「Redis源码系列」关于源码阅读的学习与思考
Sentinel reports failed to fetch metric connection timeout and connection rejection
I've taken it. MySQL table 500W rows, but someone doesn't partition it?
Analysis and solution of a classical Joseph problem
双非本科生进大厂,而我还在底层默默地爬树(上)
Essay: RGB image color separation (with code)
Shengshihaotong and Guoao (Shenzhen) new energy Co., Ltd. build the charging pile industry chain
【Go实战基础】如何安装和使用 gin
聊聊消息队列高性能的秘密——零拷贝技术
Matplotlib剑客行——没有工具用代码也能画图的造型师