@Override
    public boolean isAllowable(URL url, Invocation invocation) {
        int rate = url.getMethodParameter(RpcUtils.getMethodName(invocation), TPS_LIMIT_RATE_KEY, -1);
        long interval = url.getMethodParameter(
                RpcUtils.getMethodName(invocation), TPS_LIMIT_INTERVAL_KEY, DEFAULT_TPS_LIMIT_INTERVAL);
        String serviceKey = url.getServiceKey();
        if (rate > 0) {
            StatItem statItem = stats.get(serviceKey);
            if (statItem == null) {
                stats.putIfAbsent(serviceKey, new StatItem(serviceKey, rate, interval));
                statItem = stats.get(serviceKey);
            } else {
                // rate or interval has changed, rebuild
                if (statItem.getRate() != rate || statItem.getInterval() != interval) {
                    stats.put(serviceKey, new StatItem(serviceKey, rate, interval));
                    statItem = stats.get(serviceKey);
                }
            }
            return statItem.isAllowable();
        } else {
            StatItem statItem = stats.get(serviceKey);
            if (statItem != null) {
                stats.remove(serviceKey);
            }
        }

        return true;
    }
@Test
    void testIsAllowable() {
        Invocation invocation = new MockInvocation();
        URL url = URL.valueOf("test://test");
        url = url.addParameter(INTERFACE_KEY, "org.apache.dubbo.rpc.file.TpsService");
        url = url.addParameter(TPS_LIMIT_RATE_KEY, TEST_LIMIT_RATE);
        url = url.addParameter(TPS_LIMIT_INTERVAL_KEY, 1000);
        for (int i = 1; i <= TEST_LIMIT_RATE; i++) {
            Assertions.assertTrue(defaultTPSLimiter.isAllowable(url, invocation));
        }
    }