惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

蛮荆

如何获取更多的免费服务器 Kubernetes 调度器队列 - 设计与实现 Kubernetes 调度器 - 核心流程 Kubernetes Networking Model & CNI Kubernetes 控制器管理总结 Kubernetes CronJob 设计与实现 Kubernetes Job 设计与实现 Kubernetes HPA 设计与实现 Kubernetes Deployment 滚动更新实现原理 Kubernetes GC 设计与实现 Kubernetes Pod 驱逐 - 设计与实现 Kubernetes Daemonset 设计与实现 Kubernetes ReplicaSet 设计与实现 Kubernetes EndPoint 设计与实现 Kubernetes Informer 设计与实现 降本增效之应用优化 (三) 日志存储与检索 Kubernetes Pod 设计与实现 - 创建流程 Kubernetes 探针设计与实现 Unix 编程艺术名句摘录 Kubernetes - CRI 概述 Golang 编译速度为什么这么快? Kubernetes Pod 设计与实现 - Pause 容器 Kubernetes - kube-proxy 代理模式工程优化 Kubernetes 应用最佳实践 - 优雅关闭长连接 Kubernetes Service 类型和会话亲和性 Kubernetes 为什么需要 Ingress Kubernetes 架构 - 控制平面和数据平面 降本增效之应用优化 (二) 大报表 Go 语言如何获取 CPU 利用率 降本增效之应用优化 (一) Redis 业务规则引擎演变过程简述 微服务中的熔断算法 漏桶算法和令牌桶算法 jsonparser 为什么比标准库的 encoding/json 快 10 倍 ? zap 高性能设计与实现 HTTP Router 算法演进 布谷鸟过滤器 fastcache 高性能设计与实现 Web 常见的三个安全问题 ants Code Reading 布谷鸟过滤器 Go 线程安全 map 方案选型 布隆过滤器 死锁、活锁、饥饿、自旋锁 sync.Pool Code Reading Go 内存管理概述 Go netpoll Code Reading goroutine 泄漏与检测 time/Timer Code Reading GMP Scheduler Code Reading Go channel 的 15 条规则和底层实现 为什么 Linux “一切皆文件” context.Context Code Reading runtime/HACKING.md Goland 最佳实践 互联网开发与金庸武学 为什么 Redis 6.0 引入多线程模型? Kubernetes 应用最佳实践 - 金丝雀发布 容器中如何正确配置 GOMAXPROCS ? singleflight Code Reading sync.Map Code Reading sync.Cond Code Reading sync.WaitGroup Code Reading sync.RWMutex Code Reading sync.Mutex Code Reading sync.Once Code Reading Go 无锁编程 sync/atomic Code Reading goroutine 交替打印奇偶数 GODEBUG Go 并发模式 Go 汇编 UUID 通用技术选型 Kubernetes 应用最佳实践 - 水平自动伸缩 Go 高性能 Tips fasthttp 为什么比标准库 net/http 快 10 倍 ? 技术文章配图指南 ChatGPT 初体验 Docker 网络原理概览 iptables 的五表五链 Kubernetes 应用最佳实践 - 亲和性和污点容忍度 Go 的反射与三大定律 Docker 官方提供的最佳实践 Go 语言内置的设计模式 HTTP1 到 HTTP3 的工程优化 Kubernetes 应用最佳实践 - Sidecar 模式 Kubernetes 应用最佳实践 - init 容器和钩子函数 为什么 recover 必须在 defer 中调用? 为什么 defer 的执行顺序和注册顺序不同? Go map 设计与实现 Go 切片扩容底层实现 Go 语言中的零拷贝 Go Delve 云原生和边缘计算简介 Kubernetes Pod 服务质量等级 Kubernetes 应用最佳实践 - 探针 Kubernetes 应用最佳实践 - 资源请求和限制 CDN 原理 Kubernetes 应用最佳实践 - 开篇 缓存策略和模式
网络编程框架的作用和价值
2022-10-25 · via 蛮荆

网络编程框架的作用和价值

2022-10-25 计算机网络 网络编程

问题

既然 Linux 提供了 epoll 这样的 I/O 多路复用机制,接近内核且高性能,为什么开发者不直接使用 epoll 进行编程?而是在应用层折腾出了类似 Netty (Java), gnet (Golang) 这样的网络编程框架呢?

毕竟,每多一层封装,系统的整体性能就会有 (主要是数据复制带来的) 损耗。

或者换个说法: 网络编程框架的作用和价值体现在哪里?

这个问题,就类似: “有了汇编语言,为什么还要有高级语言” ?

答案其实和简单,总结出来无非是 3 点:

  1. 简化复杂的网络编程
  2. 自定义功能和扩展性
  3. 降低开发成本、提升代码可维护性

1. 简化复杂的网络编程

编程框架可以屏蔽细节,简化并统一 API,使应用开发者可以专注处理业务逻辑,降低心智负担,提高交付效率和质量。

上面是直接使用 epoll 提供的 API 进行编程时,(Socket) 文件描述符的相关操作的简化图,除此之外,开发者还需要其他的各种底层操作:

  • Reactor 模型的实现 (为了有效管理)
  • I/O 事件处理
  • 各类网络协议解析
  • 多线程实现 (为了高性能)

但是有了编程框架之后,就完全不一样了: 框架会处理好所有底层的这些 “脏活累活”,以 TCP 协议为例,最终传递到应用开发者的就是事件名称以及对应的应用数据,应用开发者只需要重复三板斧操作就可以了:

  1. 读数据
  2. 处理业务逻辑
  3. 写数据

所以网络编程框架,本质上可以看作是应用层的 TCP/IP 协议栈,只不过处理的 I/O 事件没有内核层的 TCP/IP 协议栈那么多而已。

提升性能和并发处理

虽然 epoll 提供了高效的 I/O 事件通知机制,但是面对大量并发网络连接时,如何调度事件、充分利用多线程的同时避免竞争条件等问题,epoll 并不负责。这时就需要一个网络编程框架来把这些必要的基础性工作完成,例如封装 Reactor 模型。

此外,框架内部通常实现了很多性能优化,比如常见的 内存池零拷贝缓冲区减少上下文切换的无锁编程 等机制,这些优化细节大大提高了网络应用的性能。

解析复杂的网路协议

一个系统的通信往往由多种网络协议组成:

  • 面向 C 端的 HTTP、WebSocket
  • 面向 B 端的 TCP、UDP
  • 系统内部众多服务之间互相调用的 RPC

应用开发者不可能逐个去实现解析各种网络协议,代码质量难以得到保证,且属于重复性造轮子。

网络编程框架把解析的活儿干完,应用开发者可以专注于 “一把梭” 就可以了。

毕竟,对于大多数项目来说,最复杂的地方就是去实现一套绝对灵活的 “极品” 业务逻辑规则,而不是相对固定的网络协议解析。

错误/异常处理

网络编程不同于单机编程,除了程序外,整个通信链路中容易出现问题的地方也很多,下面的错误是不是似曾相识:

  • connection timed out
  • connection refused
  • no route to host
  • broken pipe
  • address already in use
  • network is unreachable
  • host unreachable

如果这些错误全部交给应用开发者处理,那么在开始编写业务逻辑之前,代码可能已经变成了这个样子:

解决跨平台问题

Linuxepoll 仅仅是众多平台 I/O 多路复用实现机制其中的一种,如果开发者的系统需要运行在多个不同平台上,就要针对每个平台编写一套系统。

网络编程框架可以根据运行平台环境,(例如通过条件编译) 自动选择对应的 I/O 多路复用机制,真正做到代码 “一次编写,随地运行”。


2. 自定义功能和扩展性

既然是业务系统,那就说明每个模块、功能必要有优先级排序,几个重要且明显的需求就出来了:

  • 优先运行系统的核心功能
  • 紧急任务可以临时加塞到任务队列
  • 可以根据系统运行环境,自定义不同的配置参数

而这些需求,不可能直接和 epoll API 的调用代码堆叠到一起,此时,就需要借助网络编程框架来进行一个优雅且合理的代码实现分层。

技术性扩展功能

现代服务端网络程序中,一些基础组件是必备的,这时就可以直接借助框架来无缝集成,

最常见的也是最必要的就是 应用层的心跳检测机制 了,这一点无需解释太多。

此外还有:

  • SSL/TLS 安全层扩展集成
  • 传输数据压缩
  • 自动重连/断开
  • 负载均衡
  • 网络连接统计、状态上报
  • 针对 TCP 的粘包/拆包问题编码器/解码器

图片来源: https://netty.io/


3. 降低开发成本和提升代码可维护性

epoll 实现在内核中,提供的 API 自然是 C/C++ 语言版本。

图片来源: BOSS 直聘

即使现在 AI 已经可以写代码了,可以编写优秀的 C/C++ 程序的程序员相对较为稀缺,且开发周期较长。相反,使用 Java/Go 直接编写业务代码的程序员有足够的市场供应,这样就可以降低招聘成本和周期,快速迭代产品,投入市场进行验证。毕竟对于一个公司/项目来说,活下去最重要,而活下去靠的是什么?赚钱的业务。

通过网络编程框架,让技术水平一般的程序员,快速写出可以投入生产环境的 “及格代码”。

图片来源: https://www.oracle.com/


小结

编程框架用于分层,而分层的核心目的就是: 使用最合适的技术完成对应的工作 (合适的就是最好的 ~🐶~)。

大佬们即使用汇编语言,也可以写出健壮的高性能程序,因为他们早就超越了代码的层次,已经和计算机软硬件融为一体,真正做到 “代码千行过,Bug 不沾身”。

但是软件开发行业,尤其是其中覆盖面最广的应用软件开发领域,不能只靠精英程序员的推动,而是需要更多普通程序员的参与,这也就是为什么软件要分为系统软件、中间件、应用软件,而每种类型的软件都使用适合的编程语言、语言框架用来开发。