Dubbo源码分析:RPC协议实现-服务端限流与Semaphore信号量

撸了今年阿里、腾讯和美团的面试,我有一个重要发现…….

作者:backend

出处:https://blog.csdn.net/u010013573/article/category/8462451


概述

Dubbo支持在服务端通过在service或者method,通过executes参数设置每个方法,允许并发调用的最大线程数,即在任何时刻,只允许executes个线程同时调用该方法,超过的则抛异常返回,从而对提供者服务进行并发控制,保护资源。

用法

服务级别

限制 com.foo.BarService 的每个方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个:

方法级别

限制 com.foo.BarService 的 sayHello 方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个:


源码实现

  • Java Semaphore:信号量

    • 定义:Java信号量类似于一个计数器,用于限制在任何时刻,只允许给定个线程对某个共享资源的访问。
    • 用法:
  1. 获取信号量:每个线程通过执行tryAcquire(非阻塞)或者acquire(阻塞,可中断)获取一个信号量或者说是通行证,同时将信号总量减一,当数量变为0时,则后面来的线程获取则返回false或者阻塞;
  2. 释放信号量:线程对并发资源访问完毕之后,通过调用relase方法将信号总量加1,允许一个线程访问该共享资源;
  • ExecuteLimitFilter:线程并发控制过滤器
    201907191005_1.png
  1. 服务端每个线程处理RPC请求,进行provider方法调用时,该线程执行ExecuteLimitFilter的invoke方法,定义Semaphore类型的executeLimit的局部变量,该局部变量的主要作用是用于引用与该provider方法绑定的RpcStatus,该RpcStatus由所有调用该provider方法的线程共享;
  2. 调用count.getSemaphore(max)获取该provider方法(即共享资源)的信号量:
    201907191005_2.png
  • 通过synchronized和double check来保证信号量只初始化一次或者当前调用的url指定的executes数量变化时,更新。注意executesLimit为RpcStatus的实例的field,而单个provider的方法所绑定的rpcStatus是又所有调用这个方法的线程共享的,故为了保证该executesLimit对其他线程的可见性,从而在其中一个线程初始化之后,其他线程在进入synchronized块,再次判断executeLimit是否为null时,感知其他线程已经初始化过了,需要将executesLimit设置为volatile:
    201907191005_3.png
  • 调用Semaphore的tryAcquire获取一个信号量,如果获取到则进行往下执行进行provider的方法调用,否则抛异常返回。
    201907191005_4.png
    其中tryAcquire为非阻塞的,直接返回true或者false,当前线程进行往下执行,需要在程序中控制是否获取成功的处理,并且是unfair的。
    201907191005_5.png
赞(0) 打赏

如未加特殊说明,此网站文章均为原创,转载必须注明出处。Java 技术驿站 » Dubbo源码分析:RPC协议实现-服务端限流与Semaphore信号量
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

关注【Java 技术驿站】公众号,每天早上 8:10 为你推送一篇技术文章

扫描二维码关注我!


关注【Java 技术驿站】公众号 回复 “VIP”,获取 VIP 地址永久关闭弹出窗口

免费获取资源

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏