使用 Clojure 和 http-kit 实现 60万的并发 HTTP 请求处理

红薯 发布于 2013/01/28 15:53
阅读 4K+
收藏 30

灵感来自 Scaling node.js to 100k concurrent connections!Node.js w/250k concurrent connections!. 我之前做了一些 http-kit 的测试。

http-kit 可以让 PC 上支持超过 60 万的并发连接。

服务器端逻辑:

服务器从请求中读取长度参数,并生成指定长度的字符串:

;; main.clj
;; ~20k string
(def const-str (apply str (repeat 200 "http-kit is a http server & client written from scrach for high performance clojure web applications, support async and websocket")))

(defn handler [req]
  (let [length (to-int (or (-> req :params :length) 1024))]
    {:status 200
     :headers {"Content-Type" "text/plain"}
     :body (subs const-str 0 (max (min 10240 length) 1))}))

(defn -main [& args]
  (run-server (-> handler wrap-keyword-params wrap-params)
              {:port 8000})
  (println (str "Server started. listen at 0.0.0.0@8000")))

启动服务器:

java -server -Xms3072m -Xmx3072m -cp `lein classpath` clojure.main -m main

Linux 配置

服务器需要设置最大允许打开的文件数,默认值只有 1024

echo 9999999 | sudo tee /proc/sys/fs/nr_open
echo 9999999 | sudo tee /proc/sys/fs/file-max

# edit /etc/security/limits.conf, add the following line, need logout and login again
* - nofile 4999999

# set before run the server and test code
ulimit -n 4999999

为测试代码提供更多的端口

sudo sysctl -w net.ipv4.ip_local_port_range="1025 65535"

软硬件

服务器和测试代码都是在我的PC 上允许,配置如下:

  • CPU: Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz, 4 core, 8 threads
  • RAM: 16G @ 1333MHZ
  • OS : Linux 3.2.0-2-amd64 #1 SMP Sun Apr 15 16:47:38 UTC 2012 x86_64 GNU/Linux
  • http-kit: “2.0-rc1”
  • JVM: 1.7.0_04

如果在单台 PC 上实现 60 万的并发连接?

一个 IP 只能处理最多 65536 个连接到一个服务器上,因为 socket 端口是无符号短整形,但我们可以避开这个限制,在 Linux 上可通过简单的设置虚拟网络接口:

for i in `seq 200 230`; do sudo ifconfig eth0:$i 192.168.1.$i up ; done

这样你的电脑就有很多的 IP 地址,从 192.168.1.200 到 192.168.1.230。服务器是绑定到 0.0.0.0:port 之上。每个 IP 可处理大约 6万的并发连接,这样客户端就可以发起超过 60 完的连接。

并发测试代码

客户端打开 60万 并发 keep-alived 连接到服务器,请求服务器返回随机数在 1~4096 长度的字符串,读取响应,然后空闲 5s ~ 45s(随机选择),然后再次请求。

输出:

time 0s, concurrency: 100, total requests: 0, thoughput: 0.00M/s, 0.00 requests/seconds
time 40s, concurrency: 164000, total requests: 230142, thoughput: 11.78M/s, 5688.28 requests/seconds
...
time 89s, concurrency: 340100, total requests: 788985, thoughput: 18.23M/s, 8812.23 requests/seconds
...
time 179s, concurrency: 595166, total requests: 2483174, thoughput: 28.61M/s, 13837.77 requests/seconds
time 180s, concurrency: 597853, total requests: 2506378, thoughput: 28.71M/s, 13888.67 requests/seconds
time 183s, concurrency: 600000, total requests: 2529020, thoughput: 28.52M/s, 13788.14 requests/seconds
time 185s, concurrency: 600000, total requests: 2537212, thoughput: 28.20M/s, 13680.42 requests/seconds
...
time 930s, concurrency: 600000, total requests: 17457773, thoughput: 38.64M/s, 18763.53 requests/seconds
time 931s, concurrency: 600000, total requests: 17477678, thoughput: 38.69M/s, 18764.73 requests/seconds



当 60 完连接被保持后,继续使用 ab 测试

从命令行执行 ab 测试命令

ab -n 100000 -c 10 -k http://127.0.0.1:8000/

ab 输出:

Server Software:        http-kit
Server Hostname:        127.0.0.1
Server Port:            8000

Document Path:          /
Document Length:        1024 bytes

Concurrency Level:      10
Time taken for tests:   3.184 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    100000
Total transferred:      117000000 bytes
HTML transferred:       102400000 bytes
Requests per second:    31405.53 [#/sec] (mean) Time per request:       0.318 [ms] (mean) Time per request:       0.032 [ms] (mean, across all concurrent requests) Transfer rate:          35883.27 [Kbytes/sec] received

Connection Times (ms) min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     0    0   9.3      0     913
Waiting:        0    0   9.3      0     913
Total:          0    0   9.3      0     913

Percentage of the requests served within a certain time (ms) 50%      0
  66%      0
  75%      0
  80%      0
  90%      0
  95%      0
  98%      0
  99%      0
 100%    913 (longest request)

Clojure 服务器的 CPU 占用率

jvisualvm 的快照文件:snapshot file.

cpu usage

Clojure 服务器的内存使用

heap memory usage

你也可以自行测试

完整的测试代码可通过 github 获取。

via http-kit

加载中
0
Duziee
Duziee
服务器配置有点业余啊.....@红薯
0
fshen
fshen

http-kit 应用于 美味书签 线上服务,大家可以去看看 http://meiweisq.com  

fshen
fshen
@zhanglu(张露) 嗯,看来是程序出了问题,正在修。。。。
luluback
luluback
chrome 浏览器
luluback
luluback
回复 @fshen : QQ或者新浪登录 小窗同样报这个错 是了几次了
fshen
fshen
回复 @zhanglu(张露) : try again?
luluback
luluback
Sorry, an error occured.
0
E
Ellipse
这个代码太奇葩了,完全看不懂
0
池塘仙人
池塘仙人

建议做 @宏哥 级测试

以下引用宏哥测试法

1:做一个并发测试,每一个请求都对应一个流水号,要求应答将此流水号返回,并对比这个流水。这个测试表明spawn-fcgi搞不清哪个应答对应哪个请求,这在社区/bbs上不是大问题,但是在更多的场景,这是绝对无法接受的。 2:用AB做测试的时候,将线程/进程标识也作为应答内容,你会发现,spawn-fcgi根本没有任何调度能力。所有的负荷都集中在个别进程上,而且大多都是错误信息的返回。这个意味着你的测试,吞吐出来的数据,都是错误的,量就么有意义。

0
arden
arden
clojure的代码太难读了
0
peter112358
peter112358
clojure代码如果不涉及宏之类的,还是很好懂的。就是基本的数据类型和(表达式 参数1 参数2 ...) 这样的。
返回顶部
顶部