Gateway整合websocket stomp
之前写过springboot和websocket整合的例子,https://blog.csdn.net/u014203449/article/details/102902078在微服务中,页面与后台服务器的交互一般要通过网关,所以网关是否支持长链接也得调试一把。springcloud中有两个网关组件zuul和gateway。经查阅zuul是不支持长链接的,而gateway支持长链接。并...
之前写过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。
更多推荐
所有评论(0)