ABTest及Ngnix实现

Posted by Shi Hai's Blog on January 18, 2018

ABTest及相关实践

ABTest基础理念

A/B测试(也称为分割测试或桶测试)是比较网页或应用程序的两个版本以确定哪一个更好地执行的方法。

Ngnix安装

在两台机器上(我的两台机器地址为:114.115.162.219、114.115.162.141)安装nginx,具体的操作如下所示:

# 通过rpm安装nginx
rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

# 查看nginx信息
yum info nginx

# 安装nginx
yum install nginx

# 启动nginx
service nginx start

# 查看nginx服务
curl -i localhost

编写服务端demo

在hello.py中使用flask写一个小的server端程序

from flask import Flask
from multiprocessing import Process

app1 = Flask("app1")
app2 = Flask("app2")
app3 = Flask("app3")

HOST = "0.0.0.0"

@app1.route("/a_test")
def hello():
    return "Hello World1!"

@app2.route("/a_test")
def hello():
    return "Hello World2!"

@app3.route("/b_test")
def hello():
    return "Hello World3!"

p1 = Process(target=app1.run, args=(HOST, 9001))
P2 = Process(target=app1.run, args=(HOST, 9002))
P3 = Process(target=app1.run, args=(HOST, 9003))

p1.start()
p2.start()
p3.start()

并启用server服务

nohup python hello.py &

nginx负载配置

配置nginx负载,编辑/etc/nginx/conf.d/default.conf文件

# 添加一个upstream
upstream a_test  {
    server your_ip:9001 weight=1;
    server your_ip:9002 weight=2;
}

server  {
    location /a_test {
        #root /usr/share/nginx/html;
        #index index.html index.htm;
        proxy_pass http://a_test;
        proxy_set_header Host &host;
        proxy_set_header X-Real-IP &remote_addr;
        proxy_set_header X-Forwarded-For &proxy_add_x_forwarded_for;
    }
}

使用lua-nginx-module模块对nginx流量进行复制转发。

install luajit

git clone http://luajit.org/git/luajit-2.0.git
cd luajit-2.0
make
make install PREFIX=/usr/local/luajit
echo "/usr/local/luajit/lib" > /etc/ld.so.conf.d/usr_local_luajit_lib.conf
ldconfig
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0

Reinstall nginx

rpm -e nginx-release-centos-7-0.el7.ngx.noarch
rpm -e nginx-1.12.2-1.el7_4.ngx.x86_64

cd /home/shihai
git clone https://github.com/simpl/ngx_devel_kit.git
cd ngx_devel_kit
# checkout到最新发布版本
git checkout v0.3.0
cd /home/shihai
git clone https://github.com/openresty/lua-nginx-module.git
cd lua-nginx-module
# checkout到最新发布版本
git checkout v0.10.5
cd /home/shihai
wget https://ftp.pcre.org/pub/pcre/pcre-8.41.tar.gz
tar -zxvf pcre-8.41.tar.gz
cd /home/shihai
git clone https://github.com/madler/zlib.git
cd zlib
git checkout v1.2.9
cd /home/shihai
git clone https://github.com/openssl/openssl.git
cd openssl
git checkout OpenSSL_1_1_0

cd /home/shihai
wget http://nginx.org/download/nginx-1.11.0.tar.gz
tar -zxvf nginx-1.11.0.tar.gz

cd nginx-1.11.0
 
# tell nginx's build system where to find LuaJIT 2.0:
 export LUAJIT_LIB=/usr/local/luajit/lib
 export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0

 # Here we assume Nginx is to be installed under /usr/local/nginx/.
 ./configure --prefix=/etc/nginx --with-http_stub_status_module \
         --with-pcre=../pcre-8.41 \
         --with-zlib=../zlib \
         --with-openssl=../openssl \
         --add-module=../ngx_devel_kit \
         --add-module=../lua-nginx-module


 # Note that you may also want to add `./configure` options which are used in your
 # current nginx build.
 # You can get usually those options using command nginx -V

 # you can change the parallism number 2 below to fit the number of spare CPU cores in your
 # machine.
 make
 make install

编辑/etc/nginx/conf/nginx.conf,添加:


location =/test {
  content_by_lua '
    ngx.say("hello world")
  ';
}
执行`/etc/nginx/sbin/nginx`启动nginx。在浏览器访问http://your_ip/test, 显示结果如下所示:
![](/img/2018012501.PNG)

# 添加一个upstream(之前是rpm安装,现在是源码安装,所以配置的负载要重新刷新)
upstream a_test  {
    server your_ip:9001 weight=1;
    server your_ip:9002 weight=1;
}

upstream b_test {
    server your_ip:9003;
}

server  {
    location /ab_test {
        content_by_lua '
            local a_res, b_res = ngx.location.capture_multi{
              {"/a_test", {args = ngx.req.get_uri_args()}},
              {"/b_test", {args = ngx.req.get_uri_args()}},
            }
            ngx.print(a_res.body)
            ngx.print(b_res.body)
            ';
    }
    
    location /a_test {
        #root /usr/share/nginx/html;
        #index index.html index.htm;
        proxy_pass http://a_test;
    }
    
    location /b_test {
        #root /usr/share/nginx/html;
        #index index.html index.htm;
        proxy_pass http://b_test;
    }
}

the end

通过/etc/nginx/sbin/nginx -s reload重新加载nginx。

参考文档

1.ABTest

2.Ngnix安装

3.ngx_http_mirror_module

4.lua-nginx-module

5.NDK