第八章 流量复制/AB测试/协程 - 《亿级流量网站架构核心技术》~ - ITeye博客


本站和网页 https://www.iteye.com/blog/jinnianshilongnian-2190343 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

第八章 流量复制/AB测试/协程 - 《亿级流量网站架构核心技术》~ - ITeye博客
首页
资讯
精华
论坛
问答
博客
专栏
群组
下载
资源
搜索
您还未登录!
登录
jinnianshilongnian
浏览:
21305067 次
性别:
最近访客
更多访客>>
qq826928141
cqwb123
twentwo
csj_9_9
博主相关
博客
微博
相册
收藏
留言
关于我
博客专栏
跟我学spring3
浏览量:2378480
Spring杂谈
浏览量:2977237
跟开涛学SpringMVC...
浏览量:5617648
Servlet3.1规范翻...
浏览量:252777
springmvc杂谈
浏览量:1585822
hibernate杂谈
浏览量:246601
跟我学Shiro
浏览量:5826074
跟我学Nginx+Lua开...
浏览量:691523
亿级流量网站架构核心技术
浏览量:771058
文章分类
全部博客 (329)
跟我学Nginx+Lua开发 (13)
跟我学spring (54)
跟开涛学SpringMVC (34)
spring4 (16)
spring杂谈 (50)
springmvc杂谈 (22)
跟我学Shiro (26)
shiro杂谈 (3)
hibernate杂谈 (10)
java开发常见问题分析 (36)
加速Java应用开发 (5)
Servlet 3.1规范[翻译] (21)
servlet3.x (2)
websocket协议[翻译] (14)
websocket规范[翻译] (1)
java web (6)
db (1)
js & jquery & bootstrap (4)
非技术 (4)
reminder[转载] (23)
跟叶子学把妹 (8)
nginx (2)
架构 (19)
flume架构与源码分析 (4)
社区版块
我的资讯 (
10)
我的论坛 (
1112)
我的问答 (
2428)
存档分类
2018-04
1)
2017-06
1)
2016-12
1)
更多存档...
最新评论
xxx不是你可以惹得:
认真看错误代码,有时候重启电脑就行了 醉了 我把数据库配置写死 ...
第十六章 综合实例——《跟我学Shiro》
dagger9527:
holyselina 写道您前面说到能获取调用是的参数数组,我 ...
【第六章】 AOP 之 6.6 通知参数 ——跟我学spring3
xxx不是你可以惹得:
Access denied for user 'root'@' ...
第十六章 综合实例——《跟我学Shiro》
dagger9527:
只有@AspectJ支持命名切入点,而Schema风格不支持命 ...
【第六章】 AOP 之 6.5 AspectJ切入点语法详解 ——跟我学spring3
dagger9527:
支持虽然会迟到,但永远不会缺席!
【第四章】 资源 之 4.3 访问Resource ——跟我学spring3
jinnianshilongnian
第八章 流量复制/AB测试/协程
博客分类: 跟我学Nginx+Lua开发
nginxluacoroutinengx_luaopenresty
阅读更多
流量复制
在实际开发中经常涉及到项目的升级,而该升级不能简单的上线就完事了,需要验证该升级是否兼容老的上线,因此可能需要并行运行两个项目一段时间进行数据比对和校验,待没问题后再进行上线。这其实就需要进行流量复制,把流量复制到其他服务器上,一种方式是使用如tcpcopy引流;另外我们还可以使用nginx的HttpLuaModule模块中的ngx.location.capture_multi进行并发执行来模拟复制。
构造两个服务
location /test1 {
keepalive_timeout 60s;
keepalive_requests 1000;
content_by_lua '
ngx.print("test1 : ", ngx.req.get_uri_args()["a"])
ngx.log(ngx.ERR, "request test1")
';
location /test2 {
keepalive_timeout 60s;
keepalive_requests 1000;
content_by_lua '
ngx.print("test2 : ", ngx.req.get_uri_args()["a"])
ngx.log(ngx.ERR, "request test2")
';
  
通过ngx.location.capture_multi调用
location /test {
lua_socket_connect_timeout 3s;
lua_socket_send_timeout 3s;
lua_socket_read_timeout 3s;
lua_socket_pool_size 100;
lua_socket_keepalive_timeout 60s;
lua_socket_buffer_size 8k;
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/test1", { args = ngx.req.get_uri_args() } },
{ "/test2", { args = ngx.req.get_uri_args()} },
if res1.status == ngx.HTTP_OK then
ngx.print(res1.body)
end
if res2.status ~= ngx.HTTP_OK then
--记录错误
end
';
此处可以根据需求设置相应的超时时间和长连接连接池等;ngx.location.capture底层通过cosocket实现,而其支持Lua中的协程,通过它可以以同步的方式写非阻塞的代码实现。
此处要考虑记录失败的情况,对失败的数据进行重放还是放弃根据自己业务做处理。
AB测试
AB测试即多版本测试,有时候我们开发了新版本需要灰度测试,即让一部分人看到新版,一部分人看到老版,然后通过访问数据决定是否切换到新版。比如可以通过根据区域、用户等信息进行切版本。
比如京东商城有一个cookie叫做__jda,该cookie是在用户访问网站时种下的,因此我们可以拿到这个cookie,根据这个cookie进行版本选择。
比如两次清空cookie访问发现第二个数字串是变化的,即我们可以根据第二个数字串进行判断。
__jda=122270672.1059377902.1425691107.1425691107.1425699059.1
__jda=122270672.556927616.1425699216.1425699216.1425699216.1。
判断规则可以比较多的选择,比如通过尾号;要切30%的流量到新版,可以通过选择尾号为1,3,5的切到新版,其余的还停留在老版。
1、使用map选择版本 
map $cookie___jda $ab_key {
default "0";
~^\d+\.\d+(?P<k>(1|3|5))\. "1";
使用map映射规则,即如果是到新版则等于"1",到老版等于“0”; 然后我们就可以通过ngx.var.ab_key获取到该数据。
location /abtest1 {
if ($ab_key = "1") {
echo_location /test1 ngx.var.args;
if ($ab_key = "0") {
echo_location /test2 ngx.var.args;
此处也可以使用proxy_pass到不同版本的服务器上 
location /abtest2 {
if ($ab_key = "1") {
rewrite ^ /test1 break;
proxy_pass http://backend1;
rewrite ^ /test2 break;
proxy_pass http://backend2;
2、直接在Lua中使用lua-resty-cookie获取该Cookie进行解析
首先下载lua-resty-cookie
cd /usr/example/lualib/resty/
wget https://raw.githubusercontent.com/cloudflare/lua-resty-cookie/master/lib/resty/cookie.lua
location /abtest3 {
content_by_lua '
local ck = require("resty.cookie")
local cookie = ck:new()
local ab_key = "0"
local jda = cookie:get("__jda")
if jda then
local v = ngx.re.match(jda, [[^\d+\.\d+(1|3|5)\.]])
if v then
ab_key = "1"
end
end
if ab_key == "1" then
ngx.exec("/test1", ngx.var.args)
else
ngx.print(ngx.location.capture("/test2", {args = ngx.req.get_uri_args()}).body)
end
';
 首先使用lua-resty-cookie获取cookie,然后使用ngx.re.match进行规则的匹配,最后使用ngx.exec或者ngx.location.capture进行处理。此处同时使用ngx.exec和ngx.location.capture目的是为了演示,此外没有对ngx.location.capture进行异常处理。
协程
Lua中没有线程和异步编程编程的概念,对于并发执行提供了协程的概念,个人认为协程是在A运行中发现自己忙则把CPU使用权让出来给B使用,最后A能从中断位置继续执行,本地还是单线程,CPU独占的;因此如果写网络程序需要配合非阻塞I/O来实现。
ngx_lua 模块对协程做了封装,我们可以直接调用ngx.thread API使用,虽然称其为“轻量级线程”,但其本质还是Lua协程。该API必须配合该ngx_lua模块提供的非阻塞I/O API一起使用,比如我们之前使用的ngx.location.capture_multi和lua-resty-redis、lua-resty-mysql等基于cosocket实现的都是支持的。
通过Lua协程我们可以并发的调用多个接口,然后谁先执行成功谁先返回,类似于BigPipe模型。
1、依赖的API 
location /api1 {
echo_sleep 3;
echo api1 : $arg_a;
location /api2 {
echo_sleep 3;
echo api2 : $arg_a;
 我们使用echo_sleep等待3秒。
2、串行实现
location /serial {
content_by_lua '
local t1 = ngx.now()
local res1 = ngx.location.capture("/api1", {args = ngx.req.get_uri_args()})
local res2 = ngx.location.capture("/api2", {args = ngx.req.get_uri_args()})
local t2 = ngx.now()
ngx.print(res1.body, "
", res2.body, "
", tostring(t2-t1))
';
即一个个的调用,总的执行时间在6秒以上,比如访问http://192.168.1.2/serial?a=22
api1 : 22
api2 : 22
6.0040001869202
3、ngx.location.capture_multi实现
location /concurrency1 {
content_by_lua '
local t1 = ngx.now()
local res1,res2 = ngx.location.capture_multi({
{"/api1", {args = ngx.req.get_uri_args()}},
{"/api2", {args = ngx.req.get_uri_args()}}
})
local t2 = ngx.now()
ngx.print(res1.body, "
", res2.body, "
", tostring(t2-t1))
';
直接使用ngx.location.capture_multi来实现,比如访问http://192.168.1.2/concurrency1?a=22
api1 : 22
api2 : 22
3.0020000934601
    
4、协程API实现 
location /concurrency2 {
content_by_lua '
local t1 = ngx.now()
local function capture(uri, args)
return ngx.location.capture(uri, args)
end
local thread1 = ngx.thread.spawn(capture, "/api1", {args = ngx.req.get_uri_args()})
local thread2 = ngx.thread.spawn(capture, "/api2", {args = ngx.req.get_uri_args()})
local ok1, res1 = ngx.thread.wait(thread1)
local ok2, res2 = ngx.thread.wait(thread2)
local t2 = ngx.now()
ngx.print(res1.body, "
", res2.body, "
", tostring(t2-t1))
';
使用ngx.thread.spawn创建一个轻量级线程,然后使用ngx.thread.wait等待该线程的执行成功。比如访问http://192.168.1.2/concurrency2?a=22
api1 : 22
api2 : 22
3.0030000209808
   
其有点类似于Java中的线程池执行模型,但不同于线程池,其每次只执行一个函数,遇到IO等待则让出CPU让下一个执行。我们可以通过下面的方式实现任意一个成功即返回,之前的是等待所有执行成功才返回。
local ok, res = ngx.thread.wait(thread1, thread2)
Lua协程参考资料
《Programming in Lua》
http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/
https://github.com/andycai/luaprimer/blob/master/05.md
http://my.oschina.net/wangxuanyihaha/blog/186401
http://manual.luaer.cn/2.11.html
5 顶0 踩
分享到:
跟我学OpenResty(Nginx+Lua)开发目录贴
第七章 Web开发实战2——商品详情页
2015-03-07 17:25
浏览 21759
评论(2)
分类:企业架构
查看更多
评论
2 楼
Aceslup
2017-10-25
协程还是不理解哦
1 楼
LinApex
2016-01-03
这个很赞,根据cookie进行部分上线,灰度上线,原理就是这个。
发表评论
您还没有登录,请您登录后再发表评论
相关推荐
tcp/ip测试工具sokit
发送区的编辑框内的字符会按照ascii值发送(多字节字符按照UTF8编码),如果需要发送十六进制原始数据,请将相应数值的ascii表示放进方括号中,例如, [FF AB CD 12 12], 实际发送时会过滤掉方括号本身,以及其中的空格字符...
火山引擎+AB+测试的思考与实践.pdf
火山引擎+AB+测试
learn-ab-and-multivariate-testing, 关于 A/B 和多元测试的教程.zip
learn-ab-and-multivariate-testing, 关于 A/B 和多元测试的教程 A/B &多变量测试教程 这是对和多元测试概念的简短介绍,以及如何启动。 关于如何在 Google内容实验实验中实现这些功能的实际教程,请看我们的概述: ...
ab, 为 A/B 测试,特性斜坡和更多的Etsy框架.zip
ab, 为 A/B 测试,特性斜坡和更多的Etsy框架 AB已经存档AB不再受支持,已经被存档。 请看一下特性 API,代替。 你还可以查看 https://github.com/etsy/ab/tree/pre_archive 站点上的原始源代码。
AB测试与多变量测试[译文]
当我们对网站改版时,往往需要知道优化效果是好还是坏,因此我们可以请用户帮助检测哪个优化方案更加有效,这样的过程即A/B测试。通常用于网站新旧页面的对比。本文讨论如何有效地实践A/B测试。 ● 定义A/B测试 ●...
AB测试工具
apache自带ab工具,可以测试 apache、IIs、tomcat、nginx等服务器 但是ab没有Jmeter、Loadrunner那样有各种场景设计、各种图形报告和监控,只需一个命令即可,有输出描述 可以简单的进行一些压力测试
Lind是一个可以在您的网站上创建任何类型AB测试的开源项目
Lind是一个可以在您的网站上创建任何类型AB测试的开源项目
A/B测试实施方法指南
A/B测试(也称为分离测试)是一种意在提高转换率和反响率的测试方法。通常用于市场营销,比较两个样本的结果。在网页设计中,A/B测试通常用来测试设计元素(有时是针对现有的设计),以便获得访客最好的反响。根据A/B...
用于做ab测试的ab代码
网站测试,ab测试,可以对网站进行压测,测试性能,反应时长
SMI 慧荣3265AC/AB 量产工具
SMI 慧荣3265AC/AB 量产工具
Apache 压力测试工具ab 专注接口测试 并发测试
Apache 压力测试工具ab 专注接口测试 并发测试Apache 压力测试工具ab 专注接口测试 并发测试
pickpick一个用于Web的AB测试引擎
pickpick:一个用于Web的A / B测试引擎
AB测试终极指南
A / B测试丌是一个时髦名词。现在很多有经验的营销和设计工作者用它来获得访客行为信息,来提高转换率。然而, A / B测试不SEO丌同的是,人们都丌太知道徒河迚行网站分析和可用性分析。他们并丌完全明白它是什么戒...
云眼AB测试产品介绍.pdf
云眼AB测试产品介绍.pdf
压力测试工具ab
压力测试小工具,网络接口测试,设置地址、连接数、请求次数。开始测试
小心!A/B测试陷阱小心!AB测试陷阱
AB测试是搜索营销管理员非常喜欢的一种优化手段,但这并非SEM乃至在线营销的专利。本质上这就是可控实验:如果我们想针对SEM管理中的某个因素优化,就必须保持其他因素恒定以过滤掉可能的干扰。 AB测试是搜索营销...
sixpack一个和语言无关的AB测试框架
sixpack:一个和语言无关的 A/B 测试框架
AB测试APACHE
AB 测试 APACHE WEB服务器 负载均衡
django-experiments, Django AB测试模块.zip
django-experiments, Django AB测试模块 django实验 django实验是 Django的AB测试框架。通过模板标签来设置实验是有可能的。 通过 Django 管理,你可以监控和控制实验进度。如果你不知道AB测试是什么,请查看维基...
Nginx+Lua(OpenResty) HelloWorld
2016-04-09 16:23
14136
《使用Nginx+Lua(OpenResty)开发高 ...
Nginx+Lua(OpenResty) HelloWorld
2016-04-09 16:10
《使用Nginx+Lua(OpenResty)开发高性能W ...
使用Nginx+Lua(OpenResty)开发高性能Web应用
2016-03-06 17:13
136164
在互联网公司,Nginx可 ...
跟我学OpenResty(Nginx+Lua)开发目录贴
2015-03-07 17:29
123233
扫一扫,关注我的公众号 
购买地址
  ...
第八章 流量复制/AB测试/协程
2015-03-07 17:23
流量复制
在实际开发中经常涉及到项目的升级,而该升级不能 ...
第七章 Web开发实战2——商品详情页
2015-03-03 21:40
43813
本章以京东商品详情 ...
第六章 Web开发实战1——HTTP服务
2015-03-02 22:05
36034
此处我说的HTTP服务主要指如访问京东网站时我们看到的热门 ...
第五章 常用Lua开发库3-模板渲染
2015-03-01 17:23
27329
动态web网页开发是Web开发中一个常见的场景,比如像京东 ...
第五章 常用Lua开发库2-JSON库、编码转换、字符串处理
2015-02-28 18:46
49691
JSON库
在进行数据传输时JSON格式 ...
第七章 Web示例2——商品详情页2
2015-02-28 11:08
之前《第七章 Web示例2——商品详情页1》已经讲解了基本 ...
第五章 常用Lua开发库1-redis、mysql、http客户端
2015-02-28 09:31
64758
对于开发来说需要有好的生态开发库来辅助我们快速开发,而Lu ...
第四章 Lua模块开发
2015-02-27 10:02
27869
在实际开发中,不可 ...
第七章 Web示例2——商品详情页1
2015-02-26 22:59
本章以京东商品详情 ...
第六章 Web开发示例1——HTTP服务
2015-02-26 12:33
此处我说的HTTP服务主 ...
第三章 Redis/SSDB+Twemproxy安装与使用
2015-02-26 11:39
34723
目前对于互联网公司不使用Redis的很少,Redis不仅仅 ...
第六章 Web开发示例1——HTTP服务
2015-02-26 12:31
此处我说的HTTP服务主要指如访问京东网站时我们看到的热门 ...
第二章 OpenResty(Nginx+Lua)开发入门
2015-02-22 19:16
264230
Nginx入门
本文目的是学习Nginx+Lua开发,对 ...
第五章 常用Lua开发库-模板渲染
2015-02-22 19:14
动态web网页开发是Web开发中一个常见的场景,比如像京东商 ...
第五章 常用Lua开发库-JSON库、编码转换、字符串处理
2015-02-21 11:44
JSON库
在进行数据传输时JSON格式 ...
第五章 常用Lua开发库-redis、mysql、http客户端
2015-02-20 10:48
对于开发来说需要有好的生态开发库来辅助我们快速开发,而Lu ...
Global site tag (gtag.js) - Google Analytics