【问题标题】:Zuul proxy - how to forward requests to services depending on request pathZuul 代理 - 如何根据请求路径将请求转发到服务
【发布时间】:2020-04-06 01:59:04
【问题描述】:

问题

如何在 Spring Cloud 应用中转发请求?我需要根据 uri 的部分将请求转发到其他服务。

例如

  • HTTP GET http://user-application/api/users,返回用户 JSON。
  • HTTP GET http://user-application/api/proxy/jobs-application/api/jobs,返回作业 JSON,但此请求应转发到另一个应用程序: HTTP GET http://jobs-application/api/jobs.

    • 允许使用任何 HTTP 方法,不仅是 GET

上下文

我有一个 SpringBoot 应用程序,用户应用程序,它具有返回数据的 REST 端点。

例如GET http://user-application/api/users 将以 JSON 格式返回用户。

用户应用程序还有一个 HTTP 端点,它应该将请求转发给其他应用程序 - 我们称其中之一为 Jobs 应用程序

这个端点以HTTP {ANY_METHOD} /api/proxy/{dynamic-service}/{dynamic-path}为例, GET http://user-application/api/proxy/jobs-application/api/jobs

请注意,初始请求来自用户应用程序,然后它被转发到工作应用程序

方法

我提出了一些我认为的方法。也许你过去做过类似的事情,所以你可以分享你这样做的经验。甚至改进我的一种方法。

ProxyController 方法

我会在用户应用程序中创建一个ProxyController,并映射/proxy

@Controller
@RequestMaping("/proxy/**")
ProxyController

public void proxy(final HttpServletRequest request, HttpResponse response) {
    final String requestUri = request.getRequestUri();
    if (!requestUri.startsWith("/api/proxy/")) {
        return null; // Do not proxy
    }

    final int proxyIndex = "/api/proxy/".lenght(); // Can be made a constant
    final String proxiedUrl = requestUri.subString(proxyIndex, requestUri.lenght());

    final Optional<String> payload = retrievePayload(request);
    final Headers headers = retrieveHeaders(request);

    final HttpRequest proxyRequest = buildProxyRequest(request, headers);
    payload.ifPresent(proxyRequest::setPayload);
    final HttpResponse proxyResponse = httpClient.execute(proxyRequest)
    pdateResponse(response, proxyResponse);
}

这种方法的问题,我必须编写大量代码来构建代理请求,以检查它是否有有效负载,如果有,将其复制到代理请求中,然后将标头、cookie 等复制到代理请求,将 HTTP 动词复制到代理请求中。然后,当我得到代理响应时,我必须将其详细信息填充到响应中。

Zuul 方法

我受到 ZuulFilters 的启发:

@Component
public class ProxyFilter extends ZuulFilter {

    private static final String PROXY_PART = "/api/proxy";
    private static final int PART_LENGTH = PROXY_PART.length();

    @Autowired
    public ProxyFilter() {
    }

    @Override
    public boolean shouldFilter() {
        final RequestContext context = RequestContext.getCurrentContext();
        final String requestURI = retrieveRequestUri(context);
        return requestURI.startsWith(PROXY_PART);
    }

    @Override
    public Object run() {
        final RequestContext context = RequestContext.getCurrentContext();
        final String requestURI = retrieveRequestUri(context);
        final String forwardUri = requestURI.substring(PART_LENGTH);
        context.setRouteHost(buildUrl(forwardUri));

        return null;
    }

    @Override
    public String filterType() {
        return "proxy";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    private String retrieveRequestUri(final RequestContext context) {
        final HttpServletRequest request = context.getRequest();
        return request.getRequestURI();
    }

    private URL buildUrl(final String uri) {
        try {
            return new URL(uri);
        } catch (MalformedURLException e) {
            throw new RuntimeException(String.format("Failed to forward request uri %s}.", uri), e);
        }
    }
}

此代码使我可以更轻松地转发请求。但是,我们还在 Spring Cloud Zuul 中使用了客户端负载均衡器 Ribbon 和断路器 Hystrix。如何启用这些功能?他们会在context.setRouteHost(forwardUrl); 中开箱即用地启用吗?

【问题讨论】:

  • 您好,我尝试了您的第二种方法,但显示不支持请求方法“POST”;请求没有到达zuul过滤器。

标签: java spring reverse-proxy netflix-zuul spring-cloud-netflix


【解决方案1】:

我想添加另一种方法,也许它也可以工作。

静态application.yml文件配置Zuul代理方式

这种方法不需要动态 Zuul 过滤器。

application.yml

zuul:
  routes:
    user-application:
      path: /api/users/**
      serviceId: user-service
      stripPrefix: false
      sensitiveHeaders:

    #  I have to define all other services similarly.

    jobs-application:
      path: /api/proxy/jobs/**
      serviceId: jobs-application
      stripPrefix: true
      sensitiveHeaders:

只有在我部署用户应用程序之前我知道我的客户需要调用的所有服务时它才会起作用。如果动态添加新应用程序会怎样?然后我将不得不更新配置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-30
    • 2019-11-07
    • 1970-01-01
    • 2015-08-28
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    相关资源
    最近更新 更多