SpringCloud集成websocket出现Error: Unexpected server response: 200,服务器将WebSocket连接错误地识别为HTTP请求的问题

这篇具有很好参考价值的文章主要介绍了SpringCloud集成websocket出现Error: Unexpected server response: 200,服务器将WebSocket连接错误地识别为HTTP请求的问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近项目里需要使用到websocket,主要用于前后端实时通信,项目中用到的场景是用户扫码乘车之后司机的设备需要语音提醒,思路是司机在打开乘车二维码时前端根据司机的用户ID发送websocket请求,后端在扫码乘车成功后发送消息,在本地测试一切正常,因为在本地与前端联调时没走网关,直接通过websocket所在服务端口来连接,但是上服务器由于服务端口不能对外暴漏,只能走网关或者通过nginx转发来实现,所以就出现了nginx转发成http请求这种问题。

这是websocket实现类代码:

WebSocketServerConvenientlife
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

//乘客扫码后司机角色登录的设备语音提示
@ServerEndpoint (value = "/convenientlife/websocket/{sessionId}")
@Component
public class WebSocketServerConvenientlife
{

    private static Logger LOGGER = LoggerFactory.getLogger(WebSocketServerConvenientlife.class);

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServerConvenientlife> webSocketSet = new CopyOnWriteArraySet<>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //接收sessionId(默认就是司机账户ID)
    private String sessionId;

    //接收message
    private JSONObject message;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam ("sessionId") String sessionId)
    {
        LOGGER.info("---+++++ convenientlife模块成功连接,sessionId :{}", sessionId);
        this.session = session;
        this.sessionId = sessionId;
        webSocketSet.add(this);
        addOnlineCount();
        LOGGER.info("当前在线连接数为:"+getOnlineCount());
        try
        {
            sendMessage("{}");
        }
        catch (IOException e)
        {
            LOGGER.error("websocket IO异常");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose()
    {
        webSocketSet.remove(this);
        subOnlineCount();
        LOGGER.info("convenientlife模块有一连接关闭!当前在线连接数为:"+getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session)
    {
        JSONObject jsonObject = JSON.parseObject(message);
        if(jsonObject != null && StringUtils.isNotBlank(jsonObject.getString("sid")))
        {
            String sid = jsonObject.getString("sid");
            for(WebSocketServerConvenientlife item : webSocketSet)
            {
                if(sid.equals(item.sessionId))
                {
                    item.message = jsonObject;
                }
            }
        }
    }

    /**
     *
     * @param session 参数
     * @param error 参数
     */
    @OnError
    public void onError(Session session, Throwable error)
    {
        LOGGER.error("convenientlife模块websocke 发生错误:"+error.getMessage());
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException
    {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 群发自定义消息
     * */
    public static synchronized void sendInfo(String message, @PathParam ("sessionId") String sessionId)
    {
        for(WebSocketServerConvenientlife item : webSocketSet)
        {
            try
            {
                //只推送给指定的这个sessionId
                if(sessionId != null && item.sessionId.equals(sessionId))
                {
                    LOGGER.info("推送sessionId: "+sessionId+";推送内容:"+message);
                    item.sendMessage(message);
                }
            }
            catch (IOException e)
            {
                LOGGER.error("sendInfo error: ", e);
            }
        }
    }

    /**
     * session是否存在
     * @param sessionId 参数
     * @return boolean
     */
    public static synchronized boolean existsSesson(@PathParam ("sessionId") String sessionId)
    {
        if(StringUtils.isBlank(sessionId))
        {
            return false;
        }
        for(WebSocketServerConvenientlife item : webSocketSet)
        {
            if(item.sessionId.equals(sessionId))
            {
                return true;
            }
        }
        return false;
    }

    public static synchronized JSONObject getMessage(@PathParam ("sessionId") String sessionId)
    {
        if(StringUtils.isBlank(sessionId))
        {
            return null;
        }
        for(WebSocketServerConvenientlife item : webSocketSet)
        {
            if(item.sessionId.equals(sessionId))
            {
                return item.message;
            }
        }
        return null;
    }

    public static synchronized int getOnlineCount()
    {
        return onlineCount;
    }

    public static synchronized void addOnlineCount()
    {
        WebSocketServerConvenientlife.onlineCount++;
    }

    public static synchronized void subOnlineCount()
    {
        WebSocketServerConvenientlife.onlineCount--;
    }

}

 使用 @ServerEndpoint 注解定义 WebSocket 服务器端的终端点,WebSocket 终端点可以处理来自客户端的连接和消息,并可以向客户端发送消息。

WebSocketConfig类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    
    /** 部署时注释   start**/
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        
        return new ServerEndpointExporter();
    }
    /** 部署时注释  end**/
    
}

这个类是必须要的,配置和初始化 WebSocket 相关的设置和组件,以便在应用程序中启用 WebSocket 功能。

服务器nginx配置如下:

    location /ws {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://ip:6100;
    }

前缀为/ws开头的请求转发到6100端口去,6100是WebSocket所在服务的端口,于是我用postman测试了一下

websocket 200错误,java开发,spring cloud,websocket,服务器,nginx

就出现了WebSocket连接识别成http请求的错误了,看了一下nginx日志,也没发现报错信息,但确实将WebSocket连接识别成http请求转发到服务中去了                                                               

websocket 200错误,java开发,spring cloud,websocket,服务器,nginx

那这就很奇怪了,我明明nginx配置了WebSocket连接转发请求,然后框框一顿查,以为是服务不支持接收WebSocket请求,检查pom文件、配置文件,最后发现需要在nginx配置端口后面加一个接口前缀,改成这样

    location /ws {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://ip:6100/convenientlife;
    }

然后再用postman请求:

websocket 200错误,java开发,spring cloud,websocket,服务器,nginx

连接成功!!!查了一下大概原因:

服务器端应用程序的路径:在更改Nginx配置后,将WebSocket连接的请求代理到http://ip:6100/convenientlife这个路径上。如果你的服务器端应用程序正好在/convenientlife路径下,那么添加了接口前缀后,Nginx将正确地将WebSocket请求转发到正确的路径,从而实现了连接成功。文章来源地址https://www.toymoban.com/news/detail-761924.html

到了这里,关于SpringCloud集成websocket出现Error: Unexpected server response: 200,服务器将WebSocket连接错误地识别为HTTP请求的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • There was an unexpected error (type=Internal Server Error, status=500).

    There was an unexpected error (type=Internal Server Error, status=500). org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: “class path resource [templates/main.html]”) 这个错误原因在于模板上的有些数据异常导致的: 问题描述 在开发springboot的时候,进行modelAndView 视图层

    2024年02月09日
    浏览(52)
  • docker pull 出现错误:Error response from daemon

    [root@CentOSlocalhost /]# docker pull mysql Using default tag: latest Error response from daemon: Get \\\" https://registry-1.docker.io/v2/library/mysql/manifests/sha256:ca114710bb35b862062fd51733a7dba1ba3e93be33e4eede442b0ce15c77b718\\\": read tcp 192.168.32.101:53806-18.215.138.58:443: read: connection reset by peer 解决方法: 解析ip不可用,可以使用

    2024年02月07日
    浏览(44)
  • nacos Error to process server push response

    nacos2.0.3报错: Error to process server push response 解决办法: 排查项目当中有没有直接或间接依赖reflections: 如果有,把版本改成0.9.11,低于0.9.11会有问题。 参考

    2024年02月11日
    浏览(40)
  • 删除Docker容器里面镜像出现:Error response from daemon: conflict: unable ...

    当我们拉取的镜像有问题时,想删除镜像,进行重新拉取时。删除镜像时候发现执行普通的docker rmi [镜像id/镜像名字];时候出现类似于如下的错误: 这是因为:在使用docker删除本地某个镜像时,出现了error报错,根据意思应该是这个镜像有个依赖,需要删除依赖后再删除此镜

    2024年02月11日
    浏览(78)
  • docker 拉取镜像出现 error parsing HTTP 408 response body 错误问题

    在使用 docker 下拉镜像仓库时,出现http解析错误。具体错误log信息如下: error parsing HTTP 408 response body: invalid character ‘’ looking for beginning of value: “ nYour browser didn’t send a complete request in time.nn” 在尝试搜了很多答案后,都没有解决问题,包括如下的解决方案: https://www.

    2024年02月12日
    浏览(74)
  • 问题解决记录=-=[Error response from daemon:Get... http: server gave HTTP response to HTTs client]

    问题: 通过服务器docker登录harbor,发现登陆报错; Error response from daemon:Get “https:.//.../v2/\\\"\\\": http: server gave HTTP response to HTTs client 或者docker登录成功,镜像可以拉下来,但是k8s拉取镜像时候就会报上述错误 原因: harbor默认是https协议的,如果想要通过http协议拉取harbor的镜像需要

    2024年02月09日
    浏览(53)
  • Minio出现Non-XML response from server. Response code: 400, Content-Type: text/xml; ch的解决

    出现这个问题,基本原因的是因为你的minio的配置出现了错误。 这里要注意,要使用的是Minio启动的时候人家给你的端口和用户名以及密码 然后再去配置Minio的client 然后编写代码的时候先尝试访问桶,能访问到桶在进行接下来的步骤 然后发送请求做一个测试即可

    2024年02月11日
    浏览(54)
  • 【异常解决】(二)解决docker报错Error response from daemon: Get... http: server gave HTTP response to HTTPS

    场景:本机个人电脑Windows系统安装了docker客户端,远程Linux服务器部署了镜像仓库,远程仓库可以接收别的服务器的镜像推送,但接收本机电脑镜像时失败(实际为推送失败)。使用docker login XXXX:XX:XX:XX:8081命令登录时,报错 Error response from daemon: Get “https://XXXX:XX:XX:XX:8081/v2

    2024年02月11日
    浏览(66)
  • uniapp 开发微信小程序出现这个 Error in onLoad hook: “SyntaxError: Unexpected end of JSON input“

    原因:由于JSON.parse无法识别某些url中的特殊字符比如等特殊符号造成的。 解决办法: 页面A(JSON.stringify传参) 页面B(JSON.parse接受参数) 接收页面

    2024年02月12日
    浏览(51)
  • docker使用export/import出现错误:Error response from daemon: No command specified

    之前一个使用save和load操作镜像,有次试着使用 export 和 import 来操作。 1,export导出镜像 执行下面的命令后,文件会保存到当前命令执行的目录下。 使用 docker export 命令根据容器的 ID 将镜像导出形成一个文件如下。 docker export 2af444b9693f container_save.tar 2,导入镜像 使用 docke

    2024年04月10日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包