一、http.proxy 的基本定义
http.proxy 是用于配置 HTTP 协议代理服务器的参数,本质是指定一个 "中间服务器" 的网络地址(通常由 IP 地址和端口号组成)。当设备(如电脑、手机)或应用(如浏览器、编程脚本)需要访问 HTTP 协议的网络资源时,不会直接与目标服务器通信,而是先将请求发送到这个 "中间服务器",再由中间服务器转发请求、接收响应并回传,实现间接访问网络的效果。
简单来说,它就像网络访问的 "中转站",负责衔接客户端与目标服务器,是实现 HTTP 代理功能的核心配置项。
二、http.proxy 的核心作用
- 突破网络限制
若设备处于受限网络环境(如企业内网、校园网、部分地区网络),无法直接访问某些外部 HTTP 资源,通过配置 http.proxy 指向可访问外部网络的代理服务器,可绕过限制,正常获取资源(例如企业员工通过公司代理访问外网办公资源)。
- 隐藏客户端真实 IP
客户端的 HTTP 请求会先经过代理服务器,目标服务器接收到的请求来源是代理服务器的 IP,而非客户端真实 IP,从而保护客户端的网络身份,降低被追踪的风险(常见于需要隐私保护的场景)。
- 加速网络访问(部分场景)
部分代理服务器会缓存已访问过的 HTTP 资源(如图片、静态网页),当其他客户端通过该代理访问相同资源时,无需重新向目标服务器请求,可直接从代理的缓存中获取,减少网络传输时间,提升访问速度(多见于企业、校园等共享网络环境)。
- 过滤与管控网络内容
管理员可通过配置 http.proxy,对客户端的 HTTP 请求进行过滤(如拦截恶意网站、限制访问无关娱乐网站),实现网络内容的管控(例如企业限制员工上班时间访问购物网站,学校过滤有害信息)。
三、Spring Cloud Gateway 定义
Spring Cloud Gateway 是 Spring Cloud 生态体系中的一款基于 Spring 5、Spring Boot 2 和 Project Reactor 等技术开发的网关产品,它旨在为微服务架构提供一种简单、高效且易于扩展的 API 路由管理和请求过滤解决方案,用于替代传统的 Spring Cloud Netflix Zuul 网关。
四、核心功能
- 路由转发:能根据请求的不同属性(如路径、方法、请求头、参数等),将请求精准转发到对应的微服务实例。例如,可配置当请求路径以 /user/ 开头时,将请求转发到用户服务。
- 请求过滤:支持在请求到达目标服务之前和之后进行过滤处理。前置过滤可实现身份认证、参数校验、请求日志记录等功能;后置过滤可完成响应数据处理、响应日志记录等操作。
- 负载均衡:集成了 Spring Cloud LoadBalancer 等负载均衡组件,可在多个微服务实例之间按照一定的策略(如轮询、随机、权重等)分配请求,提高服务的可用性和并发处理能力。
- 服务熔断与降级:当后端服务出现故障或响应延迟过高时,可通过熔断机制快速切断请求链路,避免故障扩散;同时,可配置降级策略,返回预设的友好响应信息,提升用户体验。
- 动态路由配置:支持通过配置中心(如 Nacos、Apollo 等)实现路由规则的动态更新,无需重启网关服务,即可实时生效新的路由配置,极大地提高了系统的灵活性和可维护性。
五、Spring Cloud Gateway如何支持http.proxy ?
yaml
spring:
cloud:
gateway:
httpclient:
wiretap: true
proxy:
host: pre-ss.broker.com
port: 80
六、相关源码阅读
arduino
@ConfigurationProperties("spring.cloud.gateway.httpclient")
public class HttpClientProperties {
/** The connect timeout in millis, the default is 45s. */
private Integer connectTimeout;
/** The response timeout. */
private Duration responseTimeout;
/** Pool configuration for Netty HttpClient. */
private Pool pool = new Pool();
/** Proxy configuration for Netty HttpClient. */
private Proxy proxy = new Proxy();
/** SSL configuration for Netty HttpClient. */
private Ssl ssl = new Ssl();
/** Enables wiretap debugging for Netty HttpClient. */
private boolean wiretap;
ini
@Bean
@ConditionalOnMissingBean
public HttpClient gatewayHttpClient(HttpClientProperties properties) {
// configure pool resources
HttpClientProperties.Pool pool = properties.getPool();
ConnectionProvider connectionProvider;
if (pool.getType() == DISABLED) {
connectionProvider = ConnectionProvider.newConnection();
}
else if (pool.getType() == FIXED) {
connectionProvider = ConnectionProvider.fixed(pool.getName(),
pool.getMaxConnections(), pool.getAcquireTimeout());
}
else {
connectionProvider = ConnectionProvider.elastic(pool.getName());
}
HttpClient httpClient = HttpClient.create(connectionProvider)
.tcpConfiguration(tcpClient -> {
if (properties.getConnectTimeout() != null) {
tcpClient = tcpClient.option(
ChannelOption.CONNECT_TIMEOUT_MILLIS,
properties.getConnectTimeout());
}
// configure proxy if proxy host is set.
HttpClientProperties.Proxy proxy = properties.getProxy();
if (StringUtils.hasText(proxy.getHost())) {
tcpClient = tcpClient.proxy(proxySpec -> {
ProxyProvider.Builder builder = proxySpec
.type(ProxyProvider.Proxy.HTTP)
.host(proxy.getHost());
PropertyMapper map = PropertyMapper.get();
map.from(proxy::getPort).whenNonNull().to(builder::port);
map.from(proxy::getUsername).whenHasText()
.to(builder::username);
map.from(proxy::getPassword).whenHasText()
.to(password -> builder.password(s -> password));
map.from(proxy::getNonProxyHostsPattern).whenHasText()
.to(builder::nonProxyHosts);
});
}
return tcpClient;
});
HttpClientProperties.Ssl ssl = properties.getSsl();
if (ssl.getTrustedX509CertificatesForTrustManager().length > 0
|| ssl.isUseInsecureTrustManager()) {
httpClient = httpClient.secure(sslContextSpec -> {
// configure ssl
SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
X509Certificate[] trustedX509Certificates = ssl
.getTrustedX509CertificatesForTrustManager();
if (trustedX509Certificates.length > 0) {
sslContextBuilder.trustManager(trustedX509Certificates);
}
else if (ssl.isUseInsecureTrustManager()) {
sslContextBuilder
.trustManager(InsecureTrustManagerFactory.INSTANCE);
}
sslContextSpec.sslContext(sslContextBuilder)
.defaultConfiguration(ssl.getDefaultConfigurationType())
.handshakeTimeout(ssl.getHandshakeTimeout())
.closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout())
.closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout());
});
}
if (properties.isWiretap()) {
httpClient = httpClient.wiretap(true);
}
return httpClient;
}