当前位置:网站首页>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 ?
边栏推荐
- Solution of Xiaomi TV's inability to access computer shared files
- Mysql安装时mysqld.exe报`应用程序无法正常启动(0xc000007b)`
- cmd窗口中中文呈现乱码解决方法
- Mirror protocol of synthetic asset track
- 【Go实战基础】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)
- [staff] common symbols of staff (Hualian clef | treble clef | bass clef | rest | bar line)
- C Baidu map, Gaode map, Google map (GPS) longitude and latitude conversion
- C# 调用系统声音 嘀~
- Installing Oracle database 19C RAC on Linux
猜你喜欢

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

Finishing the interview essentials of secsha system!!!

Installing Oracle database 19C RAC on Linux

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

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

Cloud computing in my eyes - PAAS (platform as a service)

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

Minecraft install resource pack

Flink-使用流批一体API统计单词数量
![[go practical basis] how to verify request parameters in gin](/img/de/50db131d6993e5d955e3416c667c4c.png)
[go practical basis] how to verify request parameters in gin
随机推荐
Select sort and insert sort
Move a string of numbers backward in sequence
Qt的connect函数和disconnect函数
I've taken it. MySQL table 500W rows, but someone doesn't partition it?
Leetcode sword finger offer brush questions - day 22
2022/2/14 summary
C call system sound beep~
十年开发经验的程序员告诉你,你还缺少哪些核心竞争力?
Kubernetes deploys Loki logging system
【Go实战基础】gin 如何绑定与使用 url 参数
双非本科生进大厂,而我还在底层默默地爬树(上)
十年開發經驗的程序員告訴你,你還缺少哪些核心競爭力?
【Go实战基础】gin 如何自定义和使用一个中间件
【Go实战基础】gin 如何设置路由
Qt QTimer类
Gocv image reading and display
Tensorflow2 keras classification model
WSL installation, beautification, network agent and remote development
Qt的右键菜单
Redis zadd导致的一次线上问题排查和处理