Zuul 通过外部代理服务器路由请求
Zuul routing the requests through an external proxy server
我们当前的项目要求是将一些请求路由到第三方外部 api 服务器。为此,我们使用 spring 基于 zuul 的路由器服务。
zuul:
routes
test:
path: /test/**
serviceId: test
url: http://my.api.server.com
test2:
path: /test2/**
serviceId: test2
url: http://my.api.server.com // but through an external proxy
现在的要求是,对于某些端点,对外部 api 服务器的请求已通过某些不属于我们的外部代理服务器进行路由,
如何通过 curl 执行此操作:
curl <external_api_server>/api/v1/user -k \
-x tntqyhnhjym.sandbox.verygoodproxy.com:8080 \
-H "Content-type: application/json" \
-d '{"card_number": "tok_sandbox_t8VSoovCuHA779eJGZhKvg", ... }'
-x <proxy>
通过给定的代理重定向请求。
如何通过 spring-zuul 服务器做到这一点?
有一个线索,我得到了吗? https://github.com/spring-cloud/spring-cloud-netflix/issues/2320。不干净,因为我需要扩展 zuul
的 SimpleHostRoutingFilter
选项 1 - 反向代理服务器(使用代理)
您可以设置反向代理 - 配置为通过代理。您的反向代理将使用参数(例如 java 或 nodejs)启动以使用外部代理。这个反向代理将是一个不同的过程,它将通过您想要的代理传递所有请求。
您可以通过设置第二个 zuul 代理应用程序或通过 nodejs 反向代理 (express or node-http-proxy) 来实现。
第二个zuul应用(只针对外部)
因此,如果您使用 zuul,您将使用以下内容创建第二个应用程序:
test2:
path: /proxied-test2/**
serviceId: test2
url: http://my.api.server.com
然后您将使用您的代理参数和特定端口(例如 9200
)在同一台服务器上启动此服务器,例如
-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888
原始申请
在您原来的应用程序中,您会将路线替换为以下内容。
zuul:
routes
test:
path: /test/**
serviceId: test
url: http://my.api.server.com
test2:
path: /test2/**
serviceId: test2
url: http://localhost:9200/proxied-test2/
选项 2:使用可编写脚本的 http 代理服务器
您可以设置一个代理服务器,然后设置一些例外和规则,以决定哪些请求应该通过代理路由,哪些请求应该在没有代理的情况下工作。
第二步是将您的应用程序配置为使用在第 1 步中指定的本地代理服务器。为此,您可以使用以下 command-line 参数:
-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888
我过去曾为代理服务器配置过排除列表,但我从未configured/scripted包含列表。在你的情况下,包含列表会更有意义,所以我会测试 scriptable/programmable 代理服务器,例如:
- https://mitmproxy.org/ - scriptable via mitmdump
我也花了几个小时寻找这个问题的解决方案。我找到了一种比前面描述的方法更灵活、更容易的方法。
您可以实现自定义 ProxySelector 并为您想要的每个路由定义不同的代理。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.*;
import java.net.Proxy.Type;
import java.util.ArrayList;
import java.util.List;
public class CustomProxySelector extends ProxySelector {
ProxySelector defaultProxySelector = ProxySelector.getDefault();
ArrayList<Proxy> noProxy = new ArrayList<>();
ArrayList<Proxy> proxies = new ArrayList<>();
public CustomProxySelector(String proxyHost, int proxyPort) {
noProxy.add(Proxy.NO_PROXY);
proxies.add(new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
}
//define your custom proxy selection here
@Override
public List<Proxy> select(URI uri) {
if (uri.getHost().matches("external.address.com")) {
return proxies;
}
if (defaultProxySelector != null) {
return defaultProxySelector.select(uri);
}
return noProxy;
}
@Override
public void connectFailed(URI arg0, SocketAddress arg1, IOException arg2) {
//error handling
}
}
然后添加一个 CloseableHttpClient 类型的 bean,它会覆盖 Zuul 的标准 HttpClient,并使用您自定义的 ProxySelector 实现对其进行配置。
@Bean
@Primary
public CloseableHttpClient customHttpClientForZuulWithHttpProxyConfig(@Value("${your.proxy.host}") String proxyHost, @Value("${your.proxy.port}") int proxyPort) {
SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(new CustomProxySelector(proxyHost, proxyPort));
return HttpClientBuilder.create().setRoutePlanner(routePlanner).build();
}
另请注意,spring 云不再支持 zuul。所以推荐的方法是切换到 spring 网关。
我们当前的项目要求是将一些请求路由到第三方外部 api 服务器。为此,我们使用 spring 基于 zuul 的路由器服务。
zuul:
routes
test:
path: /test/**
serviceId: test
url: http://my.api.server.com
test2:
path: /test2/**
serviceId: test2
url: http://my.api.server.com // but through an external proxy
现在的要求是,对于某些端点,对外部 api 服务器的请求已通过某些不属于我们的外部代理服务器进行路由,
如何通过 curl 执行此操作:
curl <external_api_server>/api/v1/user -k \
-x tntqyhnhjym.sandbox.verygoodproxy.com:8080 \
-H "Content-type: application/json" \
-d '{"card_number": "tok_sandbox_t8VSoovCuHA779eJGZhKvg", ... }'
-x <proxy>
通过给定的代理重定向请求。
如何通过 spring-zuul 服务器做到这一点?
有一个线索,我得到了吗? https://github.com/spring-cloud/spring-cloud-netflix/issues/2320。不干净,因为我需要扩展 zuul
SimpleHostRoutingFilter
选项 1 - 反向代理服务器(使用代理)
您可以设置反向代理 - 配置为通过代理。您的反向代理将使用参数(例如 java 或 nodejs)启动以使用外部代理。这个反向代理将是一个不同的过程,它将通过您想要的代理传递所有请求。
您可以通过设置第二个 zuul 代理应用程序或通过 nodejs 反向代理 (express or node-http-proxy) 来实现。
第二个zuul应用(只针对外部)
因此,如果您使用 zuul,您将使用以下内容创建第二个应用程序:
test2:
path: /proxied-test2/**
serviceId: test2
url: http://my.api.server.com
然后您将使用您的代理参数和特定端口(例如 9200
)在同一台服务器上启动此服务器,例如
-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888
原始申请
在您原来的应用程序中,您会将路线替换为以下内容。
zuul:
routes
test:
path: /test/**
serviceId: test
url: http://my.api.server.com
test2:
path: /test2/**
serviceId: test2
url: http://localhost:9200/proxied-test2/
选项 2:使用可编写脚本的 http 代理服务器
您可以设置一个代理服务器,然后设置一些例外和规则,以决定哪些请求应该通过代理路由,哪些请求应该在没有代理的情况下工作。
第二步是将您的应用程序配置为使用在第 1 步中指定的本地代理服务器。为此,您可以使用以下 command-line 参数:
-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888
我过去曾为代理服务器配置过排除列表,但我从未configured/scripted包含列表。在你的情况下,包含列表会更有意义,所以我会测试 scriptable/programmable 代理服务器,例如:
- https://mitmproxy.org/ - scriptable via mitmdump
我也花了几个小时寻找这个问题的解决方案。我找到了一种比前面描述的方法更灵活、更容易的方法。
您可以实现自定义 ProxySelector 并为您想要的每个路由定义不同的代理。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.*;
import java.net.Proxy.Type;
import java.util.ArrayList;
import java.util.List;
public class CustomProxySelector extends ProxySelector {
ProxySelector defaultProxySelector = ProxySelector.getDefault();
ArrayList<Proxy> noProxy = new ArrayList<>();
ArrayList<Proxy> proxies = new ArrayList<>();
public CustomProxySelector(String proxyHost, int proxyPort) {
noProxy.add(Proxy.NO_PROXY);
proxies.add(new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
}
//define your custom proxy selection here
@Override
public List<Proxy> select(URI uri) {
if (uri.getHost().matches("external.address.com")) {
return proxies;
}
if (defaultProxySelector != null) {
return defaultProxySelector.select(uri);
}
return noProxy;
}
@Override
public void connectFailed(URI arg0, SocketAddress arg1, IOException arg2) {
//error handling
}
}
然后添加一个 CloseableHttpClient 类型的 bean,它会覆盖 Zuul 的标准 HttpClient,并使用您自定义的 ProxySelector 实现对其进行配置。
@Bean
@Primary
public CloseableHttpClient customHttpClientForZuulWithHttpProxyConfig(@Value("${your.proxy.host}") String proxyHost, @Value("${your.proxy.port}") int proxyPort) {
SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(new CustomProxySelector(proxyHost, proxyPort));
return HttpClientBuilder.create().setRoutePlanner(routePlanner).build();
}
另请注意,spring 云不再支持 zuul。所以推荐的方法是切换到 spring 网关。