Incompatibile SockJS! Main site uses:.... sockjs报错
先上图:
sockjs stomp springboot-websocket
公司的项目,经测试,直连没有问题,但只要放到服务器上,除了第一次连接,用户只要刷新页面,触发重连就开始报错。
nginx的socket已经配置过了,
在前端报错的同时,后端也会报断开连接(不知道是不是心跳包报的错)
错误信息如下:
因为socket和项目是同端口,所以没有办法远程调试。。。
下面是我的配置信息
nginx:
nginx.conf:
user nginx;worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
include /etc/nginx/conf.d/default/default.conf; #先去加载 default.conf 保证直接内网访问ip时 映射到default.conf内
include /etc/nginx/conf.d/*.conf;
}
xxx.xxxx.xxx.conf:
server {listen 80;
server_name xxx.xxxx.xxx;
location / {
#add_header 'Access-Control-Allow-Origin' '*';
proxy_http_version 1.1;
proxy_pass http://192.168.1.23:27081;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-Ip $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
}
java
@Configuration@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Autowired
TokenStore tokenStore;
public static final String Topic = "ws-topic";
public static final String Queue = "ws-queue";
public static final String HandUrl = "/endpoint";
private static long HEART_BEAT = 5000;
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//注册STOMP的endpoint,使用SockJS
registry.addEndpoint(HandUrl)
.setAllowedOrigins("*")
.addInterceptors(new ConnectionInterceptor())
.withSockJS()
.setClientLibraryUrl("https://cdn.jsdelivr.net/sockjs/1.0.0/sockjs.min.js") // 无效
.setMessageCodec(new FastjsonSockJsMessageCodec());//使用fastjson序列化
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//心跳任务
ThreadPoolTaskScheduler te = new ThreadPoolTaskScheduler();
te.setPoolSize(1);
te.setThreadNamePrefix("wss-heartbeat-thread-");
te.initialize();
//注册消息代理地址
registry.enableSimpleBroker(String.format("/%s/", Topic), String.format("/%s/", Queue))
.setHeartbeatValue(new long[]{HEART_BEAT, HEART_BEAT})
.setTaskScheduler(te);
registry.setApplicationDestinationPrefixes("/ws/ws-bmw"); // 广播消息订阅前缀
registry.setUserDestinationPrefix("/ws/ws-user"); // 点对点消息订阅前缀
// registry.setPreservePublishOrder(true); // 保证推送顺序,但会增加性能开销
}
// 拦截替换 Principal
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(@NotNull Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (accessor==null) throw new BadCredentialsException("未授权");
// 判断是否断开连接
//1、判断是否首次连接
if (StompCommand.CONNECT.equals(accessor.getCommand())){
//2、拿到token,获取授权信息
List<String> authorization = accessor.getNativeHeader("Authorization");
if (authorization==null || authorization.size()==0) throw new BadCredentialsException("未授权");
String token = authorization.stream().findFirst().orElse(null);
if (StringUtils.isEmpty(token)) throw new BadCredentialsException("未授权");
OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token);
if (oAuth2Authentication==null) throw new BadCredentialsException("未授权");
UserDetails userDetails = (UserDetails)oAuth2Authentication.getUserAuthentication().getPrincipal();
if (userDetails==null) throw new BadCredentialsException("未授权");
SocketUserInfo socketUserInfo = new SocketUserInfo();
BeanUtils.copyProperties(userDetails, socketUserInfo);
accessor.setUser(socketUserInfo);
return message;
}
//不是首次连接,已经登陆成功
return message;
}
});
}
}
Vue:
socket.js:
import SockJS from 'sockjs-client';
import Stomp from 'stompjs';
import { getToken } from "./util";
import config from '@/config/config'
const baseURL = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.pro;
class Socket {
constructor(baseUrl = baseURL){
this.stompClient = {};
this.baseUrl = baseUrl//baseUrl;
this.tryCount = 10; //重连尝试次数, 小于1为不重连
this.tryDuration = 1000; //重连时间间隔 单位ms
this.handUrl = "/endpoint"; // 握手连接
};
handler(data){}; // 该方法在组件内被重写
connectionError(err, userId){
console.error("握手出错", err);
this.tryOpen(userId);
}
connection(userId) {
// 发起连接
this.stompClient.connect(this.getHeaders(), () => { this.connectionSuccess(userId); } , err =>{ this.connectionError(err, userId); });
};
tryOpen(userId, tempCount = this.tryCount) {
let tryTask = (tempCount)=>{
if(tempCount<1) return;
if(!this.stompClient || this.stompClient=={} || !this.stompClient.connected ) {
console.warn(`尝试重连: ${this.baseUrl}${this.handUrl}`);
this.connection(userId);
setTimeout(()=>{
tryTask(tempCount-1);
}, this.tryDuration);
}
}
tryTask(tempCount);
};
disconnect() {
if (this.stompClient) {
this.stompClient.disconnect();
}
};
init(userId){
if(!userId) return;
// 建立连接对象
let socket = new SockJS(`${this.baseUrl}${this.handUrl}`);
// 获取STOMP子协议的客户端对象
this.stompClient = Stomp.over(socket);
// 日志
this.stompClient.debug = process.env.NODE_ENV === 'development' ? str=>{
console.log(str)
}: str=>{};
// 心跳包
this.stompClient.heartbeat.outgoing = 10000; // 非负整数 发送心跳的间隔(PING) 单位ms 0表示不发送
this.stompClient.heartbeat.incoming = 10000; // 非负整数 接收心跳的最小时间间隔(PONG) 单位ms 0表示不想接收
this.stompClient.ws.onclose = () => {
this.tryOpen(userId);
}
this.stompClient.ws.onerror = () => {
this.tryOpen(userId);
}
console.log(this.stompClient.ws)
this.connection(userId);
};
// 连接成功
connectionSuccess(userId){
//订阅 点对点接口
this.stompClient.subscribe('/ws/ws-user/ws-queue/getResponse', msg => {
this.handler(msg); //处理消息
}, this.getHeaders());
this.stompClient.send(`/ws/ws-bmw/online`, this.getHeaders(), JSON.stringify({id:userId}))
// this.stompClient.send("/ws-bmw/ws-user/receive",
// headers,
// JSON.stringify({a:"123"}),
// ) //用户加入接口
}
getHeaders(){
return {
Authorization: getToken()
}
}
destroyed () {
this.disconnect();
}
}
export default new Socket(baseURL)
服务器环境
弄这个东西弄了一周了,请教一个解决办法,谢谢🙏
回答
兼容性问题
以上是 Incompatibile SockJS! Main site uses:.... sockjs报错 的全部内容, 来源链接: utcz.com/a/23619.html