当前位置: 首页 > news >正文

WebSocket——推送方案选型

一、前言:为何需要服务端主动推送?

在现代应用中,很多功能都依赖于“消息推送”。比如:

  • 小红点提醒:我们经常在手机应用里看到的一个小红点提示,表示有新的消息或任务需要我们关注。
  • 新消息提醒:在聊天应用中,当有新消息时,服务端需要通知客户端,让用户看到新的内容。
  • 审批流提醒:企业内部审批流程中,一旦某个任务有了新的进展,系统会主动推送通知,提醒相关人员及时处理。

        这些功能听起来非常常见,但它们的实现并不是那么简单。特别是当需要实时或者高效地推送大量数据时,如何选择合适的推送技术就变得至关重要。

为什么需要服务端主动推送?

        在很多应用中,我们并不希望客户端频繁地去向服务器请求数据,这不仅增加了客户端的负担,也浪费了服务器和网络资源。因此,服务端主动推送消息成为了一种更加高效的方式。

        想象一下,你的手机每天都需要向应用的服务器询问:“有没有新消息?有没有新任务?”这种方式就叫做轮询。但轮询会有一些问题:

  1. 频繁请求:客户端需要定时向服务器发送请求,检查是否有新内容。这不仅会浪费大量的网络带宽,也给服务器带来很大的负担。
  2. 延迟问题:即使轮询的间隔很短,客户端依然会有一些延迟,不能做到完全实时。

相比之下,服务端主动推送就解决了这个问题。它的工作原理是:

  • 当服务端有新消息时,主动“推送”到客户端。
  • 客户端只需“监听”服务端的消息,当消息到来时,客户端立刻处理,不再主动请求。

        这就像是你打开了一个“收信箱”,一旦有新信件,信箱会自动通知你,而不是你一直去查“有没有新信件”。这样不仅省去了频繁询问的麻烦,还能让你第一时间获取到最新的消息。

服务端推送的好处:

  1. 提高实时性:因为服务端直接推送消息,用户可以第一时间收到更新,不会有等待或延迟。
  2. 减少无效请求:避免了客户端频繁向服务器发送请求,节省了网络带宽,也减轻了服务器负担。
  3. 降低客户端资源消耗:客户端不再需要频繁检查新消息,减少了 CPU 和电池消耗,特别是在移动端应用中尤为重要。

举个例子:

        想象一下你正在使用一个聊天应用。每当有人给你发新消息时,你希望立刻看到。通过服务端主动推送的方式,服务器会在有新消息时立刻把消息推送到你手机上,而不是让你的手机每隔几秒钟去检查一次服务器是否有新消息。

这就是服务端主动推送的基本思路,它能提高实时性、降低无效请求和资源消耗。

总结:

        服务端主动推送技术,解决了频繁轮询带来的性能问题,使得实时性更强、系统负担更轻。接下来的内容,我们将介绍几种常见的推送技术,帮助你更好地理解如何实现服务端主动推送。

二、常见的推送方案

        在前一部分我们了解了为什么需要服务端主动推送消息,现在我们来介绍几种常见的推送方案。每种方案都有自己的特点和适用场景,了解这些方案可以帮助我们做出最合适的选择。

1. 短轮询

        短轮询是一种最简单的方式,它的原理就是客户端定期向服务器发送请求,询问是否有新消息。如果服务器有新消息,就会返回;如果没有新消息,则返回空。

工作原理

  • 客户端每隔一定时间(比如几秒钟)就向服务器发送一个请求。
  • 服务器收到请求后,检查是否有新消息。如果有,就返回消息;如果没有,就返回空。

适用场景

  • 适合一些对实时性要求不高的应用。
  • 比如:扫码登录、简单的OA系统等,用户不需要即时获取所有更新。

优缺点

  • 优点:实现简单,容易部署。客户端只需要发请求,服务器返回数据即可。
  • 缺点
    • 无效请求:即使没有新消息,客户端也会不断向服务器发送请求,这会浪费大量的网络资源。
    • 服务器压力大:每次请求都要经过网络传输和处理,服务器压力会很大,尤其是用户量多时。

2. 长轮询

长轮询是在短轮询的基础上做了一些改进。和短轮询不同的是,长轮询不会立刻返回空结果,而是让客户端的请求“挂起”一段时间,直到服务器有新消息时再返回。

工作原理

  • 客户端发送请求后,如果服务器没有新消息,就不会马上返回,而是会“挂起”客户端请求,直到有新消息时再返回。
  • 如果请求在一定时间内没有新消息,就会超时,客户端会重新发起请求。

适用场景

  • 适合对实时性要求较高,但又不能使用更复杂的方案的应用。
  • 比如:聊天应用、通知提醒系统等。

优缺点

  • 优点
    • 减少无效请求:相比短轮询,减少了无用请求的开销,因为只有在新消息到来时,服务器才会返回数据。
    • 较低的延迟:相比短轮询,长轮询的响应速度更快,能够提供更好的用户体验。
  • 缺点
    • 服务器压力仍然存在:虽然每次请求不是都返回空,但仍然存在大量的挂起请求,服务器依然需要处理这些挂起的连接。
    • 复杂度较高:服务器需要支持挂起请求、超时处理等额外的功能,增加了系统的复杂度。

3. WebSocket

        WebSocket 是一种更为高效的方案,它允许客户端和服务器建立一个长期保持的连接。通过这个连接,服务器可以在任何时刻主动向客户端发送消息,而不需要客户端频繁请求。

工作原理

  • 客户端和服务器通过一个TCP连接建立双向通信的通道。这个连接是持久的,客户端和服务器可以在这个通道中实时交换数据。
  • 一旦建立连接,客户端不需要再发起请求,服务器可以随时推送消息。

适用场景

  • 适用于需要高实时性、高频率推送的应用。
  • 比如:即时通讯(IM)应用、多人在线游戏、股票行情实时推送等。

优缺点

  • 优点
    • 高效实时性:连接建立后,服务器可以随时向客户端推送消息,延迟非常低。
    • 减少服务器压力:只有一个持久连接,减少了频繁的连接和断开,避免了大量的请求。
    • 资源消耗少:相比轮询方案,WebSocket只需要维护一个连接,客户端和服务器都不需要频繁地交换信息,节省了资源。
  • 缺点
    • 实现复杂:相比轮询方案,WebSocket的实现要复杂得多。需要支持连接管理、心跳检测、连接断开重连等功能。
    • 连接数限制:由于每个客户端都需要保持一个长连接,因此服务器需要处理大量的并发连接,负载会比较重。
    • 不适合所有场景:并不是所有应用都需要实时双向通信,如果只是偶尔推送通知,WebSocket可能显得过于复杂。

4. 方案对比总结

方案优点缺点适用场景
短轮询实现简单,易于部署无效请求多,服务器压力大扫码登录,简单的OA系统等
长轮询较低延迟,减少无效请求服务器压力仍然较大,系统复杂度高聊天应用,通知提醒系统等
WebSocket高效实时性,减少资源消耗,服务器压力小实现复杂,连接数受限,不适合所有场景即时通讯应用,股票实时行情推送等

总结:

  • 如果你的应用对实时性要求不高,而且用户量不大,短轮询可以满足基本需求。
  • 如果你需要更低的延迟和较好的用户体验,但对服务器压力的处理要求不是非常高,长轮询是一个不错的选择。
  • 如果你的应用需要非常高效的实时性和较高的并发连接,且能接受更复杂的实现,WebSocket是最合适的方案。

三、WebSocket 协议实现方案

        在上一部分,我们了解了 WebSocket 是如何高效地实现服务器主动推送消息的。接下来,我们将介绍两种常见的 WebSocket 协议实现方案:TomcatNetty

1. Tomcat 实现 WebSocket

        Tomcat 是一个非常常见的 Java Web 服务器,它提供了对 WebSocket 协议的原生支持。Tomcat 通过在 Java Servlet API 的基础上扩展了 WebSocket 功能,使得开发者能够直接利用 Tomcat 来实现 WebSocket 连接。

工作原理

  • Tomcat 会为每个 WebSocket 客户端创建一个专用的连接,这些连接会一直保持直到客户端主动关闭连接或服务器关闭连接。
  • 客户端连接到服务器后,Tomcat 会处理 WebSocket 协议的握手过程,建立持久的双向通信通道。
  • 在这个连接建立后,服务器可以主动向客户端发送数据,客户端也可以发送数据到服务器。

优缺点

  • 优点
    • 集成简单:Tomcat 本身就支持 WebSocket,所以不需要额外的依赖,配置相对简单。
    • 兼容性好:Tomcat 是一个广泛使用的 Java Web 服务器,许多企业应用和框架都支持 Tomcat,因此可以很容易集成 WebSocket。
  • 缺点
    • 性能瓶颈:Tomcat 使用的是基于线程的方式,每个连接会分配一个线程,这对于大量并发连接的场景来说,可能会产生性能瓶颈。每增加一个连接,就增加了一个线程的开销。
    • 不适合高并发场景:Tomcat 更适合处理相对较少的并发连接,如果你的系统需要处理成千上万的并发连接,可能会面临性能问题。

适用场景

  • 小型到中型 Web 应用,或者对 WebSocket 连接的数量要求不高的场景。

2. Netty 实现 WebSocket

        Netty 是一个基于 NIO(非阻塞 I/O)的网络通信框架,专门用于开发高性能、高并发的网络应用。Netty 相比 Tomcat 更加灵活,特别适用于需要处理大量并发连接的场景。它通过事件驱动和多路复用的机制,能够高效地管理大规模的 WebSocket 连接。

工作原理

  • Netty 使用的是基于事件驱动的架构,通过一个或少数几个线程来处理成千上万的并发连接。它通过 NIO(非阻塞 I/O)技术,减少了线程数量,从而显著提高了服务器的吞吐量和并发处理能力。
  • 当客户端发起 WebSocket 连接时,Netty 会通过 Channel 管理客户端连接,并通过 Pipeline 进行数据的编解码、消息处理等。
  • 一旦连接建立,客户端和服务器之间的数据交换会通过 Netty 提供的 EventLoop 实现高效的事件驱动处理。

优缺点

  • 优点
    • 高性能高并发:由于使用了 NIO 和事件驱动架构,Netty 在处理大量并发连接时具有显著的性能优势。
    • 灵活性强:Netty 提供了丰富的功能,可以方便地自定义协议、消息格式和处理器,非常适合复杂的网络应用。
    • 可扩展性强:通过 Pipeline,Netty 支持灵活的组件扩展,开发者可以根据需求添加前置和后置的处理逻辑,比如心跳检测、数据加密等。
  • 缺点
    • 学习曲线陡峭:Netty 的使用和配置比 Tomcat 更为复杂,尤其是对于不熟悉事件驱动和 NIO 的开发者来说,可能需要一些时间来适应。
    • 开发和调试难度较大:由于 Netty 提供了更多的自由度和配置选项,开发和调试的难度也相对较高。

适用场景

  • 高并发的即时通讯(IM)系统、大规模多人在线游戏、实时数据推送等对性能要求极高的场景。

3. 方案对比总结

方案优点缺点适用场景
Tomcat集成简单,兼容性好,适合中小型应用性能瓶颈,不适合高并发小型到中型 Web 应用,对连接数要求不高的场景
Netty高性能高并发,灵活性强,适用于复杂协议学习曲线陡峭,配置和调试较复杂高并发系统,实时通讯应用,数据推送等高性能场景

总结:

  • 如果你的系统对并发连接数的要求较低,且希望使用现有的 Java Web 容器Tomcat 会是一个简单易用的选择,特别适合中小型应用。
  • 如果你的系统需要处理大量的并发连接,且对性能有严格要求,Netty 是一个更加合适的选择,尽管它的学习和配置会相对复杂。

        在实际选择时,我们需要根据项目的规模和需求来决定使用 Tomcat 还是 Netty。对于大部分小型应用,Tomcat 足够使用,但对于高并发、低延迟的场景,Netty 的优势不可忽视。

四、WebSocket 连接的具体过程

        WebSocket 连接的建立和数据传输是服务端和客户端实现双向实时通信的关键。接下来,我们将详细介绍 WebSocket 连接的具体过程,从 握手数据传输,再到 连接关闭,一步步讲解如何建立和维护 WebSocket 连接。

1. 客户端发起连接(握手请求)

        WebSocket 连接的过程从客户端发起连接开始。客户端通过浏览器、应用或者其他支持 WebSocket 的客户端向服务端发起连接请求。

请求过程

  • 客户端通过 HTTP 协议向服务端发送一个特定的 WebSocket 握手请求,这个请求与普通的 HTTP 请求有些不同,它包含了一些额外的头部信息,来告诉服务端它想要升级协议到 WebSocket。

    • 请求头示例

      GET /chat HTTP/1.1
      Host: example.com
      Upgrade: websocket
      Connection: Upgrade
      Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
      Sec-WebSocket-Version: 13
      
    • 关键字段说明

      • Upgrade: websocket:表示客户端希望从 HTTP 协议切换到 WebSocket 协议。
      • Connection: Upgrade:表示此次请求是一个协议升级请求。
      • Sec-WebSocket-Key:客户端生成的一个随机值,用于进行握手过程的安全验证。
      • Sec-WebSocket-Version:指定 WebSocket 协议版本(版本 13 是最新标准)。

2. 服务端接受连接(握手响应)

        当服务端收到客户端的握手请求后,会检查请求是否合法,确认是否支持 WebSocket 协议。如果支持,服务端会返回一个握手响应,告诉客户端可以建立 WebSocket 连接。

响应过程

  • 服务端会发送一个 HTTP 101 状态码(表示协议切换)来响应客户端的请求,并返回一个带有一些特定字段的响应头。

    • 响应头示例

      HTTP/1.1 101 Switching Protocols
      Upgrade: websocket
      Connection: Upgrade
      Sec-WebSocket-Accept: x3JJHMbDL1EzLkh9K1sdd2+Yo+g=
      
    • 关键字段说明

      • Upgrade: websocket:确认协议切换为 WebSocket。
      • Connection: Upgrade:确认这是一个协议升级请求。
      • Sec-WebSocket-Accept:服务端计算并返回的一个值,是 Sec-WebSocket-Key 字段经过特定算法加密后的结果,用于确保连接的安全性。
    • 如果客户端的请求和服务端的响应符合 WebSocket 协议标准,连接就建立成功,服务端和客户端之间就可以进行双向数据传输了。

3. 数据传输过程

        WebSocket 连接一旦建立,服务端和客户端之间就可以通过这个连接进行 全双工 数据传输。也就是说,客户端和服务端都可以随时向对方发送消息,而不需要等待对方的请求。

数据传输过程

  • WebSocket 连接通过 来传输数据。每一帧可以是文本、二进制数据等内容。文本消息通常使用 UTF-8 编码,二进制消息可以是 BlobArrayBuffer 等格式。

    • 客户端向服务端发送消息: 客户端可以通过 JavaScript 代码使用 WebSocket.send() 方法向服务器发送消息,例如:

      let socket = new WebSocket("ws://example.com/chat");
      socket.onopen = function(event) {socket.send("Hello, Server!");
      };
      
    • 服务端向客户端发送消息: 服务端也可以使用类似的 API(例如在 Netty 或 Tomcat 中的 WebSocket API)来向客户端发送消息:

      // 服务端向客户端发送消息
      session.getBasicRemote().sendText("Hello, Client!");
      
    • 消息格式: WebSocket 消息的格式通常由以下几部分组成:

      • 数据帧头:包含控制信息,如是否是最后一帧消息、消息类型等。
      • 负载数据:实际的数据内容,通常是文本或二进制数据。

4. 维持连接(心跳机制)

        WebSocket 连接在长时间的使用过程中可能会出现 连接中断超时断开 的问题。为了避免这种情况,通常会在客户端和服务端之间加入 心跳机制,定期发送数据包来确保连接的存活。

心跳机制的实现

  • 客户端心跳:客户端可以定时向服务端发送一个小的心跳消息(比如 ping 或者空白数据包),来告知服务端它依然在线。
  • 服务端心跳:服务端也可以定期向客户端发送心跳消息来确认连接的有效性。

例如,在 Netty 中,可以使用 PingFramePongFrame 来实现心跳检测。

5. 连接关闭

当 WebSocket 连接不再需要时,客户端或服务端可以发起 连接关闭 的请求,正常关闭连接。

关闭过程

  • 客户端或服务端发送一个 Close 帧(关闭帧),通知对方连接关闭。
  • 接收方收到关闭帧后,会发送一个确认帧(也是 Close 帧),确认关闭连接。
  • 连接被关闭后,双方都可以释放资源,WebSocket 连接不再可用。

关闭的代码示例

  • 客户端关闭连接

    socket.close();
    
  • 服务端关闭连接

    session.close();
    

6. 连接异常处理

        在实际应用中,WebSocket 连接可能会遇到网络不稳定、服务器故障等情况,这时就需要处理异常。通常,WebSocket 客户端和服务端都可以定义 事件监听器 来捕获连接错误和断开事件。

客户端示例

socket.onerror = function(event) {console.error("WebSocket error observed:", event);
};

服务端示例

@OnError
public void onError(Throwable throwable) {System.err.println("WebSocket error: " + throwable.getMessage());
}

总结:

  • WebSocket 连接的建立过程分为 客户端握手请求服务端握手响应 两部分,一旦建立成功,就可以进行双向的数据传输。
  • 数据通过 进行传输,支持文本和二进制数据。
  • 为了保持连接的稳定性,通常会使用 心跳机制 来维持连接的活跃状态。
  • 连接关闭时,客户端和服务端都会发送关闭帧来正常关闭连接。

通过上述过程,WebSocket 连接能够实现服务端主动向客户端推送消息,从而支持高效的实时通信。

五、总结:WebSocket 方案的优势与应用

        WebSocket 作为一种实现实时通信的技术,具有显著的优势,尤其适用于需要频繁交换数据的应用场景。接下来,我们将总结 WebSocket 方案的优势,以及它在实际中的应用。

1. WebSocket 的优势

(1)实时双向通信

        WebSocket 的最大优势就是 全双工通信,也就是说,客户端和服务端可以随时向对方发送消息,而不需要等待对方的请求。这与传统的 HTTP 请求/响应模式不同,HTTP 是单向的,客户端必须发起请求,服务器才能响应。WebSocket 的实时性使得它非常适合聊天应用、实时通知、在线游戏等需要实时数据交互的场景。

(2)减少网络开销

        与传统的 短轮询长轮询 方法相比,WebSocket 节省了大量的网络带宽和服务器资源。短轮询和长轮询需要客户端频繁地发起请求,即使没有新数据,服务端也需要响应空数据,而 WebSocket 只需要一次连接,双方可以持续交换数据,避免了重复的 HTTP 请求和响应开销。

(3)低延迟

        WebSocket 的连接一旦建立,客户端和服务端可以随时交换数据。因为 WebSocket 使用的是持久连接(也就是 TCP 长连接),数据可以迅速传输,不需要重新建立连接。这使得 WebSocket 在低延迟、高频率的数据传输方面具有显著优势,适合需要快速响应的应用。

(4)支持大规模并发

        WebSocket 在处理大规模并发连接方面比传统的 HTTP 更加高效。传统的 HTTP 每个连接都需要占用一个线程来处理,而 WebSocket 通过使用事件驱动的方式,能够用较少的线程处理更多的连接。例如,基于 Netty 的 WebSocket 服务端,能够支持上万甚至更多的并发连接。

(5)简单的协议

        WebSocket 协议相对简单,不需要复杂的请求和响应格式,数据传输可以使用文本、二进制数据等格式。开发者可以通过简单的 API(如 JavaScript 中的 WebSocket 对象)实现 WebSocket 客户端和服务端的通信,非常易于使用和理解。

2. WebSocket 的应用场景

        WebSocket 因其独特的优势,广泛应用于许多需要实时数据交换的场景。以下是几个典型的应用场景:

(1)即时通讯

        即时通讯应用(如聊天应用、社交平台)需要客户端和服务端之间保持实时双向通信,以便能够及时发送和接收消息。WebSocket 非常适合这类场景,因为它支持全双工通信,可以即时将消息从服务端推送到客户端。

例如:

  • 聊天应用:客户端和服务端之间实时推送消息。
  • 社交平台:用户在线状态更新、消息提醒、好友请求通知等。

(2)在线游戏

        在线多人游戏要求客户端和服务端之间实时同步游戏状态,例如玩家位置、分数、战斗情况等。WebSocket 的低延迟和高效性非常适合用于游戏数据的实时传输。

例如:

  • 即时战斗游戏:玩家之间的实时互动。
  • 虚拟世界:玩家与虚拟世界中的物体进行交互,所有动作即时反馈。

(3)实时数据推送

        一些需要实时更新数据的应用,比如股票交易、体育赛事直播、天气预报等,WebSocket 也能提供有效的解决方案。服务端可以在数据更新时主动推送数据到客户端,而无需客户端频繁请求。

例如:

  • 股票行情:实时显示股票价格的变化。
  • 体育赛事:实时更新比赛的分数和进程。

(4)在线协作

        WebSocket 适用于实时多人协作的应用场景,尤其是文档编辑、设计协作等领域。多个用户可以在同一文档上进行实时编辑,所有操作即时同步到其他用户。

例如:

  • 在线文档编辑:用户可以同时编辑文档,实时看到其他人的修改。
  • 设计协作平台:设计人员实时协作、同步编辑设计稿。

(5)实时监控

        WebSocket 还可用于实时监控系统,帮助管理员即时了解系统状态,如服务器负载、应用性能、日志监控等。

例如:

  • 服务器监控:实时更新服务器健康状况。
  • 应用性能监控:实时展示应用运行数据和性能指标。

3. 总结

        WebSocket 是一种强大而高效的技术,它能够解决传统 HTTP 协议无法实现的实时双向通信问题。相比于轮询机制,WebSocket 更节省带宽和服务器资源,能够支持低延迟和高并发的需求,特别适用于即时通讯、在线游戏、实时数据推送等需要频繁交换数据的场景。

通过 WebSocket,服务端可以主动向客户端推送消息,极大地提高了用户体验,使得实时性强的应用得以顺畅运行。如果你正在开发一个需要即时响应的应用,WebSocket 无疑是一个值得考虑的技术方案。

六、推荐方案:为什么选择 Netty 实现 WebSocket?

        在决定实现 WebSocket 的方案时,我们会遇到多个选择。虽然 Tomcat 也可以支持 WebSocket,但我们推荐使用 Netty 作为 WebSocket 的实现框架。接下来,我们将详细讲解为什么选择 Netty,并通过简单的对比帮助大家理解。

1. Netty 的优势

(1)基于 NIO,支持高并发

        Netty 是基于 NIO(New I/O) 的框架,而 NIO 的最大特点就是通过 事件驱动多路复用 机制,可以在 少量线程 的情况下处理大量的并发连接。这样,它非常适合用来搭建 高并发的 WebSocket 服务

        相比之下,Tomcat 是基于 传统的多线程模型,每个连接都会占用一个独立的线程,线程数量越多,服务器的性能就会越低。当并发连接数增多时,Tomcat 的性能可能会大幅下降,导致响应变慢,甚至崩溃。

总结:Netty 更擅长处理 大量并发连接,而 Tomcat 更适合处理 较少并发连接

(2)单线程处理,节省资源

        在 Netty 中,所有的连接和数据处理通常由一个或少数几个线程来完成。这种方式通过 事件驱动多路复用 使得 Netty 在处理上万甚至更多的连接时能够 节省大量的系统资源。而 Tomcat 则会为每个连接分配一个线程,这样就需要消耗更多的系统资源,限制了它的扩展性。

总结:Netty 的 单线程或少线程 模型非常适合高并发场景,节省资源,而 Tomcat 的线程模型则比较消耗资源。

(3)丰富的功能与高度的灵活性

        Netty 提供了丰富的功能和强大的 扩展性,可以方便地构建自定义的网络协议和处理器。例如,Netty 提供了 Pipeline 机制,允许你定义请求的处理流程,可以非常灵活地处理网络请求、编解码、消息转发等任务。

Tomcat 在这些方面相对较弱,它的功能主要集中在 HTTP 协议和 Web 容器的功能上,定制化程度不如 Netty。

总结:Netty 提供了更高的灵活性,可以根据具体需求定制处理过程,而 Tomcat 的定制化相对较少。

(4)内建的心跳机制与连接管理

        WebSocket 需要维护长连接,因此需要处理 连接的心跳机制,以确保连接正常运行并防止超时断开。Netty 提供了 内建的心跳机制连接状态检查,可以自动检测和管理连接,减少开发者的工作量。

Tomcat 也能支持 WebSocket,但其心跳机制和连接管理需要额外配置和开发,比较繁琐。

总结:Netty 的 心跳机制和连接管理 非常完善,能够减少开发工作量,而 Tomcat 需要手动配置和扩展。

(5)高效的编码和解码处理

        WebSocket 数据传输过程中,通常需要对数据进行编码和解码操作。Netty 提供了强大的 编解码器,可以高效处理各种数据格式,包括文本、二进制数据等。同时,Netty 提供了自定义编解码的接口,可以根据需要灵活处理数据。

而 Tomcat 的 WebSocket 处理器虽然也支持基本的编解码操作,但相比 Netty 更加简化,灵活性和效率相对较低。

总结:Netty 提供了高效、灵活的 编解码功能,可以满足复杂的数据处理需求,而 Tomcat 在这方面稍显不足。

2. 适用场景

(1)高并发应用

        对于需要同时处理大量并发 WebSocket 连接的应用,Netty 无疑是更好的选择。比如 IM 聊天应用、实时数据推送服务等,Netty 可以更高效地处理成千上万的并发连接,保证系统的稳定性和性能。

(2)需要高灵活性和扩展性的应用

        如果你需要在 WebSocket 连接中实现复杂的协议或者需要自定义消息的处理流程,Netty 会提供更高的灵活性。例如,你可以使用 Netty 轻松实现自己需要的编解码规则、业务逻辑等,而 Tomcat 的自定义能力较弱。

(3)低延迟和高性能要求的应用

        如果你的应用需要低延迟、高吞吐量,比如实时在线游戏、金融交易系统等,Netty 的事件驱动和高效的资源管理能够帮助你在高负载下保持较低的延迟和稳定性。

3. 总结:为什么选择 Netty 实现 WebSocket?

        通过以上分析,我们可以得出结论:Netty 更适合大规模并发、高性能和高灵活性要求的应用场景。它通过 NIO 机制、高效的线程管理和强大的扩展性,能够支持更加复杂和高并发的 WebSocket 实现。而 Tomcat 虽然也可以处理 WebSocket,但它在处理大规模连接和自定义协议方面的能力远远不及 Netty。

        如果你的系统需要处理大量实时连接,或者需要更灵活的协议和消息处理,选择 Netty 实现 WebSocket 将是一个更优的方案。

相关文章:

WebSocket——推送方案选型

一、前言:为何需要服务端主动推送? 在现代应用中,很多功能都依赖于“消息推送”。比如: 小红点提醒:我们经常在手机应用里看到的一个小红点提示,表示有新的消息或任务需要我们关注。新消息提醒&#xff1…...

Openresty 安装

1. 依赖包安装: # yum install readline-devel pcre-devel openssl-devel 2. 在系统中添加openresty的仓库: # sudo yum install yum-utils # sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo …...

回归预测 | MATLAB实TCN时间卷积神经网络多输入单输出回归预测

效果一览 基本介绍 回归预测 | MATLAB实TCN时间卷积神经网络多输入单输出回归预测 …………训练集误差指标………… 1.均方差(MSE):166116.6814 2.根均方差(RMSE):407.5741 3.平均绝对误差(MAE):302.5888 4.平均相对…...

TikTok专线服务器助力品牌营销新高度

在这个信息爆炸的时代,短视频平台如雨后春笋般涌现,TikTok便是其中的佼佼者。众多品牌纷纷涌入这个平台,试图借助其强大的用户基础和传播能力来提升知名度。而在这其中,IPIPGO直播专线的出现,为品牌在TikTok上的营销提…...

flutter VoidCallBack ValueChange<T> 的函数定义

在 Flutter 中,VoidCallback 和 ValueChanged<T> 是两种常用的回调函数类型,它们通常用于处理事件或传递数据。下面是它们的详细定义及使用方式。 1. VoidCallback 函数类型 VoidCallback 是一个没有参数也没有返回值的回调函数类型。它通常用于简单的事件处理,比如…...

pyspark连接clickhouse数据库的方式(其它数据库同样适用)

目录 一、背景简记二、pyspark连接clickhouse方式记录三、结语参考学习博文 一、背景简记 实际工作中&#xff0c;大部分所用的数据存储地址都是在数据库中&#xff0c;如我司现在常用的数据库是clickhouse&#xff0c;相关数据的统计分析都在此上操作。如果想用pyspark连接cl…...

当父级元素设置了flex 布局 ,两个子元素都设置了flex :1, 但是当子元素放不下的时候会溢出父元素怎么解决 (css 样式问题)

一、问题 遇到个样式问题&#xff0c;当父级元素设置了flex 布局 &#xff0c;两个子元素都设置了flex :1, 但是当子元素放不下的时候会溢出父元素怎么解决 &#xff08;拖拽浏览器 使页面变小&#xff09; 二、解决方法 .father{min-height: 600px;width: 100%;display: flex…...

软件方法论--课程笔记(整理中)

C1&#xff1a;概览Introduction &#xff08;1&#xff09;软件的4个特性 一致性&#xff08;Conformity&#xff09;&#xff1a;软件必须符合严格的规格和要求&#xff0c;包括与其他组件的接口和环境的连接&#xff0c;避免因为不一致导致无法复用或开发问题。 不可见性…...

从 0 开始实现一个 SpringBoot + Vue 项目

从 0 开始实现一个 SpringBoot Vue 项目 从 0 开始实现一个 SpringBoot Vue 项目 软件和工具创建 SpringBoot 后端项目创建 MySQL 数据库配置文件实现增删改查接口 Model 层mapper 层service 层controller 层测试 实现项目功能接口 代码测试 创建 Vue 前端 安装 Node.js配置…...

怎么修复损坏的U盘?而且不用格式化的方式!

当你插入U盘时&#xff0c;若电脑弹出“需要格式化才能使用”提示&#xff0c;且无法打开或读取其中的数据&#xff0c;说明U盘极有可能已经损坏。除此之外&#xff0c;若电脑在连接U盘后显示以下信息&#xff0c;也可能意味着U盘出现问题&#xff0c;需要修复损坏的U盘&#x…...

使用redis-cli命令实现redis crud操作

项目场景&#xff1a; 线上环境上redis中的key影响数据展示&#xff0c;需要删除。但环境特殊没办法通过 redis客户端工具直连。只能使用redis-cli命令来实现。 操作步骤&#xff1a; 1、确定redis安装的服务器&#xff1b; 2、找到redis的安装目录下 ##找到redis安装目…...

Kibana 控制台中提供语义、向量和混合搜索

作者&#xff1a;来自 Elastic Mark_Laney 想要将常规 Elasticsearch 查询与新的 AI 搜索功能结合起来吗&#xff1f;那么&#xff0c;你不需要连接到某个第三方的大型语言模型&#xff08;LLM&#xff09;吗&#xff1f;不。你可以使用 Elastic 的 ELSER 模型来改进现有搜索&a…...

设计模式-结构型-装饰器模式

装饰器模式&#xff08;Decorator Pattern&#xff09;是结构型设计模式中的一种&#xff0c;它允许你通过将对象封装在一个新的对象中&#xff0c;来动态地添加新的功能&#xff0c;而无需改变原对象的结构。装饰器模式的核心思想是“将功能附加到对象上”&#xff0c;它是一种…...

CAP:Serverless + AI 让应用开发更简单

AI 已被广泛视为推动行业进步的关键力量&#xff0c;其在各行业的落地步伐加快。企业在构建 AI 应用开发过程中经常会面临 AI 技术门槛过高、试错周期过长、GPU 资源昂贵且弹性能力不足、缺乏配套工具、业务与模型的开发运维过于割裂、缺乏定制化能力等挑战&#xff0c;成为企业…...

Redis超详细入门教程(基础篇)

目录 一、什么是Redis 二、安装Redis 1、Windows系统安装 2、Linux系统安装 三、Redis通用命令 四、Redis基本命令 五、五种数据结构类型 5.1、String类型 5.2、List集合类型 5.3、Set集合类型 5.4、Hash集合类型 5.5、Zset有序集合类型 六、总结 一、什么是Redi…...

对话 TDengine 解决方案中心总经理陈肃:构建技术与市场的桥梁

TD 小T导读 他是大数据领域的杰出专家&#xff0c;拥有超过十项一作发明专利&#xff0c;是中国通信行业标准《大数据 消息中间件技术要求与测试方法》的重要编写者&#xff0c;并凭借数据中间件领域的突出成就荣获 2019 年“CJK OSS Award”。他是腾讯云 TVP 专家和 TGO 鲲鹏会…...

Formality:参考设计/实现设计以及顶层设计

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482​​​ Formality存在两个重要的概念&#xff1a;参考设计/实现设计和顶层设计&#xff0c;本文就将对此进行详细阐述。参考设计/实现设计是中两个重要的全局概念&am…...

通过内核模块按fd强制tcp的quickack方法

一、背景 tcp的quickack功能是为了让ack迅速回发&#xff0c;快速响应&#xff0c;减少网络通讯时延&#xff0c;属于一个优化项&#xff0c;但是tcp的quickack是有配额限制的&#xff0c;配置是16个quick&#xff0c;也就是短时间内quickack了16次以后&#xff0c;这个配额为…...

Wi-Fi 7、Wi-Fi 6 与 5G、4G 的全方位对比

随着无线通信技术的飞速发展&#xff0c;Wi-Fi 7、Wi-Fi 6&#xff0c;以及5G、4G 已经成为人们生活和工作中不可或缺的网络技术。无论是家庭网络、高速移动通信&#xff0c;还是工业物联网&#xff0c;这些技术都在发挥各自的作用。那么&#xff0c;它们之间有什么区别&#x…...

【例43.3】 转二进制

目录 描述 输入描述 输出描述 用例输入 1 用例输出 1 来源 类型 知识补充站 代码 C Python3 C 描述 请你把一个整数n转化为二进制并从低位到高位输出。 输入描述 一行&#xff0c;仅含一个正整数 n (1≤n≤109)。 输出描述 从低位到高位输出一个二进制数&a…...

qt vs ios开发应用环境搭建和上架商店的记录

qt 下载链接如下 https://download.qt.io/new_archive/qt/5.14/5.14.2/qt-opensource-mac-x64-5.14.2.dmg 安装选项全勾选就行&#xff0c;这里特别说明下qt5.14.2/qml qt5.14.2对qml支持还算成熟&#xff0c;但很多特性还得qt6才行&#xff0c;这里用qt5.14.2主要是考虑到服…...

安全测评主要标准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 安全测评的主要标准‌包括多个国际和国内的标准&#xff0c;这些标准为信息系统和产品的安全评估提供了基础和指导。 一、安全测评的主要标准 1.1、国际标准 ‌可信计算机系统评估准则&#xff08;TC…...

如何学习数学 | 数学家如何思考

学习数学的关键在哪里&#xff1f; 原创 遇见数学 不少人面对数学都会觉得高深莫测&#xff0c;甚至非常枯燥乏味。 只有当你真正走入它的世界&#xff0c;才会发现里面蕴含着无尽的智慧和美感。要想推开这座数学的大门&#xff0c;需要的不仅仅是背公式&#xff0c;或者做一…...

职场沟通与行为

职场沟通与行为 引言 在职场上&#xff0c;你是否曾遇到过困惑的沟通&#xff1f;是否对同事的行为有过疑虑&#xff1f;这不仅是个别现象&#xff0c;而是我们这个时代工作文化中的普遍问题。许多职场的摩擦&#xff0c;来自沟通不畅或是行为不当。那么&#xff0c;如何才能…...

IIO(Industrial I/O)驱动介绍

文章目录 IIO&#xff08;Industrial I/O&#xff09;驱动是Linux内核中用于工业I/O设备的子系统&#xff0c;主要用于处理传感器数据采集和转换。以下是其关键点&#xff1a; 功能 数据采集&#xff1a;从传感器读取数据。数据处理&#xff1a;对原始数据进行滤波、校准等操作…...

关于vite+vue3+ts项目中env.d.ts 文件详解

env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示&#xff0c;特别是在使用一些特定于 Vite 的功能时&#xff08;如 import.meta.env&#xff09;。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…...

32单片机综合应用案例——物联网(IoT)环境监测站(四)(内附详细代码讲解!!!)

无论你身处何种困境&#xff0c;都要坚持下去&#xff0c;因为勇气和毅力是成功的基石。不要害怕失败&#xff0c;因为失败并不代表终结&#xff0c;而是为了成长和进步。相信自己的能力&#xff0c;相信自己的潜力&#xff0c;相信自己可以克服一切困难。成功需要付出努力和坚…...

【Flink系列】6. Flink中的时间和窗口

6. Flink中的时间和窗口 在批处理统计中&#xff0c;我们可以等待一批数据都到齐后&#xff0c;统一处理。但是在实时处理统计中&#xff0c;我们是来一条就得处理一条&#xff0c;那么我们怎么统计最近一段时间内的数据呢&#xff1f;引入“窗口”。 所谓的“窗口”&#xff…...

代码随想录算法训练营第三十五天-动态规划-01背包(二维)

动规五部曲 dp数组的含义&#xff0c;注意这是一个二维数组。dp[i][j] 第一维度代表“从0到第i个物品&#xff0c;而且包括选或不选的情况&#xff0c;即这一维度代表物品编号第二维度代表代表背包容量合在一起的意思是当背包容量是j时&#xff0c;从0到i个物品中选择任意物品…...

快速开发:用AI构造AI —— 打造属于个人的Copilot(M-聪明AI)

作品简介&#xff1a; 当今快速发展的AI时代&#xff0c;学会使用AI的同时&#xff0c;也可以融入AI&#xff0c;来打造自己的产品&#xff0c;我给我这个取名M-聪明&#xff0c; 是基于VUE 3 Spring Boot -Redis ChatGML RxJava SSE 的AI 服务平台。然后这款工具旨在为用户…...

Elasticsearch容器启动报错:AccessDeniedException[/usr/share/elasticsearch/data/nodes];

AccessDeniedException 表明 Elasticsearch 容器无法访问或写入数据目录 /usr/share/elasticsearch/data/nodes。这是一个权限问题。 问题原因&#xff1a; 1、宿主机目录权限不足&#xff1a;映射到容器的数据目录 /data/es/data 在宿主机上可能没有足够的权限供容器访问。 …...

用公网服务器实现内网穿透

首先需要一个公网服务器 下载frp 搜索github下载到frp&#xff0c;服务端frps/客户端frpc。。下载的时候要注意自己本地内网机的cpu版本和服务端cpu架构 我的电脑是mac M1PRO版本 下载的是&#xff1a;darwinarm64 比如 服务端一般是Linux&#xff08;Intel 64位CPU&#xf…...

Jmeter如何进行多服务器远程测试

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 JMeter是Apache软件基金会的开源项目&#xff0c;主要来做功能和性能测试&#xff0c;用Java编写。 我们一般都会用JMeter在本地进行测试&#xff0c;但是受到单…...

前端实习第二个月小结

时间飞快&#xff0c;第一次实习已经过去两个多月&#xff0c;作一些简单的总结和分享。 注&#xff1a;文章整体会比较轻松&#xff0c;提及的经历、经验仅作参考。 一、关于实习/工作内容 1、工作内容 近期做的是管理后台方面的业务&#xff0c;技术栈&#xff1a;前端re…...

C# 并发和并行的区别--16

目录 并发和并行 一.并发 定义 特点 代码示例 代码解释 二.并行 定义 特点 在C#中的体现 代码示例 代码解释 三.并发和并行的区别 四 .如何在C#中选择并发还是并行 1.考虑任务类型 2.代码示例 3.注意事项 五.总结 并发和并行 在编程领域,并发和并行是两个密切…...

Python编程与在线医疗平台数据挖掘与数据应用交互性研究

一、引言 1.1 研究背景与意义 在互联网技术飞速发展的当下,在线医疗平台如雨后春笋般涌现,为人们的就医方式带来了重大变革。这些平台打破了传统医疗服务在时间和空间上的限制,使患者能够更加便捷地获取医疗资源。据相关报告显示,中国基于互联网的医疗保健行业已进入新的…...

HBase实训:纸币冠字号查询任务

一、实验目的 1. 理解分布式数据存储系统HBase的架构和工作原理。 2. 掌握HBase表的设计原则&#xff0c;能够根据实际业务需求设计合理的表结构。 3. 学习使用HBase Java API进行数据的插入、查询和管理。 4. 实践分布式数据存储系统在大数据环境下的应用&#xff0c;…...

Java 读取 Windows 设备的唯一性标识及定位

在 Windows 系统中&#xff0c;获取设备唯一性标识及定位信息对设备管理、安全监控等场景意义重大。本文介绍 Java 中几种实现方法&#xff0c;如 JNA 库、WMI4Java 库及通过 JNI 结合 Windows API。 1. 使用 JNA 库读取 DEVPKEY_Device_ContainerId 在 Windows 系统中&…...

UE控件学习

ListView&#xff1a; item设置&#xff1a;使能在list设置为Entry类 Grid Panel&#xff1a; 常用作背包&#xff0c;每个格子大小可不相同 WidgetSwitcher&#xff1a; 用于切换页签 Wrap_Box&#xff1a; 自动横向排版子节点&#xff0c;超过一定范围则自动换行…...

1.Spring AI 从入门到实践

​Spring AI 从入门到实践 1.什么是Spring AI 2.使用Spring Boot&Spring AI快速构建AI应用程序 3.ChatClient&Chat Model简化与AI模型的交互 4.Spring AI Prompt:与大模型进行有效沟通 5.结构化输出大模型响应 6.实战:AI聊天机器人 Ben技术站关注Java技术&#x…...

2025年01月蓝桥杯Scratch1月stema选拔赛真题—美丽的图形

美丽的图形 编程实现美丽的图形具体要求: 1)点击绿旗&#xff0c;角色在舞台中心&#xff0c;如图所示&#xff1b; 2)1秒后&#xff0c;绘制一个边长为 140的红色大正方形&#xff0c;线条粗细为 3&#xff0c;正方形的中心为舞台中心&#xff0c;如图所示; 完整题目可点击下…...

FLASK创建下载

html用a标签 <!-- Button to download the image --> <a href"{{ url_for(download_file, filenameimage.png) }}"><button>Download Image</button> </a> 后端&#xff1a;url_for双大括号即是用来插入变量到模板中的语法。也就是绑…...

LDD3学习7--硬件接口I/O端口(以short为例)

1 理论 1.1 基本概念 目前对外设的操作&#xff0c;都是通过寄存器。寄存器的概念&#xff0c;其实就是接口&#xff0c;访问硬件接口&#xff0c;有I/O端口通信和内存映射I/O (Memory-Mapped I/O)&#xff0c;I/O端口通信是比较老的那种&#xff0c;都是老的串口并口设备&am…...

MySQL(高级特性篇) 06 章——索引的数据结构

一、为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构&#xff0c;就好比一本教科书的目录部分&#xff0c;通过目录找到对应文章的页码&#xff0c;便可快速定位到需要的文章。MySQL中也是一样的道理&#xff0c;进行数据查找时&#xff0c;首先查看查询条件…...

【FlutterDart】MVVM(Model-View-ViewModel)架构模式例子-http版本(30 /100)

动图更精彩 MVVM&#xff08;Model-View-ViewModel&#xff09; 特点 Model&#xff1a;负责数据管理和业务逻辑。 View&#xff1a;负责显示数据&#xff0c;通常是一个UI组件。 ViewModel&#xff1a;负责处理用户交互&#xff0c;更新Model&#xff0c;并将数据转换为View可…...

光谱相机的光谱分辨率可以达到多少?

多光谱相机 多光谱相机的光谱分辨率相对较低&#xff0c;波段数一般在 10 到 20 个左右&#xff0c;光谱分辨率通常在几十纳米到几百纳米之间&#xff0c;如常见的多光谱相机光谱分辨率为 100nm 左右。 高光谱相机 一般的高光谱相机光谱分辨率可达 2.5nm 到 10nm 左右&#x…...

.Net8 Avalonia跨平台UI框架——<vlc:VideoView>控件播放海康监控、摄像机视频(Windows / Linux)

一、UI效果 二、新建用户控件&#xff1a;VideoViewControl.axaml 需引用&#xff1a;VideoLAN.LibVLC.Windows包 Linux平台需安装&#xff1a;VLC 和 LibVLC &#xff08;sudo apt-get update、sudo apt-get install vlc libvlccore-dev libvlc-dev&#xff09; .axaml 代码 注…...

【论文阅读】基于空间相关性与Stacking集成学习的风电功率预测方法

文章目录 摘要0. 引言1. 空间相关性分析2. 风电功率预测模型2.1 Stacking 集成策略2.2 基学习器2.2.1 基于机器学习算法的基学习器2.2.2 基于神经网络的基学习器2.2.3 基于粒子群优化算法的超参数优化 2.3 元学习器2.4 基于空间相关性与Stacking集成学习的风电功率预测方法 3 算…...

什么是Spring Boot 应用开发?

一、引言 在当今的软件开发领域&#xff0c;Java 依然占据着重要的地位&#xff0c;而 Spring Boot 作为 Java 生态系统中极具影响力的框架&#xff0c;极大地简化了企业级应用的开发流程&#xff0c;提升了开发效率和应用的可维护性。它基于 Spring 框架构建&#xff0c;通过…...

选择saas 还是源码主要考虑

公司业务规模&#xff1a;小型企业可能会发现SaaS提供的即用型解决方案更符合其需求&#xff0c;而大型企业可能需要源码以实现更高的定制性和控制权。 公司技术专长&#xff1a;缺乏技术团队的企业可能会倾向于使用SaaS&#xff0c;而那些拥有强大IT部门的企业可能更适合管理…...