Gateway整合websocket

之前寫過springboot和websocket整合的例子,https://blog.csdn.net/u014203449/article/details/102902078

在微服務中,頁面與後臺服務器的交互一般要通過網關,所以網關是否支持長鏈接也得調試一把。

springcloud中有兩個網關組件zuul和gateway。

經查閱zuul是不支持長鏈接的,而gateway支持長鏈接。並且zuul底層是同步阻塞基於servlet,而gateway是基於netty、webflux異步非堵塞,性能更好。

現在來看看gateway和websoket的整合。

 

建立一個eureka項目,不贅述了。

建立提供websocket業務的服務wisdomclass-demo,註冊到註冊中心,websoket的配置也是和上篇文章一樣。https://blog.csdn.net/u014203449/article/details/102902078

主要是gateway的配置,上個配置文件。主要看cloud.gateway.routes的配置:

server:
  port: 9006

spring:
  application:
    name: wisdomclass-gateway
  servlet:
    multipart:
      enabled: true #使用http multipart上傳處理
      max-file-size: 100MB #單個文件的最大長度爲100MB,默認1mb
      max-request-size: 100MB #請求的總數據大小
      file-size-threshold: 1MB #文件大小閾值,當大於這個閾值時將寫入到磁盤,否則存在內存中,(默認值0 一般情況下不用特意修改)
      location: /  #超過以上閾值時,寫入的臨時目錄,當請求響應完成後,臨時文件自動刪除
  cloud:
    gateway:
      routes:
        - id: demo
          order: 5
          uri: lb://wisdomclass-demo   #lb代表從註冊中心獲取服務,將path的請求路由到uri
          predicates:
            - Path=/wisdomclass-demo/**
          filters:
            - StripPrefix=1    #除去第一個/前綴,比如請求/wisdomclass-demo/demo,會去除前綴/wisdomclass-demo,請求到路由服務的 /demo接口
            - name: Hystrix    #熔斷
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback  #網關的統一熔斷接口
        - id: demo
          uri: lb:ws://wisdomclass-demo     #wesocket協議
          order: 2
          predicates:
            - Path=/wisdomclass-demo/topic/**
          filters:
            - StripPrefix=1
        - id: demo
          uri: lb:ws://wisdomclass-demo
          order: 3
          predicates:
            - Path=/wisdomclass-demo/app/**
          filters:
            - StripPrefix=1

hystrix:
  command:
    fallbackcmd:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000  #超時時間後進入熔斷

#eureka客戶端配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9000/eureka/
logging:
  level:
    root: info


主要看cloud.gateway.routes的配置:

id只是個路由標誌,我認爲沒有什麼用,兩個路由配置id可以相同。

order是執行順序,兩個id相同的路由配置會執行order數值小的。

predicates:是判斷請求地址是否符合 value,如果符合會路由到uri 的value地址。

uri:請求符合predicates的,會路由到uri地址。

這個地方其實可以直接寫路由的地址,比如baidu.com,會直接將請求轉發到baidu。但微服務實例通常有很多,這裏不能直接寫服務ip端口,如果想按註冊中心的服務名來路由,前面要加 lb://, lb://wisdomclass-demo這個配置是路由到服務名爲wisdomclass-demo的服務,並且用http協議的方式。

但是wisdomclass-demo這個項目裏有關於websocket的內容,用的是websocket協議,不是http,所以在routes配置中,寫了多個路由配置,我寫的配置是 以app 和topic開頭的url,用ws協議路由到wisdomclass-demo服務去通信。其餘的請求還是http。因爲第二個第三個路由配置的order更小,所以優先執行這兩個路由規則,最後執行第一個路由規則。

爲什麼是app和topic?因爲我在stomp設置的頻道是他們:

weosocket配置:

package cn.sosuncloud.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

import javax.servlet.http.HttpSession;
import java.util.Map;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic","/q");
        config.setApplicationDestinationPrefixes("/app");
        config.setUserDestinationPrefix("/user");
    }

//    @Override
//    public void registerStompEndpoints(StompEndpointRegistry registry) {
//        registry.addEndpoint("/gs-guide-websocket").withSockJS();
//    }


    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        registry
                .addEndpoint("/gs-guide-websocket")
                .setHandshakeHandler(new DefaultHandshakeHandler() {

                    public boolean beforeHandshake(
                            ServerHttpRequest request,
                            ServerHttpResponse response,
                            WebSocketHandler wsHandler,
                            Map attributes) throws Exception {

                        if (request instanceof ServletServerHttpRequest) {
                            ServletServerHttpRequest servletRequest
                                    = (ServletServerHttpRequest) request;
                            HttpSession session = servletRequest
                                    .getServletRequest().getSession();
                            attributes.put("sessionId", session.getId());
                            HttpHeaders headers = servletRequest.getHeaders();

                        }
                        return true;
                    }}).withSockJS();
    }


    /**
     * 配置客戶端入站通道攔截器
     */
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.setInterceptors(createUserInterceptor());
    }

    /**
     *
     * @Title: createUserInterceptor
     * @Description: 將客戶端渠道攔截器加入spring ioc容器
     * @return
     */
    @Bean
    public UserInterceptor createUserInterceptor() {
        return new UserInterceptor();
    }

}

頻道接受消息和推送:

@Controller
public class GreetingController {

    @Autowired
    SimpMessagingTemplate SMT;

    @MessageMapping(value = "/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws Exception {
        Thread.sleep(1000); // simulated delay
        return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
    }
}

可以看到,只有服務端向客戶端推送消息的協議是ws,也就是app 和topick的url。

其餘建立連接的url  如 /gs-guide-websocket ,和客戶端發送消息的url  /hello 還是http。

這裏stomp建立連接用的是http。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章