高并发环境搭建nginx+lua+redis
一、安装环境 2
1.1、安装Lua解释器 2
1.2、安装nginx 2
1.2.1、下载nginx开发插件ngx_devel_kit 2
1.2.2、下载nginx的lua模块lua-nginx-module 2
1.2.3、安装nginx 2
1.3、安装redis 3
1.3.1、redis下载安装 3
1.3.2、安装lua-resty-redis 4
1.3.3、连接redis连接池 4
1.4、整合运行 6
1.4.1、修改nginx配置文件 6
1.4.2、编写lua执行脚本 6
二、高并发优化 7
2.1调整文件访问数量相关参数 7
2.2调整Socket连接相关参数 7
三、压力测试 9
3.1压力测试工具 9
3.2测试效果 9
cd /usr/local/src
wget http://luajit.org/download/LuaJIT-2.0.2.tar.gz
tar -xvf LuaJIT-2.0.2.tar.gz
cd LuaJIT-2.0.2
make && make install
默认lib 以及驱动文件路径是/usr/local/lib 和 /usr/local/include/luajit-2.0
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0
cd /usr/local/src
wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
tar -xvf v0.3.0.tar.gz **包名好奇怪
cd /usr/local/src
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.9rc7.tar.gz
tar -xvf v0.10.9rc7.tar.gz **包名。。。
cd /usr/local/src
wget http://nginx.org/download/nginx-1.12.1.tar.gz
tar -xvf nginx-1.12.1.tar.gz
cd nginx-1.12.1
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-pcre=/usr/local/src/pcre-8.40 \
--with-zlib=/usr/local/src/zlib-1.2.11 \
--with-openssl=/usr/local/src/openssl-1.0.2l \
--with-http_stub_status_module \
--add-module=/usr/local/src/ngx_devel_kit-0.3.0 \
--add-module=/usr/local/src/lua-nginx-module-0.10.9rc7
make && make install
其中http_stub_status_module 是状态监控模块
安装nginx之前确保已经安装依赖包openssl、zlib、pcre下载解压到相应位置
如果提示下面错误,应该是 lua-nginx-module和OpenSSL 1.1.0不兼容,换成OpenSSL 1.0.2就好了,
/usr/local/src/lua-nginx-module-0.10.10/src/ngx_http_lua_module.c:1022:37: error: passing argument 2 of ‘SSL_CTX_sess_set_get_cb’ from incompatible pointer type [-Werror]
运行nginx
/usr/local/nginx/sbin/nginx
如果提示下面错误,表示找不到libluajit-5.1.so.2库
error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory
解决方法:
ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
cd /usr/local/src
wget http://download.redis.io/releases/redis-4.0.1.tar.gz
tar xzf redis-4.0.1.tar.gz
cd redis-4.0.1
make
编译完成后,在src目录下,有四个文件redis-server、redis-benchmark、redis-cli和redis.conf,然后拷贝到一个目录下。
mkdir /usr/local/redis
cp /usr/local/src/redis-4.0.1/src/redis-server /usr/local/redis
cp /usr/local/src/redis-4.0.1/src/redis-benchmark /usr/local/redis
cp /usr/local/src/redis-4.0.1/src/redis-cli /usr/local/redis
cp /usr/local/src/redis-4.0.1/redis.conf /usr/local/redis
设置密码
修改redis.conf,将# requirepass foobared前面的#号去掉并设置密码;
启动redis服务端
/usr/local/redis/redis-server redis.conf &
加&表示后台启动
启动redis客户端
/usr/local/redis/redis-cli -h 127.0.0.1 -p 6379 -a yourpassword
从https://github.com/openresty/lua-resty-redis.git下载lua-resty-redis-master后解压
将lib包安装到lua库
cd /usr/local/src/lua-resty-redis-master
make && make install
安装完成之后在/usr/local/lib/lua/resty里面会有redis.lua
在/usr/local/lib/lua添加redisUtil.lua,代码如下
local redis = require "resty/redis"
local log = ngx.log
local ERR = ngx.ERR
local setmetatable = setmetatable
local _M = {
}
local mt = { __index = _M }
local function errlog(...)
log(ERR, "Redis: ", ...)
end
function _M.exec(self, func)
local red = redis:new()
red:set_timeout(self.timeout)
local ok, err = red:connect(self.host, self.port)
if not ok then
errlog("Cannot connect, host: " .. self.host .. ", port: " .. self.port)
return nil, err
end
if self.password ~= '' then
-- 请注意这里 auth 的调用过程
local count
count, err = red:get_reused_times()
if 0 == count then
ok, err = red:auth(self.password)
if not ok then
ngx.say("failed to auth: ", err)
return
end
elseif err then
ngx.say("failed to get reused times: ", err)
return
end
end
red:select(self.database)
local res, err = func(red)
if res then
local ok, err = red:set_keepalive(self.max_idle_time, self.pool_size)
if not ok then
red:close()
end
end
return res, err
end
function _M.new(opts)
local config = opts or {}
local self = {
host = config.host or "127.0.0.1",
password = config.password or '',
port = config.port or 6379,
timeout = config.timeout or 5000,
database = config.database or 0,
max_idle_time = config.max_idle_time or 60000,
pool_size = config.pool_size or 1000
}
return setmetatable(self, mt)
end
return _M
http内添加 lua_package_path "/usr/local/lib/lua/?.lua";
server 内添加
location /lua/test {
default_type 'text/plain';
content_by_lua_file conf/lua/redisController.lua;
}
在/usr/local/nginx/conf/lua添加redisController.lua,代码如下
local redisUtil = require "redisUtil"
local red = redisUtil.new({host = "127.0.0.1",password="yourpassword"})
local res, err = red:exec(
function(red)
return red:get("key1")
end
)
ngx.say(res);
测试效果
curl http://127.0.0.1/lua/test
返回结果:
helloworld
**测试之前先往redis里set数据set key1 helloworld
修改操作系统参数
ulimit -n 50000
修改nginx.conf
worker_rlimit_nofile 50000; #每个子进程允许打开的文件数
修改操作系统参数
vi /etc/sysctl.conf 新增或者修改
net.core.somaxconn = 50000 #最大连接:somaxconn
net.ipv4.tcp_tw_recycle = 1 #加快tcp回收
net.ipv4.tcp_tw_reuse = 1 #空tcp回收
net.ipv4.tcp_syncookies = 0 #去除洪水攻击抵御
让sysctl.conf生效
sysctl -p
修改nginx.conf
worker_connections 50000 #每个子进程允许打开的连接数
keepalive_timeout 0 #连接的保持时间
优化完成后的nginx.conf文件如下
#user nobody;
worker_processes 1;
worker_rlimit_nofile 50000;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 50000;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
lua_package_path "/usr/local/lib/lua/?.lua";
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /lua/get/test {
default_type 'text/plain';
content_by_lua_file conf/lua/redisController.lua;
}
location /status {
stub_status on;
access_log off;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
apache,自带ab工具;
也可以独立安装:
ab运行需要依赖apr-util包,安装命令为:
yum install apr-util
安装ab
cd /usr/local
mkdir ab
cd ab
yum install yum-utils.noarch
yumdownloader httpd-tools*
rpm2cpio httpd-*.rpm | cpio -idmv
解开后就能得到独立的 ab可执行文件了。
操作完成后 将会产生一个 usr 目录 ab工具就在这个usr 目录下的bin目录中
发生20万个请求,并发20000
/usr/local/ab/usr/bin/ab -n 200000 -c 20000 http://127.0.0.1/lua/test
测试结果:
Server Software: nginx/1.12.1
Server Hostname: 127.0.0.1
Server Port: 80
Document Path: /lua/test
Document Length: 6 bytes
Concurrency Level: 20000
Time taken for tests: 23.136 seconds
Complete requests: 200000
Failed requests: 0
Write errors: 0
Total transferred: 29600000 bytes
HTML transferred: 1200000 bytes
Requests per second: 8644.45 [#/sec] (mean)
Time per request: 2313.624 [ms] (mean)
Time per request: 0.116 [ms] (mean, across all concurrent requests)
Transfer rate: 1249.39 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 537 1687.5 2 15048
Processing: 16 69 192.4 43 6447
Waiting: 1 67 192.4 41 6445
Total: 18 605 1713.2 46 15898
Percentage of the requests served within a certain time (ms)
50% 46
66% 48
75% 52
80% 1046
90% 1240
95% 3060
98% 7063
99% 7077
100% 15898 (longest request)
出错请求为0
90%的请求在1.3秒内完成