最近在读 shadowsocks 的源码,有一些疑惑。 shadowsocks 每次通过 epoll 监听到新连接之后,程序都会阻塞一段时间去执行 on_remote_read() 或 on_remote_write() 来传输数据,数据传输完毕之后才会再次调用 epoll 并 accept 新的 socket 连接,当连接达到一定数量之后,会出现高延迟、低效率的情况啊
# 在知乎上问了这个问题,没人理只好来 SegmentFault 啦~
光阴似箭催人老,日月如移越少年。
因為這個過程是高CPU、高記憶體的操作,而非高硬碟IO的操作,也就是說,這個過程考驗的是CPU效能。而我們知道,電腦了沒有真正的多進程或是多線程,都是透過CPU調度模擬出來的。那麼對於高CPU的操作,最好就是用單一進程或單執行緒的方法來處理(多核心可考慮增加),這樣才是最高效的辦法,因為這樣避免了執行緒或進程來回切換帶來的消耗。
這塊可以參考Nginx的架構,Nginx的高負載也是在單一進程中完成的。
CPython的多執行緒不是「真正」的多執行緒(詳見 GIL),不換語言的話,解決方法是多進程,前面架一個負載平衡(haproxy之類的)。
處理並發連接有多種模型。多執行緒是一種,epoll所代表的non-blocking I/O + multiplexing也是一種。只要用得對,新連接進來之後的read/write就不會阻塞哪怕是很長時間。
早年的老司機都讀過Dan Kegel的The C10K Problem,裡面對各種並發處理模型有講解。如果英文還過得去的話還是建議你唸讀。喔對了,如果是學習概念,不涉及實際系統上為了處理大並發量而做的各種技巧性增強,那麼Richard Stevens的《Unix網絡編程》裡面講得更清楚,中譯版也易讀一些。
因為這個過程是高CPU、高記憶體的操作,而非高硬碟IO的操作,也就是說,這個過程考驗的是CPU效能。而我們知道,電腦了沒有真正的多進程或是多線程,都是透過CPU調度模擬出來的。那麼對於高CPU的操作,最好就是用單一進程或單執行緒的方法來處理(多核心可考慮增加),這樣才是最高效的辦法,因為這樣避免了執行緒或進程來回切換帶來的消耗。
這塊可以參考Nginx的架構,Nginx的高負載也是在單一進程中完成的。
CPython的多執行緒不是「真正」的多執行緒(詳見 GIL),不換語言的話,解決方法是多進程,前面架一個負載平衡(haproxy之類的)。
處理並發連接有多種模型。多執行緒是一種,epoll所代表的non-blocking I/O + multiplexing也是一種。只要用得對,新連接進來之後的read/write就不會阻塞哪怕是很長時間。
早年的老司機都讀過Dan Kegel的The C10K Problem,裡面對各種並發處理模型有講解。如果英文還過得去的話還是建議你唸讀。喔對了,如果是學習概念,不涉及實際系統上為了處理大並發量而做的各種技巧性增強,那麼Richard Stevens的《Unix網絡編程》裡面講得更清楚,中譯版也易讀一些。