网络编程答疑融合连环tcp/nio/bio/redis/redisson/lettuce/netty/dubbo

news2025/1/20 3:39:36

如果有不对的地方, 欢迎在评论区指正:

  1. bio
    1.1 请求-响应模型. 对于接收方, serverSocket.accept() 为每个请求(连接)安排一个线程
    1.2浪费(阻塞占比大): socket.getInputStream().read()调用是阻塞的, 实际情况对于常见的web应用, 大家都是长连接, 同一时刻, 阻塞在此在线程会不少.
    1.3 风险:线程很容易就上去满了
    1.4 对于.1.3风险, 改良: 可以使用线程池, socket封装为task, 往线程池提交任务. 忙不过来就排到任务队列去
    1.5 对于1.2 浪费: 没办法, 因为面向流的bio读数据的时候是阻塞的, 就算你同一个线程绑定多个连接, 总不能上一个连接read()不到数据的时候, 线程阻塞. 那这个线程上的其他连接都没戏了

  2. nio
    2.1 对于1.2浪费, 我们希望, 1个线程具有监听多个连接的能力, 当多个连接的任意一个具有可读数据的时候. 线程可以获取到数据. 这就是io多路复用
    这里有几点需要说明:
    2.2.1 1个线程监听m个连接(这个m是没有上限的. 你可能有疑惑, 那没有上限, 程序的上限在哪里呢, 这个在后文netty会说. 这个线程池中每个线程基本都均摊了m个不同的连接.) 这个就是多路复用
    2.2.2 我们想要达到这个样子, 我给你分配一块内存, 当连接有数据可读的时候, 内核要自动帮我读到这块内存中去, 这个块内存就叫缓冲区吧. (如果缓冲区读满了还是没有读完连接上传来的此轮数据, 没关系, 方正我线程是自旋去读数据的, 下一个循环依然会有这个连接). 内核完成这个操作就减少了用户态内核态之间的切换与数据拷贝, 程序员编程也简单了. 这个缓冲区就不像bio了, bio没有缓冲区, bio是面向流的 单向的. 我这个buffer可读可写 , 维护两个指针就行了, 时分复用一块内存. 区分为可读区可写区. 这样就可以给写操作用了.
    2.2.3 内核想要完成多路复用, 前提是系统提供的不阻塞读的系统调用. 如果连接没有数据读就立即返回. 当然, 这其中有基于遍历的 有基于事件回调的, epoll poll等实现的多路复用器

  3. 所以总结:
    在这里插入图片描述

  4. 连接是绑定到固定的线程上的好处
    4.1 1个线程监听m个连接, 连接是绑定到固定的线程上. 好处, 站在连接的角度, 这个连接上的数据处理是串行有序的, 是线程安全的, 是可以高效无锁的, 是方便编程的. 这也是netty优雅高效的设计之一.
    进一步展开:
    4.11 tcp是有序的, 只要连接是绑定到固定的线程上, 连接的处理就是串行的. 也就是说, 即便请求方并发的通过同一个连接发了多个请求过来, 这几个请求是不会乱序的.
    4.12 这就解释了为什么 redisson/lettuce 同一个连接上发出的并发请求, 收到的响应依然是和请求同顺序的(redis单线程连接, 哪怕redis高版本的io是多线程的, 只要连接是绑定到固定的io线程上. 所以站在同一个连接上看, redis还是单线程的). redis通讯协议不支持加requestId啥的, 照样能高效(还减少了并发竞争与切换) 把请求和响应对应起来. 而且redis本身很快, 只要没有满命令, lettuce单个连接也是很强的
    4.13 和2.2.1相关, 谈不上局限吧. 拿接收方来说, 1个线程监听m个连接, 并且绑定了这几个连接
    既然io线程绑了多个连接, 自然要快点处理, 所以io线程不要挂上多余耗时的业务处理 不然把绑定上的其他连接rt增加了.
    所以良好的设计是, io线程后面再跟一个业务线程池, io线程负责读写解码心跳等, 线程数量就设定cpu核数或者2倍(因为没有阻塞的情况下, 最大并行就这么多). 业务线程就看服务器性能了, 也和业务耗时有关, dubbo默认200 (为啥不是cpu数, 别闹, 我们还是要提高并发的, 不能要客户干等不是), 而且这种设计也是解耦的, 业务耗时归业务
    4.14 业务线程池拿dubbo举例 如何让请求和响应对应呢?
    业务线程池如果还是连接会绑定在固定线程上的话, 站在连接角度的一切还是串行的. 只不过是在几个线程之间接力串行.
    但是业务线程池往往不会这么做, dubbo不是这样的, 因为每个可读连接都是一份急待处理的业务请求, 需要同优先度的处理, 而不是由于绑在同一个线程上而被迫等待上一个业务请求处理完才能处理. 所以需要一个请求id放在通信协议中. 响应报文也会带, 发送方收到响应后, 按缓存请求id和接下来要处理结果的对象 (一般封装的连接对象上是缓存一个map结构, 请求id为key, 上面挂一个future. 当请求方等待在future.get()的时候, 就可以被唤醒并取到结果了)

4.15 4.13说要加跟一个业务线程池, 那和bio相比强在哪里呢? bio渴望与所有连接数正相关, nio更渴望与同一时间并发的可读连接正相关(bio压根没可读事件等事件, 不阻塞读的话, 没法感知, nio能注册感兴趣的事件). bio是连接数维度的, nio是并发请求数维度的, 还是有一定百分比差距的. 当然如果你的业务就是所有连接都是大报文, 传大对象, 或者高io, 那nio的io线程反而就不行了, 因为nio是想省线程, 按之前说的io线程是cpu数. 不够用. 反而会 增加并发开销, 线程切换, 以及阻塞同线程下绑定的其他连接. 这也就是为啥说netty服务端(比如dubbo , 至于rocketmq要看下才知道)在大报文请求的高并发下, 会有下降的原因. tcp是有序的, 即便是同连接并发的请求, 也一定会等到上一个请求(不管被拆成多个包) 完全被io线程被解析成完整的报文, 丢给业务线程池后才会继续处理下一个请求

  1. tomcat也是nio, 有和不同 (此段尚在研究验证中)
    5.1 tomcat是servlet规范的实现. 虽然也是nio. 但是要为每一个可读的请求连接分配一个线程(不是多个同连接请求能绑定同一个线程).也就是io线程其实就是业务线程(所以springmvc你没有看到什么线程池). 用了线程池也用了nio, 至少不是bio, bio渴望与所有连接数正相关, nio至少能感知到连接的可读事件, 至少是说 这个连接可读了, 我才提交一个任务到线程池去, 执行完就就行. 下一次可读是下一次的事, 不会一个线程专门阻塞给一个线程服务不管他可读或者读完(bio读完还是自旋在哪里) 也就是说bio是连接数维度的, nio是并发请求数维度的.
    5.2 tomcat vs netty 我的理解 (不使用aio情况下, 也不响应式 这些另开一篇)
    5.2.1 tomcat 不会出现一个请求阻碍下一个请求
    5.2.2 netty 更适合被二次开发, 比如服务端 加一个线程池就行了, 扩展性强
    5.2.3 tomcat 是专业web服务器, netty能搞jsp吗, websocket? 如何维护session? 主流web展示层技术兼不兼容? 如何下文件等把这里搞定, 那netty又变成和另一个tomcat了. 专物专用, 都不要贬低. 如果只是http场景不是复杂的情况下, 并且是在小数据的请求上,此时netty优于tomcat, 可以用netty实现http服务器. 因为: https://zhuanlan.zhihu.com/p/433868436

  2. nio是非阻塞吗
    是的, 不是降低阻塞, 是非阻塞, 因为没数据可读时可以立即返回. (返回你可以干点别的事, 然后再去轮询)
    如果你不想轮询, 那得aio了 (这个以后开一篇吧)
    但是要注意, 大报文请求的高并发, 如果一个线程绑定了多个连接, 串行处理下, 有等待问题.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/414656.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝牙技术|苹果获空间音频新专利,AirPods可动态调整声学输出

美国商标和专利局(USPTO)公示的清单显示,苹果在近日获得了一项名为“测定虚拟聆听环境”的新专利。据悉,该技术可以改善用户的聆听体验,增强空间音频的沉浸感,未来有望应用在AirPods上。 这项专利技术可以…

第二章 Linux目录结构

第二章 Linux目录结构linux的文件系统是采用级层式的树状目录结构,在此结构中的最上层是根目录“/”,然后在此目录下再创建其他的 目录。 2)深刻理解 linux 树状文件目录是非常重要的。3)记住一句经典的话:在Linux世界里,一切皆文件(!!)4)示意…

4.12--计算机网络之TCP篇之TCP 协议的缺陷+如何基于 UDP 协议实现可靠传输?--(复习+大总结)---沉下心来(加油呀)

TCP 协议四个方面的缺陷: 1.升级 TCP 的工作很困难; TCP 协议是在内核中实现的,应用程序只能使用不能修改,如果要想升级 TCP 协议,那么只能升级内核。 而升级内核这个工作是很麻烦的事情 2.TCP 建立连接的延迟&#x…

Linux -- 进程间通信

文章目录1. vscode软件下载和使用1.1 下载1.1.1 解决下载慢问题1.1.2 推荐下载链接1.2 vscode是什么1.3 Windows本地vscode使用1.4 远程连接linux1.5 推荐插件2. 进程间通信目的3. 为什么需要通信4. 匿名管道4.1 原理4.2 代码案例4.3 玩一玩(进程池)4.3.1 模型4.3.2 代码5. 命名…

STM32+W5500实现以太网通信

STM32系列32位微控制器基于Arm Cortex-M处理器,旨在为MCU用户提供新的开发自由度。它包括一系列产品,集高性能、实时功能、数字信号处理、低功耗/低电压操作、连接性等特性于一身,同时还保持了集成度高和易于开发的特点。本例采用STM32作为MC…

【开懂C++】命名空间 函数重载 缺省参数

目录一.命名空间二.缺省参数三.函数重载一.命名空间 在编写C语言代码时,当工程较大时,很容易产生变量命名冲突的情况——一般有两种冲突的情况 1.变量名与库中的函数名、关键字冲突。2.工程模块化搭建时不同文件的命名冲突。 而C为了优化这一缺陷&#…

安装Ubuntu系统后的实用工具配置指南

1. 修改软件源 Ubuntu 默认的软件源是境外的,速度上会有些问题,我们可以在Software & Updates(软件和更新)中选择国内的镜像。 一般我们选择清华源或者阿里云源。 2. 安装chorme浏览器 在ubuntu下我比较习惯用火狐浏览器和谷歌浏览器。 谷歌浏览…

vue 自定义指令directive的使用场景

1. 一个指令定义对象可以提供如下几个钩子函数(均为可选) bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。update:只要当前元素不被…

Leetcode.1971 寻找图中是否存在路径

题目链接 Leetcode.1971 寻找图中是否存在路径 easy 题目描述 有一个具有 n 个顶点的 双向 图,其中每个顶点标记从 0 到 n - 1(包含 0 和 n - 1)。图中的边用一个二维整数数组 edges 表示,其中 edges[i] [ui, vi]表示顶点 ui和顶…

关于maxwell

这里写目录标题什么是Maxwell如何使用MaxwellMaxwell是一个mysql二进制binlog日志分析工具,Java语言编写,功能十分强大,可以将日志转换成json并发送到kafka,redis,rabbitmq等中间组件,因为最近在理解怎样在…

QtSqlite加密--QtCipherSqlitePlugin的使用

文章目录QtSqlite加密第一步:环境准备第二步:连接数据库第三步:数据库操作第四步:使用新的可视化工具查看数据库数据QtSqlite加密 上次说了QxOrm的数据库连接、映射和基础的增删改查,但是我们在使用数据库的时候并不希…

期刊论文图片代码复现【由图片还原代码】(OriginMatlab)

👨‍🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…

【数据结构】图解八大排序(上)

文章目录一、排序简介二、直接插入排序三、希尔排序四、直接选择排序五、堆排序六、冒泡排序七、冒泡排序与直接插入排序效率对比一、排序简介 生活中,我们经常能看到排序的应用。例如,我们在网购商品的时候,经常按销量从高到低排序。 那么这…

Linux服务器怎么分区

Linux服务器怎么分区 我是艾西,linux系统除了从业某个行业经常要用到的程序员比较熟悉,对于小白或只会用Windows系统的小伙伴还是会比较难上手的。今天艾西简单的跟大家聊聊linux系统怎么分区,让身为小白的你也能一眼看懂直接上手操作感受程序…

【数据结构】用Java实现七大排序算法

目录 🌷1. 排序的概念及引用 1.1 排序的概念 1.2 衡量指标 1.2 十个排序算法 1.3 十个排序性能对比 🌷2. 冒泡排序 2.1 算法描述 2.2 动图 ⭐️代码优化 🌷3. 选择排序 3.1 算法描述 3.2 动图 3.3 代码 🌷4. 插入排序 4.1 算法描述…

(大数据开发随笔9)Hadoop 3.3.x分布式环境部署——全分布式模式

索引完全分布式模式守护进程布局集群搭建准备总纲配置文件格式化集群启动集群集群控制命令集群启停进程查看启动日志查看集群常见问题案例演示:WordCount完全分布式模式 分布式文件系统中,HDFS相关的守护进程也分布在不同的机器上,如&#x…

cgroups是linux内核中限制、记录、隔离进程组(process groups)所使用的物理资源的机制

容器虚拟化 可以实现应用程序的隔离 直接使用物理机的操作系统可以快速响应用户请求 不占用部署时间 占用少量磁盘空间 缺点∶学习成本增加、操作控制麻烦、网络控制与主机虚拟化有所区别、服务治理难。 微服务架构师需要会多门编程语言,才能治理各种服务 三种…

web路径专题+会话技术

目录自定义快捷键1. 工程路径问题及解决方案1.1 相对路径1.2 相对路径缺点1.3 base标签1.4 作业11.5 作业21.6注意细节1.7 重定向作业1.8 web工程路径优化2. Cookie技术2.1 Cookie简单示意图2.2 Cookie常用方法2.2 Cookie创建2.3 Cookie读取2.3.1 JSESSIONID2.3.2 读取指定Cook…

Linux文件目录操作命令

目录 Linux常用的基础命令 使用技巧 1. ls命令:查看当前目录所有内容 ls 命令的多种使用方法: 注:假如执行乱码,则执行以下两步的代码: 2. cd命令:切换当前工作目录,即进入指定目录 3. …

网络-IP地址(嵌入式学习)

IP地址基本概念IPv4 五类:A B C D E特殊地址子网掩码子网号概念IPv6优势举个栗子基本概念 IP地址是Internet中主机的标识 IP地址(Internet Protocol Address 互联网国际地址)是一种在Internet上的给主机编址的方式,它主要是为互…