You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zuul路由前置调用限流服务的Java代码实现方案咨询

Zuul前置限流过滤器实现方案

首先修正你配置中的语法问题:新增的throttle路由缩进错误、key后缺少冒号,修正后配置如下:

routes:
    silver:
      path: "/silver/**"
      serviceId: "SILVER-MICO-SERVICE"
      stripPrefix: true
    gold:
      path: "/gold/**"
      serviceId: "GOLD-MICO-SERVICE"
      stripPrefix: false
    throttle:
      path: "/throttle/**"
      serviceId: "THROTTLE-MICO-SERVICE"
      stripPrefix: false

1. 自定义Zuul前置过滤器实现

你需要使用pre类型的Zuul过滤器,它会在请求转发到目标服务之前执行,优先级设置高于路由转发过滤器即可,代码示例如下:

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Component
public class ThrottleFilter extends ZuulFilter {

    // 注入支持负载均衡的RestTemplate
    @Resource
    private RestTemplate restTemplate;

    // 过滤器类型:pre代表前置执行
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    // 过滤器优先级,数值越小优先级越高,此处设置为高于路由转发过滤器
    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
    }

    // 过滤器生效规则:仅对silver相关请求生效
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        String requestUri = ctx.getRequest().getRequestURI();
        return requestUri.startsWith("/silver/");
    }

    // 核心限流逻辑
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        // 获取请求特征信息传给限流服务,可根据业务需求扩展
        String clientIp = getClientIp(request);
        String requestPath = request.getRequestURI();

        try {
            // 通过服务名调用限流服务,依赖RestTemplate的负载均衡能力
            Boolean passFlag = restTemplate.getForObject(
                    "http://THROTTLE-MICO-SERVICE/throttle/check?ip={ip}&path={path}",
                    Boolean.class,
                    clientIp,
                    requestPath
            );

            // 限流不通过直接返回错误,不转发到目标服务
            if (!Boolean.TRUE.equals(passFlag)) {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(429);
                ctx.getResponse().setContentType("application/json;charset=utf-8");
                ctx.setResponseBody("{\"code\":429,\"msg\":\"请求过于频繁,请稍后再试\"}");
            }
        } catch (Exception e) {
            // 限流服务调用异常的降级逻辑,可根据业务需求调整为放行/拦截
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(500);
            ctx.setResponseBody("{\"code\":500,\"msg\":\"系统繁忙,请稍后再试\"}");
        }
        return null;
    }

    // 获取客户端真实IP工具方法
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
}

2. 配套配置

需要在Spring配置类中注入带负载均衡能力的RestTemplate:

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

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

其他说明

  • 如果不需要对外暴露限流服务接口,可以直接删掉配置中的throttle路由,过滤器直接通过服务名调用即可,不会对外暴露限流服务端点
  • 如果需要对gold接口也做限流,只需要修改shouldFilter方法的判断逻辑即可
  • 限流服务的入参、返回值可根据业务需求调整,比如新增用户ID、请求方法等判断维度

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 09:36:07