spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发

本文为博主原创,转载请注明出处:

  在spring cloud gateway 为 2.x 的版本的时候,可以通过引入 ribbon ,在进行过滤器 LoadBalancerClientFilter 进行服务请求路由时,通过调用 choose 方法选择具体的服务实例,源码如下:

public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
    public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10100;
    private static final Log log = LogFactory.getLog(LoadBalancerClientFilter.class);
    protected final LoadBalancerClient loadBalancer;
    private LoadBalancerProperties properties;
    public LoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) {
        this.loadBalancer = loadBalancer;
        this.properties = properties;
    }
    public int getOrder() {
        return 10100;
    }
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        URI url = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        String schemePrefix = (String)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
        if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {
            ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
            if (log.isTraceEnabled()) {
                log.trace("LoadBalancerClientFilter url before: " + url);
            }
            ServiceInstance instance = this.choose(exchange);
            if (instance == null) {
                throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());
            } else {
                URI uri = exchange.getRequest().getURI();
                String overrideScheme = instance.isSecure() ? "https" : "http";
                if (schemePrefix != null) {
                    overrideScheme = url.getScheme();
                }
                URI requestUrl = this.loadBalancer.reconstructURI(new DelegatingServiceInstance(instance, overrideScheme), uri);
                if (log.isTraceEnabled()) {
                    log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
                }
                exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
                return chain.filter(exchange);
            }
        } else {
            return chain.filter(exchange);
        }
    }
    protected ServiceInstance choose(ServerWebExchange exchange) {
        return this.loadBalancer.choose(((URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR)).getHost());
    }
}

  在choose 方法的调用中,打断点跟进,如果服务中引入了 ribbon ,断点会进入 到  RibbonLoadBalancerClient 中

  在使用 ribbon 的过程中,服务的实例是在 RibbonLoadBalancerClient.RibbonServer 类中进行了实例的封装,源码如下:

public static class RibbonServer implements ServiceInstance {
        private final String serviceId;
        private final Server server;
        private final boolean secure;
        private Map<String, String> metadata;
        public RibbonServer(String serviceId, Server server) {
            this(serviceId, server, false, Collections.emptyMap());
        }
        public RibbonServer(String serviceId, Server server, boolean secure, Map<String, String> metadata) {
            this.serviceId = serviceId;
            this.server = server;
            this.secure = secure;
            this.metadata = metadata;
        }
        public String getInstanceId() {
            return this.server.getId();
        }
        public String getServiceId() {
            return this.serviceId;
        }
        public String getHost() {
            return this.server.getHost();
        }
        public int getPort() {
            return this.server.getPort();
        }
        public boolean isSecure() {
            return this.secure;
        }
        public URI getUri() {
            return DefaultServiceInstance.getUri(this);
        }
        public Map<String, String> getMetadata() {
            return this.metadata;
        }
        public Server getServer() {
            return this.server;
        }
        public String getScheme() {
            return this.server.getScheme();
        }
        public String toString() {
            StringBuilder sb = new StringBuilder("RibbonServer{");
            sb.append("serviceId='").append(this.serviceId).append('\'');
            sb.append(", server=").append(this.server);
            sb.append(", secure=").append(this.secure);
            sb.append(", metadata=").append(this.metadata);
            sb.append('}');
            return sb.toString();
        }
    }

  在 服务路由进行请求时,会根据其中的  isSecure 属性判断是否进行 https 请求,如果是 isSecure 是 true,则请求的scheme 协议为 https,反之为 http ;该值可以通过以下方式进行配置:

ribbon.isSecure=true

  在 spring cloud gateway 中spring-cloud--openfeign-core为 3.x 的版本的时候,该依赖中 将 ribbon 单独的脱离了出来,此时的ribbon 配置不会生效。通过阅读源码之后会发现,该请求的协议是通过调用服务的 sslPort端口来判断是否进行https 请求,如果 sslPort端口不为空,则进行https 请求,

  以使用 zookeeper 为注册中心时,查看自动发现配置的property 文件:

@ConfigurationProperties("spring.cloud.zookeeper.discovery")
public class ZookeeperDiscoveryProperties {
  public static final String DEFAULT_URI_SPEC = "{scheme}://{address}:{port}";
  private HostInfo hostInfo;
  private boolean enabled = true;
  private String root = "/services";
  private String uriSpec = "{scheme}://{address}:{port}";
  private String instanceId;
  private String instanceHost;
  private String instanceIpAddress;
  private boolean preferIpAddress = false;
  private Integer instancePort;
  private Integer instanceSslPort;
  private boolean register = true;
  private Map<String, String> metadata = new HashMap();
  private String initialStatus = "UP";
  private int order = 0;
}

  在 choose 选择路由的服务时,会 根据ServiceInstance的实例的 isSecure 属性,解析得出http 或https,而zookeeperInstance 是根据  instanceSslPort 端口是否为空进行解析出http或https。zookeeperInstance解析http与https的源码在ZookeeperServiceInstance中

如果想在服务路由时,进行https 的路由,可以进行如下的配置:

server:
  port: 9000
spring:
  application:
    name: my-zookeeper-registry
  cloud:
    zookeeper:
      connect-string: localhost:2181
      discovery:
        register: true
        enabled: true
        root: my-registry
        instance-ssl-port: {{server.port}}

 

  按照上述配置,可以实现 https 的网关路由转发。

 

标签: spring cloud

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
13天前
|
消息中间件 监控 Ubuntu
大数据-54 Kafka 安装配置 环境变量配置 启动服务 Ubuntu配置 ZooKeeper
大数据-54 Kafka 安装配置 环境变量配置 启动服务 Ubuntu配置 ZooKeeper
46 3
大数据-54 Kafka 安装配置 环境变量配置 启动服务 Ubuntu配置 ZooKeeper
|
15天前
|
安全 应用服务中间件 Shell
nginx配置https的ssl证书和域名
nginx配置https的ssl证书和域名
|
13天前
|
分布式计算 Hadoop
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
33 1
|
1月前
|
数据安全/隐私保护 Docker 容器
配置Harbor支持https功能实战篇
关于如何配置Harbor支持HTTPS功能的详细教程。
72 12
配置Harbor支持https功能实战篇
|
1月前
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
文章介绍了如何配置HAProxy以支持HTTPS协议和实现服务器的动态上下线。
110 8
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
|
1月前
|
分布式计算 Hadoop Devops
Hadoop集群配置https实战案例
本文提供了一个实战案例,详细介绍了如何在Hadoop集群中配置HTTPS,包括生成私钥和证书文件、配置keystore和truststore、修改hdfs-site.xml和ssl-client.xml文件,以及重启Hadoop集群的步骤,并提供了一些常见问题的故障排除方法。
60 3
Hadoop集群配置https实战案例
|
1月前
|
Java 网络安全
zookeeper的环境搭建和配置
本文介绍了如何在多台节点上搭建和配置Zookeeper环境。内容包括Zookeeper的下载、解压、环境变量配置、配置文件修改、zkdata目录创建、myid文件设置,以及将Zookeeper及其配置文件复制到其他节点。还提供了运行测试的命令,包括启动、状态检查和停止Zookeeper服务。
zookeeper的环境搭建和配置
|
1月前
|
Linux Docker Windows
Docker配置https证书案例
本文介绍了如何为Docker的Harbor服务配置HTTPS证书,包括安装Docker和Harbor、修改配置文件以使用证书、生成自签名证书、配置证书以及验证配置的步骤。
92 2
Docker配置https证书案例
|
1月前
|
应用服务中间件 网络安全 Apache
HTTPS配置
HTTPS配置
107 11
|
13天前
|
存储 SQL 消息中间件
Hadoop-26 ZooKeeper集群 3台云服务器 基础概念简介与环境的配置使用 架构组成 分布式协调框架 Leader Follower Observer
Hadoop-26 ZooKeeper集群 3台云服务器 基础概念简介与环境的配置使用 架构组成 分布式协调框架 Leader Follower Observer
34 0