perface

小道一句:本文为原创文章,某SDN博主抄袭我的文章不带出处的。

最近有需求,需要把服务a发给服务b的请求复制给服务c,服务a发给服务b的时候会经过nginx,这个nginx是有lua脚本来辅助工作的。说白了,这个nginx+lua就是abtestingGateway。

架构图如下:

下面看看怎么实现abtestingGateway来复制流量。

分流条件

customercode和user字段的数据都在请求里的json数据里面。

  1. 匹配到customercode等于我们指定的值后把流量分到服务B。
  2. 在条件1的基础上,判断是否有users这个字段,有的话服务b,服务C同时发,否则只发服务B。
  3. 如果没有匹配到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 复制请求到其他服务上的更多相关文章

  1. [转]在 Azure 云服务上设计大规模服务的最佳实践

    本文转自:http://technet.microsoft.com/zh-cn/magazine/jj717232.aspx 英文版:http://msdn.microsoft.com/library ...

  2. ubuntu安装discourse论坛----结合在apache服务上建立虚拟主机

    指导操作:https://github.com/discourse/discourse/blob/master/docs/INSTALL-cloud.md 一.先安装 Docker / Git: wg ...

  3. SpringCloud学习之Hystrix请求熔断与服务降级(六)

    我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...

  4. 揭秘有状态服务上 Kubernetes 的核心技术

    背景 随着 Kubernetes 成为云原生的最热门的解决方案,越来越多的传统服务从虚拟机.物理机迁移到 Kubernetes,各云厂商如腾讯自研上云也主推业务通过Kubernetes来部署服务,享受 ...

  5. WCF服务上应用protobuf

    WCF服务上应用protobuf Web api  主要功能: 支持基于Http verb (GET, POST, PUT, DELETE)的CRUD (create, retrieve, updat ...

  6. Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件(二)

    Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件第二版 上次粗略的写了相同功能的代码,这次整理修复了之前的一些BUG,结构也大量修改 ...

  7. 利用python httplib模块 发送Post请求测试web服务是否正常起来!

    最近在学习python,恰好老大最近让我搞个基于post请求测试web服务是否正常启用的小监控,上网查了下资料,发现强大的Python恰好能够用上,所以自己现学现卖,顺便锻炼下自己. 由于本人也刚接触 ...

  8. SpringCloud实战-Hystrix请求熔断与服务降级

    我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...

  9. 15分钟在阿里云Kubernetes服务上快速建立Jenkins X Platform并运用GitOps管理应用发布

    本文主要介绍如何在阿里云容器服务Kubernetes上快速安装部署Jenkins X Platform并结合demo实践演示GitOps的操作流程. 注意:本文中使用的jx工具.cloud-envir ...

随机推荐

  1. java中动态给sql追加?号

    /* * 用来生成where子句 len数组的长度 */ private String toWhereSql(int len) { StringBuilder sb = new StringBuild ...

  2. 我的 Sublime Text 2 笔记

    作为aptana死忠粉的我,最近由于工作需要最近开始使用sublime,初次使用,就被其秒开的启动速度,简洁的界面设计,无干扰的信息提示所这幅. 俗话说,工欲善其事必先利其器,作为码农,在开始编码之前 ...

  3. bzoj 3924 点分

    感谢asm.Definer清楚明了的题解: http://www.cnblogs.com/Asm-Definer/p/4470112.html 收获: 1.  关于重心, 对于一个无向图, 我们这样给 ...

  4. Filebeat 快速开始

    Filebeat可以做什么 条目 filebeat 编写语言 GO 是否支持多输出 支持 是否支持多输入 支持 是否支持修改日志内容 支持 是否会丢数据 不会 对多行文件的合并 支持 对多层目录的模糊 ...

  5. spring源码分析系列

    spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor.BeanDefinitionRegistryPostProcessor spring源码分析系列 ...

  6. ubuntu jdk 安装

    sudo add-apt-repository ppa:linuxuprising/java sudo apt-get update sudo apt-get install oracle-java1 ...

  7. Web 前端面试题整理(不定时更新)

    重要知识需要系统学习.透彻学习,形成自己的知识链.万不可投机取巧,临时抱佛脚只求面试侥幸混过关是错误的! 面试有几点需注意: 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增 ...

  8. JVM内存区域的划分(内存结构或者内存模型)

    JVM内存区域的划分(内存结构或者内存模型)   运行时数据区域: 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 程序计数器(线程私有): 是当前线程所 ...

  9. OpenGL核心技术之HDR

    笔者介绍:姜雪伟.IT公司技术合伙人,IT高级讲师,CSDN社区专家.特邀编辑,畅销书作者.国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  10. python 网络工具 scapy 介绍

    作者介绍,这是个万能的网络工具,除了可以查看 TCP/IP 各层的报文,还可以发送报文.可以说是一个万能工具,作者嚣张的说, “it can replace hping, 85% of nmap, a ...