使用Spring构建实时聊天通知的页面应用(续篇)

原文链接

欢迎大家对于本站的访问 - AsterCasc

前言

在前篇使用Spring构建实时聊天通知的页面应用中,我们构建了一个可通信的简单websocket应用。但是这里还有一个问题,我们常规的微服务一般是不会直接暴露在公网的,那么在网关转发下我们如何建立连接?

网关

首先,前文中我们提到对于跨域问题,一般的处理方法是

@Configuration  
@EnableWebSocketMessageBroker  
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {  
	//...

    @Override  
    public void registerStompEndpoints(StompEndpointRegistry registry) {  
        //建立连接地址  
        registry.addEndpoint("/chat-websocket")  
				.setAllowedOrigins("http://localhost:8080")
                .withSockJS();  
    }  
  
}

但是,如果我们尝试使用通配符进行处理的时候,例如.setAllowedOrigins("*")就会报错No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.,此时我们需要使用.setAllowedOriginPatterns("*")代替

此时我们再来考虑网关,如果我们的网关此前也是使用的通配符配置,比如:

spring:  
  cloud:  
    gateway:  
      globalcors:  
        cors-configurations:  
          '[/**]':  
            allowedOrigins: "*"  
            allowedHeaders: "*"  
            allowedMethods: "*"  
            allowCredentials: true

那么同样,我们需要将allowedOrigins改为allowedOriginPatterns,使用专门的通配参数进行处理,此时就会报一个新的错误:The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:8080, http://localhost:8080', but only one is allowed. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.,意味着我们在网关和服务端都设置了Access-Control-Allow-Origin导致重复报错,那我们的选择是去掉一个么?重新配置网关的逻辑肯定是不合适的,作为网关不应该跟着业务逻辑跑,那么改服务端的么,那就只透了网关,等于没配。所以这里正常的处理应该是网关处对于Access-Control-Allow-Origin进行去重即可,这里可以选择配置文件的方式,也可以选择编程的方式进行配置:

spring:  
  cloud:  
    gateway:  
      defaultFilters:  
        - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_UNIQUE

或者:

//RouteLocatorBuilder builder -> builder.routes -> RouteLocatorBuilder.Builder::route -> Function<PredicateSpec, Buildable<Route>> fn
filter.dedupeResponseHeader("Access-Control-Allow-Origin", "RETAIN_UNIQUE")  
        .dedupeResponseHeader("Access-Control-Allow-Credentials", "RETAIN_UNIQUE");

其实以上对于服务本身来说就已经可以了,但是还有相当一部分的代码会提供给你类似这样的配置:

spring:
  cloud:
    gateway:
      routes:
      - id: websocket-sockjs-route
        uri: http://websocket-service
        predicates:
        - Path=/websocket/info/**
      - id: websocket_route
        uri: lb:ws://websocket-service
        predicates:
        - Path=/websocket/**

这个配置的目的是将流程中websocket操作和http区分开,但是对于绝大多数的spring版本没有必要进行这个单独的配置,正常转发就可以了,在很早期的spring就已经将websocket兼容了,不需要进行特殊配置,更何况这种类似的配置很多配的都不对,只是因为spring都兼容了,很多情况下所以即使不对也不会产生什么影响

Nginx

nginx对于websocket的兼容是比较麻烦的,但是在1.3.13之后,就非常简单了,使用了协议切换Switching ProtocolsHTTP切换为WebSocket,具体可以参考WebSocket proxying

server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;
        server_name  api.astercasc.com;

		#some else config

        #static resources
        location /ushio/resources {
                proxy_pass  http://xxx:xxx;
        }
        #websocket
        location /yui/chat-websocket/ {
                proxy_pass  http://xxx:xxx;

                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_read_timeout 3600;
        }
        #service
        location / {
                proxy_pass  http://xxx:xxx;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Real-IP $remote_addr;
        }
    }

可以使用proxy_read_timeout自定义超时时间,默认为60秒

目前代理版本proxy_http_version不支持http2,参考Allow proxy_http_version 2.0

There are no plans to implement HTTP/2 support in the proxy module in the foreseeable future

There is almost no sense to implement it, as the main HTTP/2 benefit is that it allows multiplexing many requests within a single connection, thus almost removing the limit on number of simalteneous requests - and there is no such limit when talking to your own backends. Moreover, things may even become worse when using HTTP/2 to backends, due to single TCP connection being used instead of multiple ones.

原文链接

欢迎大家对于本站的访问 - AsterCasc

  • 23
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值