C10X 包括 C10K、C10M 等。C10K 问题最早由 Dan Kegel 在《The C10K problem》提出,指的是单机处理 1 万个并发连接。我们已经解决了 C10K 问题,当前面临的是C10M ,指单机同时处理一千万的请求。
早期互联网并不普及,用户不多,服务器并不存在高并发问题。到了 Web1.0,用户主要浏览静态网页,以门户类网站为主(比如 Netscape、Yahoo),互联网逐渐普及,虽然用户增多但也没有达到 C10K。到了 Web2.0,浏览网页发展成了实时通信和在线实时互动,以社交网站为代表(比如 Twitter、Facebook),用户爆发式增长,这个时候出现了 C10K 问题,再往后便是 C10M 问题。
C10X 的核心思想是让服务器处理更多的请求,追求单机极致性能。广义的角度来说,我们希望用更低的成本,更高的效率生产的产品为更多的用户提供有价值的服务。这样 C10X 也可以理解为用低成本、简单高效的方式提供高性能应用服务。
Solutions解决这个问题的主要有三个方向:
- 硬件系统
- 操作系统
- 应用软件
Software Layers & Performance Productivity & Generality
从下往上,依次是硬件层、操作系统层、应用软件层。从下往上性能和通用性逐渐降低,生产效率逐渐升高。
Hardware
硬件是运行应用的物理基础,包括 CPU、内存、硬盘等,提供通用的计算、存储等能力。
硬件研发成本和风险高,但可以工厂化大规模批量生产。
CPU
单核 CPU —> 多核 CPU
根据摩尔定律,CPU 的性能在不断提高。当前硅基半导体工艺的已接近物理极限,单核的性能提升越来越慢,通过多核的方式可以以更低成本提升 CPU 整体性能。除此之外,芯片领域在探索新的材料和技术(比如碳基芯片)。
存储
软盘 —> 机械硬盘 —> SSD
随着存储器技术的更新换代,成本越来越低,存储容量越来越大,速度越来越快。
网卡
十兆网卡 —> 百兆 —> 千兆 —> 万兆
单网卡性能提升和多网卡绑定技术可以承载越来越大的吞吐量。
System
操作系统介于硬件和软件层之间,是管理硬件与软件资源的系统软件。操作系统的核心价值在于:实现软件治理、提供基础的编程接口、降低软件开发难度。
硬件在不断演进,操作系统也在演进。比如 CPU 演变成多核后,操作系统也具备更好利用多核的能力。
History of Evolution
- 手工操作阶段:独占计算机资源
- 单道批处理系统:高效利用 CPU 资源
- 多道批处理系统:宏观上并行,微观上串行
- 分时操作系统:交互性强
- 实时操作系统:及时性和可靠性不如分时
- 网络操作系统:集中式控制
- 分布式操作系统:分布式控制
- 个人操作系统:目前最广泛
Process & Thread
操作系统通过进程和线程管理资源的分配和调度,提高硬件资源的利用率。进程是资源分配的基本单位,通过进程可以实现多软件同时运行。线程是调度的基本单位,通过线程可以实现同一进程内多任务同时运行。
CPU 性能提升遇到了瓶颈,通过多核的方式提高 CPU 的整体性能。操作系统则通过多线程模型利用了 CPU 多核的优势。
I/O Model
网络处理能力是服务端性能的一个重要点。操作系统早期提供的阻塞 I/O 模型导致单线程只能同时处理一个网络请求,遇到阻塞需要进行线程上下文切换,带来了线程上下文切换时间消耗和线程资源消耗。非阻塞 I/O 模型和多路复用出现后,单线程可以同时处理多个网络请求,大大提高了网络请求的并发处理能力,又避免和线程上下文切换带来的时间消耗和线程资源消耗。I/O 多路复用提高了单线程并发处理网络请求的能力。
- Blocking I/O - 阻塞 I/O
- Nonblocking I/O - 非阻塞 I/O
- I/O multiplexing - I/O 多路复用(Select、Poll、Epoll)
- Signal Driven I/O - 信号驱动 I/O
- Asynchronous I/O - 异步 I/O(未成熟技术)
Software
硬件和操作系统都在不断演进,软件也在演进,充分利用硬件和操作系统演进带来的进步。
软件层是生产效率最高的一层,大量的开发工作消耗在这层。作为软件开发工程师,我们专注于软件层。硬件资源是昂贵且有限的,在硬件层和操作系统层一定的情况下,我们只能尽可能提高软件层的生产效率、性能和通用性。
软件开发目前没有实现工厂化一样自动化批量生产,还属于“劳动力密集型”。多人协作需要软件工程和项目管理控制效率和质量。
语言
不同语言写的代码在同一台计算机(硬件和操作系统都一样)跑为什么会有不同的性能。
CPU 只能执行机器码,高级语言的代码需要编译器编译成机器码。不同语言的编程模型不一样,编译成的机器码不一样导致了执行效率不一样。编程模型和编译这两部是语言性能和效率的关键,比如 Go 引入了Goroutine。
对于底层和极致性能追求的场景我们往往选择C、C++ 等语言,但是在应用层似乎用的比较多的是 Java、PHP 等语言。Java 等高级语言的性能可能比 C 差,但是开发效率高,用部分性能换取更高的效率。
分布式
单机性能再厉害也有极限,单机性能提升到一定程度再往后提升会越来越困难。单核 CPU 性能提升遇到瓶颈,我们使用多核 CPU 提升整体性能。同样,单机性能遇到瓶颈,我们使用集群和分布式系统提升整体性能。
传统的 SQL 数据库单机性能遇到瓶颈后,我们通过分库分表、NewSQL 提高数据库的整体能力。