天天看点

openresty+lua实现流量百分比分配

1、安装openresty:

#!/bin/bash
#NGINX_SERVER_IP="10.153.167.190"
SOURCE_DIR="/data/jenkins_data"
TARGET_DIR="/usr/local"
NGINX_SOURCE_FILE="openresty-1.9.7.3.tar.gz"
NGINX_TARGET_FILE="openresty-1.9.7.3"
INSTALL_DIR="$TARGET_DIR/openresty/nginx/sbin"

echo "servers : ${NGINX_SERVER_IP}"

IP_ARR=(${NGINX_SERVER_IP//,/})

echo "prepare to install pcre"

for IP in ${IP_ARR[@]}
do
    ssh root@$IP  "yum install -y gcc gcc-c++ && wait"
    ssh root@$IP  "yum install -y pcre-devel && wait"
    ssh root@$IP  "yum install -y readline-devel && wait"
    ssh root@$IP  "yum install -y openssl-devel && wait"

    echo "prepare to install nginx"
        scp $SOURCE_DIR/openresty-1.9.7.3.tar.gz root@$IP:$TARGET_DIR
        ssh root@$IP  "cd $TARGET_DIR && tar -zxvf $NGINX_SOURCE_FILE "
        ssh root@$IP  "cd $TARGET_DIR/$NGINX_TARGET_FILE && ./configure --with-luajit  && make && make install && sleep 15"
        #ssh root@$IP  "cd /lib64 && ln -s libpcre.so.0.0.1 libpcre.so.1"
        ssh root@$IP  "if [ -e /lib64/libpcre.so.1 ];then echo 'file exits...';else cd /lib64 && ln -s libpcre.so.0.0.1 libpcre.so.1;fi"
    ssh root@$IP  "cd $INSTALL_DIR && ./nginx"
done

echo " start nginx ! "
           

安装目录在:/usr/local/openresty

2、lua脚本配置:

接下来我们通过一个murmurhash2的lua库,实现一个对用户uid进行流量分桶得功能。具体需求如下:

对url中得uid参数值进行hash计算,取模,将5%的流量指向upstreamA,剩余流量走upstreamB。

1)murmurhash2 lua库安装:

下载地址:https://www.rootopen.com/git/5b8ba95364fec049aff8f0dc

github地址:https://github.com/bungle/lua-resty-murmurhash2

下载后,将murmurhash2.lua 拷贝到/usr/local/openresty/lualib/resty 目录下。

2)配置:

upstream local_worker_A {
    server 10.9.8.9:80;
    server 10.9.9.9:80;
    keepalive 1024;
}

upstream local_worker_B {
    server 10.6.80.6:8088;
    server 10.6.80.7:8088;
    keepalive 1024;
}

server {
    listen              80 default;
    server_name         localhost;
    root                /data/none;
    index               index.html index.htm;

    ### deny user agent
    if ($http_user_agent ~* (apachebench|spider|robot|wget)) {
        return 403;
    }
	##定义两个location
    location @worker_A{
        proxy_pass      http://local_worker_A;
    }
    location @worker_B{
        proxy_pass      http://local_worker_B;
    }

    ### refuse illegal access
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    ### speed limit
    #limit_req   zone=java  burst=50 nodelay;

    location / {
		root  	html;
		index	index.html index.htm index.php;
        proxy_redirect      off;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    Host $http_host;
        proxy_http_version  1.1;
        proxy_set_header    Connection "";
 
        #lua_code_cache off;
        content_by_lua_block {
          local mmh2 = require "resty.murmurhash2"
          local uid=ngx.var.arg_uid or ""
          if(string.len(uid) ~= 0)
          then
             local hash = mmh2(uid)
             if (hash % 100 > 94)
             then
               ngx.exec("@worker_redian")
             else
               ngx.exec("@worker_old")
             end
          end
        }
        #proxy_pass      http://local_worker_A;
    }
}
           

这里面需要注意两点:

1、lua脚本中获取nginx得内置变量,使用ngx.var.XXX得方式。

$arg_uid:nginx中得命令,可以获取url中得uid参数值,在lua中可以通过ngx.var.arg_uid来获取。

2、在content_by_lua_block 中只能通过ngx.exec来执行对应的跳转命令。

3、在 nginx.conf 文件的 server {.. ...} 中加入 lua_code_cache off; 可以方便调试lua脚本,修改lua脚本之后,不需要 reload nginx.

继续阅读