`
baishancloud
  • 浏览: 6976 次
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

如何解决WebSocket Server返回数据不一致

阅读更多

作者简介:

花名“卡库”,白山云科技系统开发工程师

 

API开发与管理老鲜肉,丰富的产品开发与运维经验,先后就职于搜狐、新浪等知名互联网公司,曾参与新浪云SAE平台CC防火墙项目,为数十万用户提供安全防护,保证SAE平台性能稳定;2016年入职白山,就此成为酒仙桥地区最大酒窝的系统开发工程师。

 

针对实时Web应用(如:实时通信、股票基金应用、体育实况更新、多玩家游戏等场景),传统Web中为了实时获取Server端的数据,通常是Client端定期发送HTTP请求,Server端进行响应并返回数据。由于Client定期向Server发送请求,当Server端没有数据更新时,Client仍旧发送请求,这造成了带宽的浪费以及Server端CPU的占用。

 

为解决上述问题,越来越多企业在思考如何解决长连接问题,WebSocket是较为常用的方法之一。WebSocket通过第一个 HTTP request 建立 TCP 连接,后续数据交换都无需再发送 HTTP request,创建了一个真正的长连接。同时WebSocket 还是一个双通道的连接,可以实现在同一个 TCP 连接上收发信息。

 

 

白山云聚合平台也融入了WebSocket,可以为用户提供WebSocket协议到HTTP协议的转换功能,让用户的Client以长连接WebSocket协议的方式连接到云聚合平台,云聚合只需一个HTTP连接即可连接到企业后端,大幅降低后端压力的同时,更免去了用户服务器端适配WebSocket协议的问题。我们在研发测试过程中遇到了一个有意思的问题,这或许是很多开发者都曾遇到过的:使用不同的WebSocket客户端和WebSocket Server通信,WebSocket Server返回数据不一致。

 

一、问题场景

1.不同客户端访问

 

(1)python通过WebSocket客户端和WebSocket Server ws://2abe356fc.bsclink.com/交互,输出正常;



 (python 客户端输出内容)

 

 

(2)Chrome浏览器加载ws.html页面之后,页面中的js调用浏览器自带的WebSocket  Client与WebSocket Server ws://2abe356fc.bsclink.com/交互,输出ERROR;



 (Chrome浏览器输出内容)

 

 

(3)Safari浏览器加载ws.html页面之后,页面中的js调用浏览器自带的WebSocket Client和WebSocket Server ws://2abe356fc.bsclink.com/交互,输出正常;



 (Safari浏览器输出内容)

 

2.浏览器请求流程图

 

以下是浏览器通过WebSocket协议向服务器请求的流程:



 (浏览器请求流程图)

 

二、问题分析

只有Chrome与Websocket Server间的通信发生异常,判断ERROR很可能是由Chrome浏览器问题导致的,基于此来分析问题产生的具体原因。

 

1. 通过浏览器控制台查看报错相关信息:



 

如上图下方所示,WebSocket协议decode a text frame在转化为uft-8编码时失败。

 

 

 

 

 

由于WebSocket Server向Client返回数据时,使用text frame方式,于是我们开始排查WebSocket Server返回数据导致decode失败的原因。

 

 

2. 打印WebSocket Server日志,查看返回内容

 

通过日志,观察到longloop传送给WebSocket Server的内容与WebSocket Server输出到Client的内容一致,均为乱码。基于此我们可以确定WebSocket Server不存在异常情况,于是我们需要确定longloop是否存在异常。

 

3. 通过longloop抓包查看backend返回内容

 

可以通过TCPDUMP抓包来判定longloop是否存在问题。

 


 

(backend返回到longloop的数据)



 (longloop返回到WebSocket Server的数据)

 

通过对比以上两组数据,可以得出如下结论:

经过longloop后,真实返回给Client的数据并未发生变化。

(1)backend的返回数据被gzip压缩;

(2)压缩的响应数据被发送至WebSocket Server;

(3)最终由WebSocket Server发送到WebSocket客户端。

 

4. backend返回的数据为什么被压缩了?

 

首先,backend端必须开启gzip压缩,并支持对此返回的数据类型的gzip压缩,才能返回压缩后的响应数据;

其次,客户端要明确声明能接收gzip压缩的响应数据,backend端才能够返回gzip压缩过的数据。

 

经确认,backend server上的配置开启了gzip压缩功能,并对content-type为text/html的数据支持gzip压缩。

可以判断问题有可能出现在client环节:

Client没有要求返回压缩数据,但是backend端返回了压缩数据;

通过不同浏览器访问,返回不同数据,可以判定不是backend端的问题。

Client主动要求backend端返回被压缩的数据;

 

只有Chrome浏览器返回了gzip压缩数据,可以推断可能是因为Chrome请求backend端时,在request header中包含了可以接收gzip压缩数据的header,导致backend端返回了gzip压缩数据。

 

5. 抓包对比Chrome和Safari请求头信息

 

Chrome相关信息:

(1)Chrome浏览器请求ws.html静态文件的请求头中带有Accept-Encoding:


 

(2)Chrome浏览器将ws.html加载到本地后,ws.html文件中的js WebSocket 客户端向WebSocket Server发送请求的请求头中带有Accept-Encoding:



 

(3)Chrome浏览器的请求发送到longloop之后,longloop到backend的请求头中带有Accept-Encoding:



 

Safari相关信息

(1)Safari浏览器请求ws.html静态文件的请求头中带有Accept-Encoding:



 

 

(2)Safari浏览器将ws.html加载到本地后,ws.html文件中的js WebSocket 客户端向WebSocket Server发送请求的请求头中未带有Accept-Encoding:

 

 

(3)Safari浏览器的请求发送到longloop之后,longloop到backend的请求头中未带有Accept-Encoding:


 

通过对比ChromeSafari相关请求数据,我们可以判断出WebSocket Server返回数据不一致的原因如下:

Chrome,Safari浏览器发送请求时,为了提高网络传输效率、减少网络带宽占用,默认自带gzip压缩支持,两种浏览器加载ws.html时均无异常。但当js调用Chrome浏览器WebSocket 客户端向WebSocket Server端发送请求时,在请求头Accept-Encoding中添加了对gzip的支持,backend收到HTTP请求后,认为客户端能够对gzip压缩的响应数据进行解压缩,从而backend返回了gzip压缩过的响应数据,而WebSocket客户端接收到gzip压缩的数据后,不支持gzip数据解压缩,最终导致了decode出错。

而js调用Safari浏览器WebSocket客户端向WebSocket Server端发送请求时,请求头未带有Accept-Encoding,backend收到http请求后,不会返回被gzip压缩的响应数据,从而WebSocket客户端正常解析访问正常。

 

三、解决办法

为解决上述问题,我们需要在longloop这一层进行判断:如果user agent为Chrome浏览器,则需要去掉request header中的Accept-Encoding这个header,明确告知服务器端不接受gzip压缩过的数据,这样服务器端就不会返回gzip压缩过的数据,Chrome浏览器即可正常访问。

 

  • 大小: 83.7 KB
  • 大小: 63.1 KB
  • 大小: 52.2 KB
  • 大小: 129.4 KB
  • 大小: 218.5 KB
  • 大小: 222.6 KB
  • 大小: 182.6 KB
  • 大小: 205.4 KB
  • 大小: 203.1 KB
  • 大小: 177.3 KB
  • 大小: 205.4 KB
  • 大小: 173.4 KB
  • 大小: 178.2 KB
分享到:
评论

相关推荐

    js跨域解决方案

    8. **Server-Sent Events(SSE)**:与WebSocket类似,SSE允许服务器向客户端推送数据,但它是单向的。服务器通过`Content-Type: text/event-stream`响应头告知浏览器这是一个SSE流,然后可以连续发送事件数据。 理解...

    swoole和websocket简单聊天室开发

    swoole_lock用于在多线程环境下,对共享资源进行加锁操作,保证数据的一致性。而swoole_websocket_server则允许我们创建支持WebSocket协议的服务器。 开发聊天室时,通常需要一个配置文件来存储可配置的参数和变量...

    前端开源库-apollo-datasource

    Apollo是GraphQL客户端解决方案的代表,它旨在帮助开发者高效地处理API数据,尤其是在复杂的应用场景下。Apollo-datasource是这个生态中的一个关键组件,它扩展了数据源的概念,使得前端应用可以更加灵活地管理和...

    mockserver-client-2.10.zip

    5. **多协议支持**:除了HTTP,MockServer还可以处理HTTPS和WebSocket请求。 而gprof和groovygprof的使用步骤大致如下: 1. **编译带Profiling的程序**:在编译C/C++或Groovy程序时,启用特定的编译标志,使程序...

    解决跨域问题方案实例

    其次,“跨域”意味着当请求的URL与当前页面URL的域名、端口或协议不一致时,浏览器会认为这是跨域请求。例如,一个在www.example.com上的网页试图通过Ajax请求获取www.anotherexample.com的数据,就会触发跨域问题...

    用Swift写服务端 — Perfect框架学习

    Perfect的设计目标是让开发者能够充分利用Swift的性能和现代语法特性,同时提供与客户端开发一致的体验。 在开始学习Perfect框架之前,你需要确保已经安装了Swift编译器。Perfect框架兼容最新的Swift版本,因此保持...

    ajaxpush服务器推

    在这种模式下,客户端发送Ajax请求后,服务器不会立即响应,而是保持连接打开状态,直到有新的数据或者超时才会返回。这样可以显著减少无效的网络通信,但同时也增加了服务器的连接管理成本。 ### 3. 服务器发送...

    基于PHP的佳蓝即时通讯系统PHP开源版源码.zip

    MySQL或MongoDB等数据库可能被用于存储这些数据,需要考虑高效查询和数据一致性。 6. **安全与隐私**: 开源项目需要注意安全性和用户隐私保护。在PHP源码中,应确保数据传输加密(如HTTPS)、密码安全存储(哈希加...

    The-client-and-server.zip_The Client

    在IT行业中,客户端-服务器(Client-Server)架构是一种常见的通信模式,广泛应用于各种网络应用程序,包括即时通讯软件如QQ。本压缩包文件"QQ客户端和服务器端.zip_The Client"可能包含QQ客户端和服务器端的源代码...

    ServerAndPartOfClient

    例如,BDSServer可能是一个分布式数据库服务,负责处理客户端对数据的存取操作,保证数据的安全性和一致性。 客户端则是用户直接交互的设备或程序,它向服务器发送请求并接收服务器返回的结果。在这个场景中,`...

    一品红商业网站+聊天室

    这个解决方案基于JSP(Java Server Pages)技术,搭配SQL数据库,旨在提供稳定、高效且用户友好的在线服务。 首先,JSP是Java平台上的动态网页开发技术,它允许开发者将业务逻辑和页面展示分离,使得网页更新更加...

    查看同步的服务器页面

    同步是指在多个设备或系统之间保持数据一致性的过程,确保所有参与者都能访问到最新、最准确的信息。下面我们将深入探讨这个主题,了解其背后的原理和实现方法。 首先,服务器页面通常指的是Web服务器上运行的动态...

    design_server:server_client

    状态管理工具如Redux或Vuex在前端应用中用于维护和协调全局状态,确保数据的一致性。 7. **安全性**:在JavaScript的服务器-客户端通信中,安全性是一个关键问题。这包括防止跨站脚本攻击(XSS)、跨站请求伪造...

    jsp毕业设计——jsp+sql即时通讯工具(系统+论文).zip

    为了实现实时性,可能采用了WebSocket或AJAX技术,WebSocket提供双向通信,而AJAX可以在不刷新整个页面的情况下更新部分网页内容。 四、关键功能实现 1. 用户注册与登录:用户信息存储在数据库中,注册时验证...

    模拟QQ聊天工具(计算机网络大实验)

    学生需要学习如何设计数据库结构,编写SQL语句来操作数据,同时考虑到数据的安全性和一致性。 在实现过程中,可能涉及的技术还包括: 1. **多线程编程**:为了处理并发的用户请求,服务器端通常需要使用多线程或多...

    chatterbox-server:chatterbox 聊天应用程序的服务器

    在实际部署中,Chatterbox-server 可能会利用 Docker 容器化技术,确保软件在不同环境下的可移植性和一致性。Docker 配合 Docker Compose 可以轻松管理和部署包含多个服务(如数据库、服务器等)的应用。 综上所述...

    改进的支持中文的AJAX聊天室(ChatRoom)

    8. **实时通信**:如果聊天室需要实时更新,可能需要用到WebSocket或Server-Sent Events (SSE)等技术,提供双向通信能力。 9. **用户身份验证**:为保护聊天室不被未授权用户滥用,应包含用户登录系统,确保只有已...

    高仿QQ(客户端,服务端,数据库)

    1. SQL Server:C#与SQL Server的集成非常紧密,使用ADO.NET库可以方便地进行数据操作。 2. 数据库设计:合理设计用户表、聊天记录表、联系人关系表等,确保数据的一致性和完整性。 3. ORM框架:可能采用Entity ...

    Javascript 跨域访问解决方案

    `这样的JavaScript代码,域A的页面可以定义一个与返回函数名一致的回调函数来处理数据。 3. **CORS(Cross-Origin Resource Sharing)**: CORS是一种现代浏览器支持的跨域访问机制,它允许服务器指定哪些源可以...

    网站在线客服系统(Jsp+MySql)

    【标题】"网站在线客服系统(Jsp+MySql)"是一个基于Java Web技术构建的开源客服解决方案,它结合了JSP(JavaServer Pages)和MySQL数据库,用于实现网站上的实时交流功能。这个系统允许访客与客服人员进行实时对话,...

Global site tag (gtag.js) - Google Analytics