欢迎访问Spring Cloud中国社区

《重新定义Spring Cloud实战》由Spring Cloud中国社区倾力打造,基于Spring Cloud的Finchley.RELEASE版本,本书内容宽度足够广、深度足够深,而且立足于生产实践,直接从生产实践出发,包含大量生产实践的配置。欢迎加微信Software_King进群答疑,国内谁在使用Spring Cloud?欢迎登记

Spring Cloud Gateway转发Spring WebSocket

Naah · 6月前 · 8387 ·

在经过了两天的刻苦钻研,在经过了google,stackoverflow,github轮番查找无果,而官方文档又毫无记录的情况下,终于,一个夜里,在肯德基的我调试通过…为了防止大家重复踩相同的坑,所以在这里记录一下,希望遇到同样问题的人不要浪费太多时间。我们在这里模拟一个广播弹幕的websocket。gateway通过eureka注册中心拉取服务进行转发websocket

1.搭建 Spring WebSocket

1.1 pom.xml websocket maven依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-actuator</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-web</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.cloud</groupId>
  11. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-websocket</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-devtools</artifactId>
  20. <optional>true</optional>
  21. </dependency>

1.2 application.yml 配置文件

  1. spring:
  2. application:
  3. name: bullet
  4. server:
  5. port: 5678
  6. eureka:
  7. client:
  8. serviceUrl:
  9. defaultZone: http://localhost:1025/eureka/

1.3 BulletApplication websocket启动程序

  1. @SpringBootApplication
  2. public class BulletApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(BulletApplication.class, args);
  5. }
  6. }

1.4 WebSocketAutoConfig websocket配置类

  1. @Configuration
  2. @EnableWebSocketMessageBroker
  3. public class WebSocketAutoConfig implements WebSocketMessageBrokerConfigurer {
  4. @Override
  5. public void registerStompEndpoints(StompEndpointRegistry registry) {
  6. registry.addEndpoint("/bullet") //开启/bullet端点
  7. .setAllowedOrigins("*") //允许跨域访问
  8. .withSockJS(); //使用sockJS
  9. }
  10. @Override
  11. public void configureMessageBroker(MessageBrokerRegistry registry) {
  12. registry.enableSimpleBroker("/toAll"); //订阅Broker名称
  13. }
  14. }

1.5 BulletMessageVO类

使用lombok的@Getter@Setter注解来自动生成get、set方法

  1. @Getter
  2. @Setter
  3. public class BulletMessageVO {
  4. String username;
  5. String message;
  6. }

1.6 BulletController websocket控制器

  1. @Controller
  2. public class BulletController {
  3. @MessageMapping("/chat")
  4. @SendTo("/toAll/bulletScreen") //SendTo 发送至 Broker 下的指定订阅路径
  5. public String say(BulletMessageVO clientMessage) {
  6. String result=null;
  7. if (clientMessage!=null){
  8. result=clientMessage.getUsername()+":"+clientMessage.getMessage();
  9. }
  10. return result;
  11. }
  12. }

2 搭建 Spring Cloud Gateway

2.1 pom.xml gateway网关maven依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-actuator</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.cloud</groupId>
  7. <artifactId>spring-cloud-starter-gateway</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.cloud</groupId>
  11. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-devtools</artifactId>
  16. <scope>runtime</scope>
  17. </dependency>

2.2 application.yml gateway网关配置文件

  1. spring:
  2. application:
  3. name: gateway
  4. gateway:
  5. routes:
  6. - id: bulletscreen
  7. # 重点!/info必须使用http进行转发,lb代表从注册中心获取服务
  8. uri: lb://bullet
  9. predicates:
  10. # 重点!转发该路径!
  11. - Path=/bullet/info/**
  12. - id: bulletscreen
  13. # 重点!lb:ws://代表从注册中心获取服务,并且转发协议为websocket,这种格式怀疑人生!
  14. uri: lb:ws://bullet
  15. predicates:
  16. # 转发/bullet端点下的所有路径
  17. - Path=/bullet/**
  18. server:
  19. port: 8888
  20. eureka:
  21. client:
  22. serviceUrl:
  23. defaultZone: http://localhost:1025/eureka/

2.3 GatewayApplication gateway启动类

  1. @SpringCloudApplication
  2. public class GatewayApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(GatewayApplication.class, args);
  5. }
  6. }

3 编写html

这个是从网上找来的html代码,可以保存到本地文件,不需要放入服务里面

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>Spring Boot WebSocket+广播式</title>
  6. </head>
  7. <body onload="disconnect()">
  8. <noscript>
  9. <h2 style="color:#ff0000">貌似你的浏览器不支持websocket</h2>
  10. </noscript>
  11. <div>
  12. <div>
  13. <button id="connect" onclick="connect()">连接</button>
  14. <button id="disconnect" onclick="disconnect();">断开连接</button>
  15. </div>
  16. <div id="conversationDiv">
  17. <label>输入你的名字</label> <input type="text" id="name" />
  18. <br>
  19. <label>输入消息</label> <input type="text" id="messgae" />
  20. <button id="send" onclick="send();">发送</button>
  21. <p id="response"></p>
  22. </div>
  23. </div>
  24. <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
  25. <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
  26. <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
  27. <script type="text/javascript">
  28. var stompClient = null;
  29. //gateway网关的地址
  30. var host="http://127.0.0.1:8888";
  31. function setConnected(connected) {
  32. document.getElementById('connect').disabled = connected;
  33. document.getElementById('disconnect').disabled = !connected;
  34. document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
  35. $('#response').html();
  36. }
  37. function connect() {
  38. //地址+端点路径,构建websocket链接地址
  39. var socket = new SockJS(host+'/bullet');
  40. stompClient = Stomp.over(socket);
  41. stompClient.connect({}, function(frame) {
  42. setConnected(true);
  43. console.log('Connected:' + frame);
  44. //监听的路径以及回调
  45. stompClient.subscribe('/toAll/bulletScreen', function(response) {
  46. showResponse(response.body);
  47. });
  48. });
  49. }
  50. function disconnect() {
  51. if (stompClient != null) {
  52. stompClient.disconnect();
  53. }
  54. setConnected(false);
  55. console.log("Disconnected");
  56. }
  57. function send() {
  58. var name = $('#name').val();
  59. var message = $('#messgae').val();
  60. //发送消息的路径
  61. stompClient.send("/chat", {}, JSON.stringify({username:name,message:message}));
  62. }
  63. function showResponse(message) {
  64. var response = $('#response');
  65. response.html(message);
  66. }
  67. </script>
  68. </body>
  69. </html>

4 启动程序

  1. 启动Eureka 服务端,开启注册中心
  2. 启动Bullet WebSocket程序
  3. 启动GateWay网关

5 测试程序

  1. 开启多个html页面,并打开控制台

  2. 在多个页面中点击连接按钮,观察控制台是否连接成功

  1. 输入名字和消息,观察是否成功进行广播

6 源码

https://github.com/naah69/SpringCloud-Gateway-WebSocket-Demo