AbtestingGateway 复制请求到其他服务上
perface
小道一句:本文为原创文章,某SDN博主抄袭我的文章不带出处的。
最近有需求,需要把服务a发给服务b的请求复制给服务c,服务a发给服务b的时候会经过nginx,这个nginx是有lua脚本来辅助工作的。说白了,这个nginx+lua就是abtestingGateway。
架构图如下:
下面看看怎么实现abtestingGateway来复制流量。
分流条件
customercode和user字段的数据都在请求里的json数据里面。
- 匹配到customercode等于我们指定的值后把流量分到服务B。
- 在条件1的基础上,判断是否有users这个字段,有的话服务b,服务C同时发,否则只发服务B。
- 如果没有匹配到customercode,那么就转发到服务C上。
分流策略添加
这个请参考我们的另一篇博文 abtestingGateway 分流策略添加
编写复制请求的代码
我在abtestingGateway下,在customercode.lua(lib/abtesting/diversion目录下)文件里面添加代码
逻辑是这样的:
当abtestingGateway拿到customercode后,从redis里面拿取对应的upstream,如果upstream是服务b的upstream,那么就需要复制流量咯,反之。
所以我们在getUpstream里添加一段代码
_M.getUpstream = function(self, customercode)
if not tostring(customercode) then
return nil
end
local database, key = self.database, self.policyLib
local backend, err = database:hget(key, customercode)
if not backend then error{ERRORINFO.REDIS_ERROR, err} end
if backend == ngx.null then backend = nil end
-- 下面就是新添加的代码 begin
if backend == "newacm" then -- newacm就是我们配置的upstream名字
copyRequest()
end
-- end
local new_acm_uri = ngx.var.new_acm_uri
if new_acm_uri and backend then
backend = backend..new_acm_uri
end
return backend
end
匹配到指定的upstream后,那么就走copyRequest的方法了,代码如下:
_M.copyRequestToOldAcm = function(self)
if ngx.var.copy_switch == "on" then -- 分流开关,on为打开
copyRequest()
end
end
function copyRequest() -- 匹配到我们指定的customerCode以后,那么就复制一份请求发送到老的ACM上,原因是因为发送给老的acm就可新老一块同步数据了
users_exist = false -- 有这个users那么这个标志位为true,没有的话就是false
action = ngx.var.request_method
local postData = ngx.req.get_post_args() --如果post请求里面没有这个customercode参数,
if postData then -- post 请求
local errinfo = ERRORINFO.UNKNOWN_ERROR
if postData then
for k, v in pairs(postData) do --这个k为未json反序列化的数据,v为布尔值
local after_json_k = cjson.decode(k) --提交上来的数据为json格式的,需要反序列化一下
if after_json_k then
for k1 ,v1 in pairs(after_json_k) do
if k1 == "customer" then
if v1.users then
users_exist = true
end
end
end
end
end
end
end
if users_exist == true then --没有匹配到users在post请求数据里,那么就不需要复制一份请求到老的的acm上了,直接return就行了。否则需要复制
log:info("the request has users arguments ,so needn't copy the request to the old acm!")
return false
else
log:info("the request doesn't have users arguments, so need to copy the request to the old acm!")
end
if action == "POST" then
--ngx.req.read_body() -- 解析 body 参数之前一定要先读取 body
local arg = ngx.req.get_post_args() -- post需要参数传递
arry = {method = ngx.HTTP_POST, body = ngx.var.request_body, args=arg}
else
arry = {method = ngx.HTTP_GET}
end
oldacm = ngx.location.capture_multi {
{ "/oldacm" .. ngx.var.request_uri, arry},
}
if oldacm.status == ngx.HTTP_OK then -- 只返回online server的结果
-- ngx.say(online.body)
log:info("copy request result is ok!!")
return true
else
-- ngx.status = ngx.HTTP_NOT_FOUND
--for i,r in pairs(oldacm) do end
log:info("copy request result is failed!! the response body is -->"..oldacm.body)
return false
end
end
然后我们在diversion/diversion.lua里面添加下这段代码,添加的这段代码起到这个作用的,abtestingGateway在运行的时候,只要匹配到了我们的规则,比如customercode=123456,匹配到了customercode=123456,那么abtestingGateway会从redis获取这个规则对应的upstream,然后把这个upstream放在nginx的内存里面,在接下来的60秒以内,只要匹配到规则就直接从内存里面拿取,不走getUpstream这个函数了,所以也触发不了复制请求的代码块了。这就是为什么我们还要添加下面这些代码:
95 local copyRequest = function()
96 local cm = require("abtesting.diversion.customercode")
97 local cr = cm:copyRequestToOldAcm()
98 return cr
99 end
264 local info = "get upstream ["..ups.."] according to ["..idx.."] userinfo ["..usertable[idx].."] in cache 1"
266 log:info(info)
267 if string.find(ups,"newacm") == 1 then
268 copyRequest()
269 end
左边的数字是代码所处的行数,可以参考行数来添加代码。
最后我们需要在nginx的配置文件里面添加oldacm这个location,不然会提示404咯
location /oldacm/ {
proxy_pass http://stable/; # 服务B ip
}
然后重启nginx即可咯。测试,没啥问题。
AbtestingGateway 复制请求到其他服务上的更多相关文章
- [转]在 Azure 云服务上设计大规模服务的最佳实践
本文转自:http://technet.microsoft.com/zh-cn/magazine/jj717232.aspx 英文版:http://msdn.microsoft.com/library ...
- ubuntu安装discourse论坛----结合在apache服务上建立虚拟主机
指导操作:https://github.com/discourse/discourse/blob/master/docs/INSTALL-cloud.md 一.先安装 Docker / Git: wg ...
- SpringCloud学习之Hystrix请求熔断与服务降级(六)
我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...
- 揭秘有状态服务上 Kubernetes 的核心技术
背景 随着 Kubernetes 成为云原生的最热门的解决方案,越来越多的传统服务从虚拟机.物理机迁移到 Kubernetes,各云厂商如腾讯自研上云也主推业务通过Kubernetes来部署服务,享受 ...
- WCF服务上应用protobuf
WCF服务上应用protobuf Web api 主要功能: 支持基于Http verb (GET, POST, PUT, DELETE)的CRUD (create, retrieve, updat ...
- Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件(二)
Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件第二版 上次粗略的写了相同功能的代码,这次整理修复了之前的一些BUG,结构也大量修改 ...
- 利用python httplib模块 发送Post请求测试web服务是否正常起来!
最近在学习python,恰好老大最近让我搞个基于post请求测试web服务是否正常启用的小监控,上网查了下资料,发现强大的Python恰好能够用上,所以自己现学现卖,顺便锻炼下自己. 由于本人也刚接触 ...
- SpringCloud实战-Hystrix请求熔断与服务降级
我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...
- 15分钟在阿里云Kubernetes服务上快速建立Jenkins X Platform并运用GitOps管理应用发布
本文主要介绍如何在阿里云容器服务Kubernetes上快速安装部署Jenkins X Platform并结合demo实践演示GitOps的操作流程. 注意:本文中使用的jx工具.cloud-envir ...
随机推荐
- AngularJS中巧用ngModel的$asyncValidators属性写一个验证唯一性的Direcitve
有这样的一个需求:添加用户的时候,根据主键判断当前添加用户的email是否已经被使用. 为此,我们需要把主键和email来传递给远程的一个API,让API返回结果,告之当前email是否被使用过. 写 ...
- [转载]安装Oracle11gR2先决条件检查失败的详细解决处理过程
原文地址:安装Oracle11gR2先决条件检查失败的详细解决处理过程作者:四海名汀 最近在32位Win7系统下安装Oracle11g发现一系列错误,现将详细的错误解决过程记录如下,以供大家参考. 一 ...
- Win7下MongoDB的安装和使用
Win7下MongoDB的安装和使用 1.下载: http://www.mongodb.org/downloads 2.安装: 安装目录为 D:\mongodb\MongoDB 2.6 Standar ...
- raw_socket(原始套接字)以及普通socket使用终极总结
一.传输层socket(四层socket,普通socket) 可参考本人以下博客: Windows Socket编程之UDP实现大文件的传输:http://blog.csdn.net/luchen ...
- KVM虚拟化管理 virt manager常用操作
部分涉及到Linux.Nginx.tomcat.MySQL等的点滴操作记录,时间长了,就忘掉了,偶尔整理一下操作的history,就此简要备份一下: [原][BG]-一次虚拟化环境实践简要记录: ht ...
- UVA 12293 - Box Game(博弈)
UVA 12293 - Box Game 题目链接 题意:两个盒子,一開始一个盒子有n个球.一个仅仅有1个球,每次把球少的盒子中球消掉,把多的拿一些球给这个盒子.最后不能操作的输(球不能少于1个),A ...
- 结巴分词和自然语言处理HanLP处理手记
手记实用系列文章: 1 结巴分词和自然语言处理HanLP处理手记 2 Python中文语料批量预处理手记 3 自然语言处理手记 4 Python中调用自然语言处理工具HanLP手记 5 Python中 ...
- Windows批处理 调用程序后 不等待子进程 父进程继续执行命令
从DOS过来的老鸟应该都知道批处理,这个功能在WINDOWS中仍然保留着.批处理 说白了就是把一系列DOS命令写在一个文本文件里,然后把这个文件命名为XXX.bat(WINXP以后的系统也可以命名为* ...
- 让div获取焦点
DIV获取焦点有两种方法: tabindex="0" contenteditable="true" ①:设置div为可编辑状态,则可点击获取焦点,同时div的内 ...
- List stream 对象 属性去重
单值去重不写了,记录对象去重 随手一个对象: @Data @AllArgsConstructor public class Milk { private Integer key; private St ...