一个经常被提及的问题:APISIX 作为 API 网关经常需要同时处理大量并发请求,如果部分请求响应时间过长是否会明显增加 API 网关上其他正常请求的响应时间?APISIX 在这方面表现非常好,不会因为部分请求响应时间过长影响其他正常请求。但对于其他语言、软件架构的 API 网关产品,表现可能就比较糟糕了。
不同的编程语言对并发的软件架构具有较强的绑定性。例如早期的编程语言,如 C 和 Fortran,主要用于单处理器系统,因此它们的并发支持非常弱。然而,随着多处理器和多线程环境的出现,新的编程语言,如 Java 和 Python,开始内置更强大的并发和并行处理功能。此外,如 Go 甚至在设计之初就考虑到了并发,因此它们的并发模型和语言特性紧密结合。编程语言的并发支持不仅反映了其诞生时代的技术环境,也反映了其预期的应用场景。
假设有上千个并发请求,如果使用多线程、多进程架构(Java、Python 等语言),此时服务需要申请上千个线程或进程维护请求上下文。了解计算机编程的工程师知道,即使大部分线程空闲,操作系统维护上千个线程、进程也需要消耗硬件资源。但如果使用协程(APISIX、Golang 等),不会因为并发请求多进而申请更多线程、进程资源。
协程和线程、进程都是多任务处理的方式,但它们之间存在一些关键的区别:
调度方式:线程、进程的调度是由操作系统进行的,是抢占式的,即操作系统决定何时中断,切换到另一个线程、进程运行。而协程的调度是由程序员或者编程语言的库进行的,是协作式的,即协程需要显式地交出控制权,才会切换到其他协程。
开销:线程、进程是操作系统级别的,创建、切换和销毁线程都需要更多的资源,因此开销较大。而协程是在用户态下执行的,创建、切换和销毁协程的开销相对较小。
数据共享和同步:线程、进程间的数据共享需要使用复杂的同步操作,如互斥锁、读写锁、信号量等,以防止数据竞态。而协程由于是在同一线程中,可以直接共享全局变量,不需要进行复杂的同步操作。
在 APISIX 世界的慢请求,都仅仅是在等待上游的响应,这种等待仅仅是监听网络事件,它不会产生额外系统资源开销。最后总结:APISIX 不会因为某些请求响应慢从而影响其他正常请求响应时间。