欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

RestTemplate 负载均衡原理

程序员文章站 2022-07-02 15:44:54
RestTemplate负载均衡原理 RestTemplate为什么具有负载均衡的功能? 在使用了@LoadBalanced后,Spring容器在启动的时候会为被修饰过的RestTemplate添加拦截器,拦截器里会使用LoadBalanced相关的负载均衡接口来处理请求,通过这样一个间接的处理,会 ......

resttemplate负载均衡原理

 

resttemplate为什么具有负载均衡的功能?

    在使用了@loadbalanced后,spring容器在启动的时候会为被修饰过的resttemplate添加拦截器,拦截器里会使用loadbalanced相关的负载均衡接口来处理请求,通过这样一个间接的处理,会使原来的resttemplate变得不是原来的resttemplate了,就变的更nb了,因此具备了负载均衡的功能。
那么在这章的内容中呢,笔者将带大家实现一个很简单的loadbalanced注解,为resttemplate添加拦截器的这么一个过程,至于如何在拦截器中实现负载均衡的功能,这个还需探索。。。(如果各位道友知道如何实现,请告知一二,先感谢了)

 

引入web依赖:pom.xml

<dependencies>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
        <version>2.0.3.release</version>
    </dependency>
</dependencies>

自定义注解:myloadbalanced.java

/**
 * 修饰:域、参数、方法
 */
@target({elementtype.field, elementtype.parameter, elementtype.method})
/**
 * 作用是定义被它所注解的注解保留多久,一共有三种策略,定义在retentionpolicy枚举中
 * 1. source:被编译器忽略
 * 2. class:注解将会被保留在class文件中,但在运行时并不会被vm保留。这是默认行为,所有没有用retention注解的注解,都会采用这种策略
 * 3. runtime:保留至运行时。所以我们可以通过反射去获取注解信息。
 */
@retention(retentionpolicy.runtime)
/**
 * 限定注解
 */
@qualifier
public @interface myloadbalanced {

}

创建controller:mycontroller.java

@restcontroller
@configuration public class mycontroller { @bean // 将getresttemplate修饰为bean,交给spring管理 @myloadbalanced // 这里使用刚刚自定义的注解 public resttemplate getresttemplate(){ return new resttemplate(); } }

创建配置类:config.java

@configuration
public class config {
    
    @autowired(required = false)// 非必须的,将那些被@myloadbalanced注解修饰过的对象,自动装配到tpls集合中
    @myloadbalanced
    private list<resttemplate> tpls = collections.emptylist();
    
    // 在spring容器启动之后,需要对每一个resttemplate都要设置一个拦截器,拦截器里面会实现负载均衡的功能
    @bean
    public smartinitializingsingleton lbinitializing(){
        return new smartinitializingsingleton() {
            @override
            public void aftersingletonsinstantiated() {
                system.out.println("resttemplate集合大小:"+tpls.size());
            }
        };
    }

}

下面我们创建一个启动类,看一看到底有没有自动装配成功:application.java

@springbootapplication
public class application {
    
    public static void main(string[] args) {
        springapplication.run(application.class, args);
    }
    
}

RestTemplate 负载均衡原理

如图,resttemplate集合大小:1  说明,我们的配置生效了。。。。。。 

 

下面我们创建一个自定义的拦截器:myinterceptor.java  该拦截器需要实现 clienthttprequestinterceptor 接口

public class myinterceptor implements clienthttprequestinterceptor {

    @override
    public clienthttpresponse intercept(httprequest request, byte[] body, clienthttprequestexecution execution) throws ioexception {
        system.out.println("==================== 进入自定义拦截器");
        return null;
    }

}

现在自定义拦截器有了,那么我们就去修改一下配置类,让程序启动后,循环向每个被@myloadbalanced修饰过的resttemplate添加拦截器,修改 config.java 如下:

@bean
public smartinitializingsingleton lbinitializing(){
    return new smartinitializingsingleton() {
        @override
        public void aftersingletonsinstantiated() {
            for(resttemplate rtl : tpls){
                // 为了防止覆盖默认拦截器,将默认拦截器取出
                list<clienthttprequestinterceptor> interceptors = rtl.getinterceptors();
                // 将自定义的拦截器加入到默认拦截器中
                interceptors.add(new myinterceptor());
                // 给resttemplate设置拦截器
                rtl.setinterceptors(interceptors);
            }
        }
    };
}

 拦截器是用来拦截请求的,我们还需要在 mycontroller.java 中定义一个接口,用于调用测试,修改 mycontroller.java 如下:

@requestmapping(value="/getpolice", method=requestmethod.get, produces=mediatype.application_json_value)
public string getpolice(){
    resttemplate rtl = getresttemplate();
    string result = rtl.getforobject("http://springcloud-ribbon-police/getpolice", string.class);
    return result;
}

 下面,我们访问下接口,试试拦截器有没有配置成功,如图:

RestTemplate 负载均衡原理

拦截器中输出了内容,那么就证明拦截器配置成功了。报错是因为在拦截器中返回了null,那我们现在就来解决这个问题。

 

在拦截器中暂时不实现负载均衡的功能,我们以跳转为例,给大家讲解。。。将旧请求进行修改,并返回一个新的请求。这样的话,就需要我们返回一个新的request对象。

创建 newrequest.java 并实现 httprequest 接口:newrequest.java

public class newrequest implements httprequest{
    
    private httprequest sourcerequest;// 原请求request

    public newrequest(httprequest sourcerequest){
        this.sourcerequest = sourcerequest;
    }
    
    @override
    public httpheaders getheaders() {
        return sourcerequest.getheaders();
    }

    @override
    public string getmethodvalue() {
        return sourcerequest.getmethodvalue();
    }

    @override
    public uri geturi() {
        try {
            // 将拦截到的uri,修改为新的uri
            uri uri = new uri("http://localhost:9090/getpolicebyid/123");
            return uri;
        } catch (exception e) {
            e.printstacktrace();
        }
        return sourcerequest.geturi();
    }

}

 下面修改一下我们自定义的拦截器:myinterceptor.java

public class myinterceptor implements clienthttprequestinterceptor {

    @override
    public clienthttpresponse intercept(httprequest request, byte[] body, clienthttprequestexecution execution) throws ioexception {
        system.out.println("==================== 这是自定义拦截器");
        system.out.println("==================== 旧的url:"+request.geturi());
        newrequest newrequest = new newrequest(request);
        system.out.println("==================== 新的url:"+newrequest.geturi());
        return execution.execute(newrequest, body);
    }

}

 我们再运行程序,得到如下结果:

RestTemplate 负载均衡原理

再看一下页面返回的结果,完美实现拦截跳转:

RestTemplate 负载均衡原理

 

 

 ok,,,以上就是本章的全部内容了,一个简单的自定义注解、自定义拦截器,你 学会了吗!