Nginx HTTP/2 编译安装

yum apt等包管理系统安装的软件有时候比较旧, 导致一些莫名其妙的问题. 最近在给Nginx加HTTP/2模块中, 编译时加上了--with-http_v2_module参数, 但Chrome请求发现还是不是http2, 后面发现是OpenSSL版本太低. 踩过这一坑后, 感觉Linux下部分软件最好还是自己编译安装比较妥, 如果编译过程出错, 搜下错误信息, 一般是基础依赖没有安装, 很好解决.

官方的源码编译指南
https://nginx.org/en/docs/configure.html
https://nginx.org/en/docs/http/ngx_http_v2_module.html (这里写了需要OpenSSL1.0.2以上版本), 很多选项都有合适的默认值, 比如–prefix=/usr/local/nginx, 所以只需要指定自己需要的字段

--user=www-data // 习惯将web相关的服务以www-data用户运行, 如没有此用户可以创建一个也可不加此项按默认nobody用户
--group=www-data
--with-http_v2_module // 默认选项不带http2
--with-http_ssl_module // 默认选项不带ssl, 上http2必须要上ssl的
--with-stream // https://nginx.org/en/docs/stream/ngx_stream_core_module.html
--with-openssl // 指定OpenSSL
--with-pcre=./pcre-8.40 // 需要(version 4.4 — 8.40)的pcre,注意Nginx不支持pcre2
--with-pcre-jit // 打开pcre JIT支持
--with-zlib=./zlib-1.2.11 // 需要(version 1.1.3 — 1.2.11)的zlib以支持gzip

1.官网下载Nginx包

cd /usr/local
wget https://nginx.org/download/nginx-1.12.0.tar.gz
tar -zxf nginx-1.12.0.tar.gz
cd nginx-1.12.0

2.[官网下载OpenSSL 1.0.2以上版本].https://github.com/openssl/openssl/releases

cd nginx-1.12.0
wget https://github.com/openssl/openssl/archive/OpenSSL_1_1_0e.tar.gz
tar -zxf OpenSSL_1_1_0e.tar.gz

2.官网下载pcre (version 1.1.3 — 1.2.11)

注意Nginx不支持pcre2,下载pcre最新版即可. 解压到Nginx解压的目录

cd nginx-1.12.0
wget https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz
tar -zxf pcre-8.40.tar.gz

4.官网下载zlib(version 1.1.3 — 1.2.11)

cd nginx-1.12.0
wget http://zlib.net/zlib-1.2.11.tar.gz
tar -zxf zlib-1.2.11.tar.gz

5.编译并安装

./configure \
--user=www-data \
--group=www-data \
--with-http_v2_module \
--with-http_ssl_module \
--with-stream \
--with-openssl=./openssl-OpenSSL_1_1_0e \
--with-pcre=./pcre-8.40 --with-pcre-jit \
--with-zlib=./zlib-1.2.11
make && make install

6.为了方便操作,软链/usr/local/nginx/sbin/nginx到/usr/local/bin

ln -s /usr/local/nginx/sbin/nginx /usr/local/bin
分享到 评论

Python(Tornado Tornado+uvloop Tornado+uvloop2 Flask Sanic Django) Go(http Httprouter Fasthttp) RPS性能对比

在v2ex上发现了一个Python的新web框架, Sanic, 基于uvloop, 其在GitHub上的性能数据十分耀眼, 于是想跟其他用过的web框架对比一下性能, 跑个分嘛.

测试环境:

Python:3.6.0 Go:1.8.0

测试脚本:

app用tmux启动, 然后使用Apache bench测试, n=1000, c=100, 每个app测5次

for session in test_tornado test_tornadouv test_tornadouv2 test_flask test_sanic
do
tmux kill-session -t $session > /dev/null 2>&1
sleep 1
tmux new -s $session -d "/root/.pyenv/versions/3.6.0/bin/python $session.py"
done
# django
tmux kill-session -t test_django
sleep 1
tmux new -s test_django -d "/root/.pyenv/versions/3.6.0/bin/python test_django/manage.py runserver 127.0.0.1:8893"
for session in test_go_http test_go_httprouter test_go_fasthttp
do
tmux kill-session -t $session
sleep 1
tmux new -s $session -d "go run $session.go"
done
for ((i=0;i<5;i++))
do
echo $i
ab -n 1000 -c 100 http://127.0.0.1:8888/ 2> /dev/null |grep "Requests per second" |awk '{printf "tornado-epoll :%s\n",$0}'
ab -n 1000 -c 100 http://127.0.0.1:8889/ 2> /dev/null |grep "Requests per second" |awk '{printf "tornado-uvloop :%s\n",$0}'
ab -n 1000 -c 100 http://127.0.0.1:8890/ 2> /dev/null |grep "Requests per second" |awk '{printf "tornado-uvloop2:%s\n",$0}'
ab -n 1000 -c 100 http://127.0.0.1:8891/ 2> /dev/null |grep "Requests per second" |awk '{printf "flask :%s\n",$0}'
ab -n 1000 -c 100 http://127.0.0.1:8892/ 2> /dev/null |grep "Requests per second" |awk '{printf "sanic :%s\n",$0}'
ab -n 1000 -c 10 http://127.0.0.1:8893/ 2> /dev/null |grep "Requests per second" |awk '{printf "django :%s\n",$0}' # django自带的wsgi server 无法处理concurrent 100
ab -n 1000 -c 100 http://127.0.0.1:8894/ 2> /dev/null |grep "Requests per second" |awk '{printf "go_http :%s\n",$0}'
ab -n 1000 -c 100 http://127.0.0.1:8895/ 2> /dev/null |grep "Requests per second" |awk '{printf "go_httprouter :%s\n",$0}'
ab -n 1000 -c 100 http://127.0.0.1:8896/ 2> /dev/null |grep "Requests per second" |awk '{printf "go_fasthttp :%s\n",$0}'
done

测试结果:

本机 i5-6600k@3.5GHZ 四核16GB

0
tornado-epoll :Requests per second: 1714.60 [#/sec] (mean)
tornado-uvloop :Requests per second: 1988.30 [#/sec] (mean)
tornado-uvloop2:Requests per second: 1977.77 [#/sec] (mean)
flask :Requests per second: 2167.29 [#/sec] (mean)
sanic :Requests per second: 14221.72 [#/sec] (mean)
django :Requests per second: 1157.64 [#/sec] (mean)
go_http :Requests per second: 13847.92 [#/sec] (mean)
go_httprouter :Requests per second: 14595.34 [#/sec] (mean)
go_fasthttp :Requests per second: 12730.74 [#/sec] (mean)
1
tornado-epoll :Requests per second: 2011.02 [#/sec] (mean)
tornado-uvloop :Requests per second: 1788.50 [#/sec] (mean)
tornado-uvloop2:Requests per second: 1980.40 [#/sec] (mean)
flask :Requests per second: 2237.84 [#/sec] (mean)
sanic :Requests per second: 13614.70 [#/sec] (mean)
django :Requests per second: 1145.03 [#/sec] (mean)
go_http :Requests per second: 13811.01 [#/sec] (mean)
go_httprouter :Requests per second: 13441.94 [#/sec] (mean)
go_fasthttp :Requests per second: 12619.25 [#/sec] (mean)
2
tornado-epoll :Requests per second: 2056.31 [#/sec] (mean)
tornado-uvloop :Requests per second: 1831.49 [#/sec] (mean)
tornado-uvloop2:Requests per second: 2015.39 [#/sec] (mean)
flask :Requests per second: 2124.87 [#/sec] (mean)
sanic :Requests per second: 12485.80 [#/sec] (mean)
django :Requests per second: 1160.55 [#/sec] (mean)
go_http :Requests per second: 14014.43 [#/sec] (mean)
go_httprouter :Requests per second: 13949.34 [#/sec] (mean)
go_fasthttp :Requests per second: 12419.12 [#/sec] (mean)
3
tornado-epoll :Requests per second: 2017.32 [#/sec] (mean)
tornado-uvloop :Requests per second: 1731.04 [#/sec] (mean)
tornado-uvloop2:Requests per second: 2014.46 [#/sec] (mean)
flask :Requests per second: 2100.02 [#/sec] (mean)
sanic :Requests per second: 12459.04 [#/sec] (mean)
django :Requests per second: 1164.06 [#/sec] (mean)
go_http :Requests per second: 13239.77 [#/sec] (mean)
go_httprouter :Requests per second: 14127.49 [#/sec] (mean)
go_fasthttp :Requests per second: 12824.46 [#/sec] (mean)
4
tornado-epoll :Requests per second: 1810.77 [#/sec] (mean)
tornado-uvloop :Requests per second: 1975.12 [#/sec] (mean)
tornado-uvloop2:Requests per second: 1962.81 [#/sec] (mean)
flask :Requests per second: 2234.08 [#/sec] (mean)
sanic :Requests per second: 13881.95 [#/sec] (mean)
django :Requests per second: 1154.90 [#/sec] (mean)
go_http :Requests per second: 14399.47 [#/sec] (mean)
go_httprouter :Requests per second: 13688.69 [#/sec] (mean)
go_fasthttp :Requests per second: 12672.99 [#/sec] (mean)

阿里云ECS 双核8GB

0
tornado-epoll :Requests per second: 542.60 [#/sec] (mean)
tornado-uvloop :Requests per second: 930.95 [#/sec] (mean)
tornado-uvloop2:Requests per second: 811.54 [#/sec] (mean)
flask :Requests per second: 897.00 [#/sec] (mean)
sanic :Requests per second: 5681.50 [#/sec] (mean)
django :Requests per second: 447.41 [#/sec] (mean)
go_http :Requests per second: 8551.98 [#/sec] (mean)
go_httprouter :Requests per second: 9655.31 [#/sec] (mean)
go_fasthttp :Requests per second: 11469.21 [#/sec] (mean)
1
tornado-epoll :Requests per second: 969.97 [#/sec] (mean)
tornado-uvloop :Requests per second: 970.14 [#/sec] (mean)
tornado-uvloop2:Requests per second: 990.24 [#/sec] (mean)
flask :Requests per second: 900.50 [#/sec] (mean)
sanic :Requests per second: 5789.89 [#/sec] (mean)
django :Requests per second: 435.28 [#/sec] (mean)
go_http :Requests per second: 8076.63 [#/sec] (mean)
go_httprouter :Requests per second: 9340.99 [#/sec] (mean)
go_fasthttp :Requests per second: 6024.82 [#/sec] (mean)
2
tornado-epoll :Requests per second: 946.98 [#/sec] (mean)
tornado-uvloop :Requests per second: 975.64 [#/sec] (mean)
tornado-uvloop2:Requests per second: 955.25 [#/sec] (mean)
flask :Requests per second: 1021.28 [#/sec] (mean)
sanic :Requests per second: 6361.36 [#/sec] (mean)
django :Requests per second: 440.23 [#/sec] (mean)
go_http :Requests per second: 7601.67 [#/sec] (mean)
go_httprouter :Requests per second: 8123.21 [#/sec] (mean)
go_fasthttp :Requests per second: 8500.00 [#/sec] (mean)
3
tornado-epoll :Requests per second: 944.39 [#/sec] (mean)
tornado-uvloop :Requests per second: 921.12 [#/sec] (mean)
tornado-uvloop2:Requests per second: 980.30 [#/sec] (mean)
flask :Requests per second: 946.53 [#/sec] (mean)
sanic :Requests per second: 5686.99 [#/sec] (mean)
django :Requests per second: 498.31 [#/sec] (mean)
go_http :Requests per second: 6297.78 [#/sec] (mean)
go_httprouter :Requests per second: 8078.91 [#/sec] (mean)
go_fasthttp :Requests per second: 6523.84 [#/sec] (mean)
4
tornado-epoll :Requests per second: 953.86 [#/sec] (mean)
tornado-uvloop :Requests per second: 983.97 [#/sec] (mean)
tornado-uvloop2:Requests per second: 955.04 [#/sec] (mean)
flask :Requests per second: 994.77 [#/sec] (mean)
sanic :Requests per second: 6877.11 [#/sec] (mean)
django :Requests per second: 510.76 [#/sec] (mean)
go_http :Requests per second: 8243.14 [#/sec] (mean)
go_httprouter :Requests per second: 7055.97 [#/sec] (mean)
go_fasthttp :Requests per second: 6183.83 [#/sec] (mean)

###结论:

  1. Sanic确实叼, 拉出Flask一大截. 由于这个测试只是简单返回”Hello, world”, Tornado的优势要在使用了aio,AsyncHTTPClient的时候才能发挥出来. 如果拿tornado当纯同步使用的话, 性能会比flask弱一点点.
  2. Django自带的wsgi server无法完成此任务.
  3. fasthttp表现的很奇怪, 可能是handler太简单的情况下sync/pool的代价超过了gc的影响, httprouter比http快一点.

###测试代码:

1.test_tornado.py Tornado 4.4.2

import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()

2.test_tornadouv.py Tornado+uvloop(pip install tornadouvloop)

import tornado.ioloop
import tornado.web
from tornadouvloop import TornadoUvloop
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8889)
tornado.ioloop.IOLoop.configure(TornadoUvloop)
tornado.ioloop.IOLoop.current().start()

3.test_tornadouv2.py Tornado+uvloop2(pip install tornaduv)

import tornado.ioloop
import tornado.web
from tornaduv import UVLoop
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8890)
tornado.ioloop.IOLoop.configure(UVLoop)
tornado.ioloop.IOLoop.current().start()

4.test_flask.py Flask 0.12

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, world"
if __name__ == "__main__":
app.run(port=8891)

5.test_sanic.py Sanic 0.4.1

from sanic import Sanic
from sanic.response import HTTPResponse
app = Sanic()
@app.route("/")
async def test(request):
return HTTPResponse("Hello, world")
if __name__ == "__main__":
app.run(port=8892)

6.test_django.py Django

# views.py
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello, world")

7.test_go_http.go Go http

package main
import (
"net/http"
"runtime"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, world"))
})
http.ListenAndServe("127.0.0.1:8894", nil)
}

8.test_go_httprouter.go GO httprouter

package main
import (
"net/http"
"github.com/julienschmidt/httprouter"
"runtime"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
router := httprouter.New()
router.HandlerFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, world"))
})
http.ListenAndServe("127.0.0.1:8895", router)
}

9.test_go_fasthttp.go Go fasthttp

package main
import (
"github.com/valyala/fasthttp"
"runtime"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
requestHandler := func(ctx *fasthttp.RequestCtx) {
ctx.Write([]byte("Hello, world"))
}
fasthttp.ListenAndServe("127.0.0.1:8896", requestHandler)
}
分享到 评论