restTemplate loadbalance 负载均衡使用demo 案例 原理以及全网最细源码解析

本文详细介绍了Spring Cloud中如何利用@LoadBalanced注解的RestTemplate实现服务间的负载均衡调用。通过注册带有@LoadBalanced的RestTemplate Bean,结合Nacos服务发现,实现了工作流回调的负载均衡。文章通过代码示例和源码分析,展示了RestTemplate执行exchange的整个流程,包括从服务名到IP:port的转换,以及RetryLoadBalancerInterceptor在请求过程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

restTemplate 是spring 提供的http请求工具,类似于httpclient,
默认情况下与其他的http 工具类没有区别
但是当添加了@Loadbalance 注解之后,则具备了负载均衡功能,可以通过服务名找到对应的ip:port进行访问
闲话少说,我们直接上demo

注册templete loadbalance bean

如果引入了spring cloud 默认会注册 loadbalance resttemplate 

@Bean
	@LoadBalanced
	public RestTemplate restTemplate(){
		return new RestTemplate();
	}

使用方式 post 使用demo案例

我这里是用的spring cloud nacos ,针对工作流回调函数传入服务名进行负载均衡调用

@Autowired
    private  RestTemplate restTemplate;

    /***
     * 
     * @param serverName 服务名
     * @param event 回调事件
     * @param vars 回调参数j'son
     * @return R<String> 返回结果
     * 
     */
    @Override
    public R<String> call(String serverName,String event, String vars) {
        log.info("serverName:{},event:{},vars:{}",serverName,event,vars);
        String url = "http://"+serverName+"/workflow/callback/event";

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(SecurityConstants.FROM, SecurityConstants.FROM_IN);
        HttpEntity<Void> httpEntity = new HttpEntity<>(null, httpHeaders);

        MultiValueMap<String, String> requestMap = new LinkedMultiValueMap<>();
        requestMap.add("event", event);
        requestMap.add("dataMapString", vars);
        ResponseEntity<R> r =  restTemplate.exchange(url, HttpMethod.POST,httpEntity,R.class,requestMap);
        return R.ok();
    }

接收端

/**
     * 工作流回调接口
     *
     * @param event         事件名称
     * @param dataMapString 传递参数
     *                      dataMapString 参数如下:
     *                      flag :审批结果 "审批,驳回,终止"
     *                      username: 该流程提交者用户名
     *                      busi_id: startSubmit 返回的流程业务id,与业务挂钩的主键
     *                      nodeId: 节点Id
     *                      assignee: 分配的审批人
     *                      auditer: 真正完成审批人
     *                      comment: 审批意见
     */
    @Inner
    @RequestMapping("/event")
    @ApiOperation(value = "工作流各种回调事件接口", tags = "工作流各种回调事件接口")
    public R callBack(String event,String dataMapString) {
        System.out.println("event:" + event + ",dataMapString:" + dataMapString);
        //流程相关参数
        Map<String, String> params = JSON.parseObject(dataMapString, new TypeReference<Map<String, String>>() {
        });
        //流程节点分到了具体审批人后回调事件
        if (WorkflowCallBackEvent.EVENT_ASSIGNEE.equals(event)) {
            return R.ok();
        }else{
            return R.failed();
        }
     }

redistemplete 执行loadbanlace 运行流程与源码分析

为了大家方便理解,我画了一个简单的运行泳道图,主要分为两个部分,第一是启动部分,如下图:

 

启动部分源码分析

 整体流程描述

1. 通过LoadBalancerAutoConfiguration 加载所有带有@LoadBalanced 注解的restTemplate
2. 初始化 执行 loadBalancedRestTemplateInitializerDeprecated 方法内部遍历执行 customizer.customize(restTemplate)
3. customizer.customize(restTemplate) 其实就是执行 之前注入的bean RestTemplateCustomizer,然后执行restTemplate.setInterceptors(list)


初始化完毕

详细步骤源码分析

1. 通过LoadBalancerAutoConfiguration 加载所有带有@LoadBalanced 注解的restTemplate
重点,为什么是加载了有@LoadBalanced 注解的restTemplate 而不是所有的restTemplate ,因为@LoadBalanced 内有一个@Qualifier 元注解
因此有@LoadBalanced 注解的restTemplate 就绑成了一个整体注入到了spring 中管理

 2. 初始化 执行 loadBalancedRestTemplateInitializerDeprecated 方法内部遍历执行 customizer.customize(restTemplate)

 

 3. customizer.customize(restTemplate) 其实就是执行 之前注入的bean RestTemplateCustomizer,然后执行restTemplate.setInterceptors(list);

 setInterceptors(list) 其实就是注入了RetryLoadBalancerInterceptor ,现在完成后也就是将含有loadbalance 注解的resttemplate 注入了interceptor 

redistemplete 执行exchange 负载均衡源码分析(参照上面流程图)

整体流程描述 

1. redistemplete 执行 exchange,然后内部 exchange->execute->doExecute
2. 然后 createRequest 然后通过 getRequestFactory 创建request 
3. getRequestFactory 会根据是否内部注册了拦截器来返回不同的factory, 有拦截会返回InterceptingClientHttpRequestFactory ,没有会返回SimpleClientHttpRequestFactory
4. InterceptingClientHttpRequestFactory 会创建返回InterceptingClientHttpRequest,SimpleClientHttpRequestFactory 会创建返回SimpleBufferingAsyncClientHttpRequest
5. SimpleBufferingAsyncClientHttpRequest 会正常和httpclient 一样执行execute,暂不多说,主要来说InterceptingClientHttpRequest ,这个是负责负载均衡的
6. InterceptingClientHttpRequest 执行execute ,内部会先执行拦截器也就是之前启动注入的RetryLoadBalancerInterceptor
7. RetryLoadBalancerInterceptor 内部会执行 RibbonLoadBalancerClient 的choose 方法用NamedContextFactory 将服务名从注册中心获取实例转为ip:port 的ServiceInstance
8. 然后 RetryLoadBalancerInterceptor 会拿着得到的ServiceInstance 正常执行http请求得到 ClientHttpResponse 
9. 返回response 全部流程结束

详细步骤源码分析 

1. redistemplete 执行 exchange,然后内部 exchange->execute->doExecute

2. 然后 createRequest 然后通过 getRequestFactory 创建request

 

 3. getRequestFactory 会根据是否内部注册了拦截器来返回不同的factory, 有拦截会返回InterceptingClientHttpRequestFactory ,没有会返回SimpleClientHttpRequestFactory

4. InterceptingClientHttpRequestFactory 会创建返回InterceptingClientHttpRequest,SimpleClientHttpRequestFactory 会创建返回SimpleBufferingAsyncClientHttpRequest

 5. SimpleBufferingAsyncClientHttpRequest 会正常和httpclient 一样执行execute,暂不多说,主要来说InterceptingClientHttpRequest ,这个是负责负载均衡的

 

 6. InterceptingClientHttpRequest 执行execute ,内部会先执行拦截器也就是之前启动注入的RetryLoadBalancerInterceptor

 7. RetryLoadBalancerInterceptor 内部会执行 RibbonLoadBalancerClient 的choose 方法用 NamedContextFactory 将服务名从注册中心获取实例转为ip:port 的ServiceInstance

 8. 然后 RetryLoadBalancerInterceptor 会拿着得到的ServiceInstance 正常执行http请求得到 ClientHttpResponse

 9. 返回response 全部流程结束

注意点:如果resttemplate 加了@loadbalance 注解,那么就不可以在用ip:port 形式的url请求了,只能用servername 形式,不然会报错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峡谷电光马仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值