Jex’s Note

I/O

Server 效能調校

快速設定最多開啟 file 的數量

/etc/security/limits.conf 最後增加

* soft nofile 65535
* hard nofile 65535

可以再ulimit 指令查詢

/etc/pam.d/login 加上

session    required     pam_limits.so

/etc/sysctl.conf

fs.file-max = 100000
net.core.somaxconn = 2048

修改完後執行 sudo sysctl -p 使設定值生效

TCP 參數細節

/etc/sysctl.conf

# 調高系統的 IP 及 Port 限制,可以接受更多的連接 32768 61000
net.ipv4.ip_local_port_range = 32768 65000
net.ipv4.tcp_window_scaling = 1

# 調高 socket 監聽的數值
net.core.somaxconn = 65535
net.ipv4.tcp_max_tw_buckets = 1440000

# Increase TCP buffer sizes
# 調大 TCP 儲存大小
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_congestion_control = cubic

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
fs.file-max = 65000

ref : http://blog.didibird.com/2016/05/24/the-way-of-turning-the-best-performance-for-nginx/

PHPConf I/O

之前參加 PHPConf Ricky 講者發表的一個主題裡談到 I/O 架構, 然候我再以它的投影片為基礎做的一個小整理

這篇適合簡單及快速了解 I/O 架構的基本介紹, 沒辦法提供專業的教學說明。

C10K Problem

  • 解決通訊問題, server 端有問題要解決, 因為要即時通知 client, server 勢必得保持大量連線
  • 1990 提出, 當連線數到達 10K 時, 一些設計不良的架構會遭遇到效能問題, 無法通過提升硬體來解決, 是操作系統固有問題
  • 假設 server 最高支撐 1000 個連線, 儘管硬體升級一倍也無法支援 2000 個連線

blocking I/O:

Serve one client with each thread/process

優點:

  • 設計容易
  • 容易實現複雜的邏輯
  • CPU 資源可充份運用

缺點:

  • 每個 thread / process 都得佔用一份記億體
  • 當連線爆增容易拖垮效能, 並且產生阻塞(block)情形

apache 的 prefork 或 worker MPM

non-blocking I/O :

改良 blocking I/O 缺點, 使用 event-driven 讓整支程式在事件發生時才做事

Asynchronous I/O

一個 thread 處埋多個連線, 同樣具有 non-blocking 特性, 使用者不需自已檢查事件是否完成, 而是系統主動通知, 使用者收到再做動作

優點:

  • 節省記憶體(不管連線數都只會佔用一份記憶體)
  • 反應速度快(不用重複產生 process)
  • 事件驅動

缺點:

  • Blocked API 也可能導致其他連線也被 block

Nginx, memcached, node.js

要處理大量連線還是得用 Asynchronous I/O

  • 實現 Asynchronous I/O 一般採用 select 及 poll 兩個系統函式
  • 在處理大量連線效能會隨連線數遞減

libevent

  • 非同步事件處理的函式庫, 提供 API 使某些事生發生時執行函式, 因此易於移植, 擴展性佳
  • 可以用來取代網路伺服器所使用的事件循環檢查框架

優點 : * 解決 3 個平台不能移植問題 * 反應速度快能應付大量連線 * 省資源

ref: http://ricky.ez2.us/

OpenResty 介紹

這是在一次技術活動聽 Pahud 大神推薦的 web server 時做的筆記,

它可大幅度提升 server 的反應速度, 尤其是對 php 這種 request / per process 的語言

先介紹各 web server 的特點

Apache

  • select 網路 I/O 模型, 處理大量連續的讀寫效率低
  • process / perconnection
  • 1~2 G Ram 同時服務幾百人

缺點 : 阻塞

Nginx

  • epoll 網路 I/O 模型, 高併發下效能好
  • 佔用更少的 Ram
  • 請求非同步

優點 : 非阻塞

運作流程 : Master process 將 resque 丟給 worker, worker 再丟到 Task Queue 執行

  • Single process / thread - 利用 coroutine 達到多工
  • worker 數量 = cpu core 數量

假如 php 跑在 nginx 上, 仍會阻塞, 因為 php 是線性一個一個撈取 (拿留言版 -> 再拿心情帖 -> 再拿大頭貼)

OpenResty (ngx_openresty)

  • 不是新的 web server
  • 不是 nginx fork, 可跟上最新的 nginx 核心
  • 打包標準 nginx 核心及常用的第三方模組
  • 可處理極高並發請求的高性能 web 應用
  • 無縫結合 Lua, 可在 nginx 執行 lua script

先來講 Lua 帶來的好處

  • Multiple concurrent subrequests in Lua
  • Shared-memory dictionary API in Lua
  • The socket API is implemented atop Lua conroutines and is synchronous and non-blocking

運作流程 : 由 openresty 來伴演 Frondend API, 將每個 API request 拆成 subrequest 再並行發送到 sub API

詳細實現原理 :

每個 worker 是一個 process, 單執行緒處理多個連線, 可想像成一個 node.js

Worker 會跑 Lua VM, 使用 coroutine 方式處理連線, 一個連線就是一個 coroutine,

如果要做其他的 network I/O 等等動作, 會把控制權交給 Lua VM, 再交由其他 coroutine 去做, 做完後再把控制權交回

即使是線性的 php 也可以達到完全非阻塞

四核 16G Ram 可達到 60,000 req/s 真實流量

Comments