使用dubbo filter实现一个限流过滤器
3 个月前

yyds

一个女儿的爸爸
在 Dubbo 中,可以通过 Filter 来实现对调用进
行过滤和处理,包括限流、鉴权、日志等操作。在这
里,我们将以限制同一个调用方、同一个接口的接口
调用时间间隔不超过 300 毫秒为例,实现一个限流
具体实现步骤如下:
自定义过滤器
首先,我们需要自定义一个过滤器来实现限流操作。
在这个过滤器中,我们可以定义一个 Map 来保存接
口的调用时间,以调用方和接口名为键。如果当前时
间与上一次调用时间间隔小于 300 毫秒,就拒绝调
用,否则更新调用时间并继续执行。
public class LimitFilter implements Filter {
private final Map<String, Long> callTimeMap = new ConcurrentHashMap<>(); // 接口调用时间
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String interfaceName = invoker.getInterface().getName();
String caller = RpcContext.getContext().getRemoteHost(); // 调用方IP地址
String key = interfaceName + ":" + caller;
long now = System.currentTimeMillis();
Long lastCallTime = callTimeMap.get(key);
if (lastCallTime != null && now - lastCallTime < 300) {
// 如果调用时间间隔小于 300 毫秒,拒绝调用
return new RpcResult(new RuntimeException("Invoke too fast!"));
} else {
// 更新调用时间并继续执行
callTimeMap.put(key, now);
return invoker.invoke(invocation);
}
}
}
配置过滤器
在 Dubbo 的配置文件(例如 dubbo.xml)中,我
们需要将这个自定义的过滤器配置到 provider 的
filter 中,以便让 Dubbo 知道我们需要使用这个
过滤器进行限流操作。
<bean id="limitFilter" class="com.example.LimitFilter" />
<dubbo:provider filter="limitFilter" />
测试限流效果
现在我们可以测试一下我们实现的限流过滤器的效果
了。我们可以写一个简单的 Dubbo 服务,其中包含
一个方法,用于睡眠 500 毫秒,并返回字符串。
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello, " + name;
}
}
然后,我们可以编写一个客户端程序,在其中不断地
调用 sayHello() 方法,模拟高并发调用的情况。
public class DemoClient {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo.xml");
DemoService demoService = context.getBean(DemoService.class);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
while (true) {
try {
String result = demoService.sayHello(UUID.randomUUID().toString());
System.out.println(Thread.currentThread().getName() + " => " + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}, "Thread-" + i).start();
}
}
}
如果限流过滤器生效,我们将会看到输出中出现不
少类似下面的错误:
java.lang.RuntimeException: Invoke too
fast!