当前位置:网站首页>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 ?
边栏推荐
猜你喜欢
随机推荐
Openshift container platform community okd 4.10.0 deployment
Redis sorted set data type API and application scenario analysis
以字节跳动内部 Data Catalog 架构升级为例聊业务系统的性能优化
【Go实战基础】gin 如何绑定与使用 url 参数
[go practical basis] how to install and use gin
Count the number of various characters in the string
一、Qt的核心类QObject
"Redis source code series" learning and thinking about source code reading
C# 将网页保存为图片(利用WebBrowser)
Servlet全解:继承关系、生命周期、容器和请求转发与重定向等
数构(C语言--代码有注释)——第二章、线性表(更新版)
C # save web pages as pictures (using WebBrowser)
Programmers with ten years of development experience tell you, what core competitiveness do you lack?
Connect function and disconnect function of QT
Avoid breaking changes caused by modifying constructor input parameters
【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)
聊聊消息队列高性能的秘密——零拷贝技术
[go practical basis] how to customize and use a middleware in gin
C# 百度地图,高德地图,Google地图(GPS) 经纬度转换