文档章节

来,让我们做一个数据流的"分光镜"吧

 自由的眼
发布于 2016/12/13 10:38
字数 2553
阅读 45
收藏 0
点赞 0
评论 0

前一段时间,写过一篇帖子,http://eip.teamshub.com/t/3245814
里面最后提到了一种数据"分光镜"的技术。
今天我就来说说这个东东到底是什么,以及怎么运用。
当年习惯性的在QQ上搜索技术群,尤其是服务器技术的群,其中吹水的很多,加了看了几天就退了。被朋友推荐加入了一个tcpcopy的群(这个群那时候需要推荐才能加入),刚加入这个群的时候,6天没一个人说话。正准备放弃的时候,看到了群主的github连接,于是上去看了一眼。
似乎是一个类似抓包的开源工具,我感兴趣的是那几千个star为什么会给一个这样的工具。
于是和群主聊天,开始研究它的技术实现,最终发现,这确实是一个不得了的东西。
有幸和群主一起约出来吃饭,更加深入了解了这个东西的用途,这个东西很多大公司都在使用,确实起到了很好的测试效果。我开始在我的项目中使用,起到了非常好的效果。
数据分光镜是什么呢?
它解决的是"开发 - 测试 -运维"一条线上的信任关系。
开发不断的出新的迭代,传统的测试,往往通过测试工具,覆盖一定的场景,但是不可能完美覆盖所有的场景,导致了运维没次上线系统更新都是心惊胆战,生怕出什么篓子,从此往复循环,大家都活的很累。
而实际线上的数据流动多种多样,几乎可以覆盖各种情况,远远超过了传统测试能覆盖的测试结果。
那么,我们有没有一种方式,将在线的巨大流量,在不知不觉中导入到我的迭代的新系统中去呢?从而完成线上测试?
答案是可以的,我们需要将在线的数据流量,神不知鬼不觉的复制出来一份(类似光学的分光,你可以把数据变成一种光),传递给我的更新服务器,从而做到压力测试。
那么你可能会有一个疑问,我复制过去的流量,那么返回数据流量如何处理?其实很简单,在Linux下,使用IP Route规则做一个"黑洞",把哪些不必要的数据"吸"入黑洞就可以了。这样,在线数据什么都不会受到影响,同时,导出的流量,足足可以验证你的新上线的服务器是否稳定。当然,你也可以用此调试BUG,比如一个能引起服务器崩溃的BUG,在生产环境下不可停机的基础上,我们导入流量到测试服务器上,在测试服务器上做BUG的验证,极大的减轻了测试和运维的压力,同时也可以给程序员增加上线的信心。
来让我们看一张图,看看tcpcopy是怎么做的。


这是来源在一个网易平台的网络广告推荐算法的更新测试实例。(作者是网易的)
由于推荐算法会不断的更新,如果产生了推送广告不是用户想要的,就会造成很大的负面影响,
那么,使用tcpcopy,实际就可以将在线流量导入到每次的测试服务器上运行,即可得到相应的测试结果。
tcpcopy实际上不止可用在http,所有的tcp基础数据包也支持。比如一些硬件的数据流,视频流等等。当初我和作者开始开发适合于tcp任意数据包的数据流格式,并获得了成功。
它的实现是利用底层的数据抓包,直接从物理层链路抓数据,并修改包中关于IP指向的部分(将原有指向当前服务器的地址信息修改成测试主机的IP信息,并修改路由信息将数据跳到测试主机上去。前提是测试主机必须和生产环境在一个网段上)
那么,生产环境的数据流,就会被自动分成两份,一份流向当前正常的生产环境。另一份流向测试服务器。
那么,在测试服务器上,我们也需要做一些工作,设置回流的路由"中断",毕竟,我们不希望测试的服务器返回数据干扰生产环境,所以,我们必须做一个"黑洞",把测试服务器返回的数据全部吸收掉。
怎么做这个黑洞呢?我们需要设置一条路由规则,让返回的数据走到一个其它的IP上面去,在这个IP上把数据丢弃即可。同时,返回上层tcp发送"成功"。欺骗测试服务器网络一切正常,实际上返回的数据因为不存在的IP在底层被丢弃掉了。只是测试服务器不知道而已。
例如,具体事例,可以参考这里(http://www.cnblogs.com/tommyli/p/4239570.html)
之所以再说一遍,是因为这篇文章的顺序有问题,如果按照它的顺序,会造成一部分数据回流到正式环境,所以,步骤很重要,在这里强调一下,别被坑了。
第一步先制造数据黑洞,保证测试主机数据不能流回生产环境。
route add -net 192.168.100.0 netmask 255.255.255.0 gw 10.53.132.52
数据黑洞就造成了。
intercept -i eth1 -F tcp and src port 8090 -d当然,如果你的测试服务器被拿下干别的事情,最好恢复一下路由,否则会对别人不知情的使用者造成数据发送的困扰,切记。
那么,黑洞设置完了,我们看看怎么设置在线服务器。
先需要在在线服务器上安装tcpcopy,建议使用源代码编译安装方式,因为代码会根据环境进行一些优化的配置。
然后运行
tcpcopy -x 8090-10.53.132.55:8090 -s 10.53.132.52 -c 192.168.100.x -n 5
这里的一些参数,我需要说明一下
直接上源码来的快些,实际上,它可以支持不止是指定端口转发那么简单,还可以根据规则决定生产环境的那些数据被转发,那些不转发,真正起到"分光"的作用,那就是后话了。
    printf("tcpcopy " VERSION "\n");
#if (!TC_PCAP_SND)
    printf("-x use to specify the IPs and ports of the source and target\n"
           "               servers. Suppose 'sourceIP' and 'sourcePort' are the IP and port \n"
           "               number of the source server you want to copy from, 'targetIP' and \n");
    printf("               'targetPort' are the IP and port number of the target server you want\n"
           "               to send requests to, the format of could be as follows:\n"
           "               'sourceIP:sourcePort-targetIP:targetPort,...'. Most of the time,\n");
    printf("               sourceIP could be omitted and thus could also be:\n"
           "               'sourcePort-targetIP:targetPort,...'. As seen, the IP address and the\n"
           "               port number are segmented by ':' (colon), the sourcePort and the\n");
    printf("               targetIP are segmented by '-', and two 'transfer's are segmented by\n"
           "               ',' (comma). For example, './tcpcopy -x 80-192.168.0.2:18080' would\n"
           "               copy requests from port '80' on current server to the target port\n"
           "               '18080' of the target IP '192.168.0.2'.\n");
#else
    printf("-x use to specify the IPs, ports and MAC addresses of\n"
           "               the source and target. The format of could be as follow:\n");
    printf("               'sourceIP:sourcePort@sourceMac-targetIP:targetPort@targetMac,...'.\n"
           "               Most of the time, sourceIP could be omitted and thus could\n"
           "               also be: sourcePort@sourceMac-targetIP:targetPort@targetMac,...'.\n");
    printf("               Note that sourceMac is the MAC address of the interface where \n"
           "               packets are going out and targetMac is the next hop's MAC address.\n");
#endif
    printf("-H   change the localhost IP address to the given IP address\n");
    printf("-c  change the client IP to one of IP addresses when sending to the\n"
           "               target server. For example,\n"
           "               './tcpcopy -x 8080-192.168.0.2:8080 -c 62.135.200.x' would copy\n"
           "               requests from port '8080' of current online server to the target port\n"
           "               '8080' of target server '192.168.0.2' and modify the client IP to be\n"
           "               one of net 62.135.200.0/24.\n");
#if (TC_OFFLINE)
    printf("-i      set the pcap file used for tcpcopy to (only valid for the\n"
           "               offline version of tcpcopy when it is configured to run at\n"
           "               enable-offline mode).\n");
    printf("-a       accelerated times for offline replay\n");
    printf("-I       set the threshold interval for offline replay acceleration\n"
           "               in millisecond.\n");
#endif
#if (TC_PCAP)
    printf("-i   The name of the interface to listen on. This is usually a driver\n"
           "               name followed by a unit number, for example eth0 for the first\n"
           "               Ethernet interface.\n");
    printf("-F    user filter (same as pcap filter)\n");
    printf("-B       buffer size for pcap capture in megabytes(default 16M)\n");
    printf("-S   capture bytes per packet\n");
#endif
#if (TC_PCAP_SND)
    printf("-o   The name of the interface to send. This is usually a driver\n"
           "               name followed by a unit number, for example eth0 for the first\n"
           "               Ethernet interface.\n");
#endif
    printf("-n       use to set the replication times when you want to get a \n"
           "               copied data stream that is several times as large as the online data.\n"
           "               The maximum value allowed is 1023. As multiple copying is based on \n"
           "               port number modification, the ports may conflict with each other,\n");
    printf("               in particular in intranet applications where there are few source IPs\n"
           "               and most connections are short. Thus, tcpcopy would perform better \n"
           "               when less copies are specified. For example, \n"
           "               './tcpcopy -x 80-192.168.0.2:8080 -n 3' would copy data flows from \n");
    printf("               port 80 on the current server, generate data stream that is three\n"
           "               times as large as the source data, and send these requests to the\n"
           "               target port 8080 on '192.168.0.2'.\n");
    printf("-f       use this parameter to control the port number modification process\n"
           "               and reduce port conflications when multiple tcpcopy instances are\n"
           "               running. The value of should be different for different tcpcopy\n"
           "               instances. The maximum value allowed is 1023.\n");
    printf("-m       set the maximum memory allowed to use for tcpcopy in megabytes, \n"
           "               to prevent tcpcopy occupying too much memory and influencing the\n"
           "               online system. When the memory exceeds this limit, tcpcopy would quit\n"
           "               automatically. The parameter is effective only when the kernel \n");
#if (TC_MILLION_SUPPORT)
    printf("               version is 2.6.32 or above. The default value is 4096.\n");
#else
    printf("               version is 2.6.32 or above. The default value is 1024.\n");
#endif
    printf("-M       MTU value sent to backend (default 1500)\n");
    printf("-D       MSS value sent back(default 1460)\n");
    printf("-R       set default rtt value\n");
    printf("-U       set user session pool size in kilobytes(default 1).\n"
           "               The maximum value allowed is 63.\n");
    printf("-C       parallel connections between tcpcopy and intercept.\n"
           "               The maximum value allowed is 11(default 2 connections).\n");
    printf("-s   intercept server list\n"
           "               Format:\n"
           "               ip_addr1:port1, ip_addr2:port2, ...\n");
    printf("-t       set the session timeout limit. If tcpcopy does not receive response\n"
           "               from the target server within the timeout limit, the session would \n"
           "               be dropped by tcpcopy. When the response from the target server is\n"
           "               slow or the application protocol is context based, the value should \n"
           "               be set larger. The default value is 120 seconds.\n");
    printf("-k       set the session keepalive timeout limit.\n");
    printf("-l      save the log information in \n"
           "-r       set the percentage of sessions transfered (integer range:1~100)\n"
           "-p       set the target server listening port. The default value is 36524.\n");

© 著作权归作者所有

共有 人打赏支持
粉丝 0
博文 9
码字总数 16565
作品 1
西城
技术主管
物理界科学无法解释现象:因果可以倒置,当下可以改变曾经

  物理学中有趣的实验是双缝干涉实验,它证明了光具有波粒二象性;更有趣的实验是单粒子双缝干涉实验,它表明:物体在产生与探测的奇怪过渡间,可能并不是明确存在的,甚至不是真正的粒子,...

科学解说家 ⋅ 01/02 ⋅ 0

HTTP 400 错误 - 请求无效 (Bad request)

介绍 您的Web服务器认为客户端发送的数据流 (例如您的浏览器或我们的 CheckUpDown 机器人 ) 是 ' 畸形的',即没有完全遵守 HTTP 协议。 因此您的 Web 服务器无法理解和处理该请求。 该错误几...

五大三粗 ⋅ 2015/11/12 ⋅ 0

Rxjs实践-各种排序算法排序过程的可视化展示

这几天学习下《算法》的排序章节,具体见对排序的总结,想着做点东西,能将各种排序算法的排序过程使用Rxjs通过可视化的方式展示出来,正好练系一下Rxjs的使用 本文不会太多介绍Rxjs的基本概念...

xiyuyizhi ⋅ 2017/10/27 ⋅ 0

Head First C 第十章 进程间通信 创建管道

Head First C 第十章 进程间通信 创建管道 我们已经可以通过重定向的方式,将子进程的输出重定向到文件,但我们想从进程中直接读取数据,如何使实现。 用管道连接进程 我们曾经用一个命令来连...

AlexTuan ⋅ 2016/04/10 ⋅ 0

精读《dob - 框架使用》

本系列分三部曲:《框架实现》 《框架使用》 与 《跳出框架看哲学》,这三篇是我对数据流阶段性的总结,正好补充之前过时的文章。 本篇是 《框架使用》。 1 引言 现在我们团队也在重新思考数...

黄子毅 ⋅ 2017/12/31 ⋅ 0

storm自定义数据分组

数据流组 设计一个拓扑时,你要做的最重要的事情之一就是定义如何在各组件之间交换数据(数据流是如何被bolts消费的)。一个数据流组指定了每个bolt会消费哪些数据流,以及如何消费它们。 st...

张欢19933 ⋅ 2016/01/26 ⋅ 0

可视化在线编辑器架构设计

1 背景 本文开发框架基于 React,涉及 React 部分会对背景做简单铺垫。 前端开源江湖非常有意思,竞争是公平的,而且不需要成本,任何一个初入茅庐的学徒都可以找江湖高手过招,且迟早会自成...

黄子毅 ⋅ 2016/11/30 ⋅ 0

Angular 中的响应式编程 -- 浅淡 Rx 的流式思维

在 Rx--隐藏在Angular 2.x中利剑 一文中我们已经初步的了解了 Rx 和 Rx 在 Angular 的应用。 今天我们一起通过一个具体的例子来理解响应式编程设计的思路。最后会看看刚刚发布的 Angular 4 ...

接灰的电子产品 ⋅ 2017/03/31 ⋅ 0

RxJava && Agera 从源码简要分析基本调用流程(1)

版权声明:本文由晋中望原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/123 来源:腾云阁 https://www.qcloud.com/community 相信很多做Android或是Jav...

偶素浅小浅 ⋅ 2016/11/04 ⋅ 0

面向未来的前端数据流框架 - dob

我们数据技术产品部有一部分只需要兼容最新版 chrome 对外产品,以及大部分对内产品,都广泛使用了 dob 管理前端数据流,下面隆重介绍一下。 dob 是利用 proxy 实现的数据依赖追踪工具,利用...

黄子毅 ⋅ 2017/11/03 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

如何优雅的编程——C语言界面的一点小建议

我们鼓励在编程时应有清晰的哲学思维,而不是给予硬性规则。我并不希望你们能认可所有的东西,因为它们只是观点,观点会随着时间的变化而变化。可是,如果不是直到现在把它们写在纸上,长久以...

柳猫 ⋅ 38分钟前 ⋅ 0

从零手写 IOC容器

概述 IOC (Inversion of Control) 控制反转。熟悉Spring的应该都知道。那么具体是怎么实现的呢?下面我们通过一个例子说明。 1. Component注解定义 package cn.com.qunar.annotation;impo...

轨迹_ ⋅ 39分钟前 ⋅ 0

系统健康检查利器-Spring Boot-Actuator

前言 实例由于出现故障、部署或自动缩放的情况,会进行持续启动、重新启动或停止操作。它可能导致它们暂时或永久不可用。为避免问题,您的负载均衡器应该从路由中跳过不健康的实例,因为它们...

harries ⋅ 40分钟前 ⋅ 0

手把手教你搭建vue-cli脚手架-详细步骤图文解析[vue入门]

写在前面: 使用 vue-cli 可以快速创建 vue 项目,vue-cli很好用,但是在最初搭建环境安装vue-cli及相关内容的时候,对一些人来说是很头疼的一件事情,本人在搭建vue-cli的项目环境的时候也是...

韦姣敏 ⋅ 51分钟前 ⋅ 0

12c rman中输入sql命令

12c之前版本,要在rman中执行sql语句,必须使用sql "alter system switch logfile"; 而在12c版本中,可以支持大量的sql语句了: 比如: C:\Users\zhengquan>rman target / 恢复管理器: Release 1...

tututu_jiang ⋅ 今天 ⋅ 0

Nginx的https配置记录以及http强制跳转到https的方法梳理

Nginx的https配置记录以及http强制跳转到https的方法梳理 一、Nginx安装(略) 安装的时候需要注意加上 --with-httpsslmodule,因为httpsslmodule不属于Nginx的基本模块。 Nginx安装方法: ...

Yomut ⋅ 今天 ⋅ 0

SpringCloud Feign 传递复杂参数对象需要注意的地方

1.传递复杂参数对象需要用Post,另外需要注意,Feign不支持使用GetMapping 和PostMapping @RequestMapping(value="user/save",method=RequestMethod.POST) 2.在传递的过程中,复杂对象使用...

@林文龙 ⋅ 今天 ⋅ 0

如何显示 word 左侧目录大纲

打开word说明文档,如下图,我们发现左侧根本就没有目录,给我们带来很大的阅读障碍 2 在word文档的头部菜单栏中,切换到”视图“选项卡 3 然后勾选“导航窗格”选项 4 我们会惊奇的发现左侧...

二营长意大利炮 ⋅ 今天 ⋅ 0

智能合约编程语言Solidity之线上开发工具

工具地址:https://ethereum.github.io/browser-solidity/ 实例实验: 1.创建hello.sol文件 2.调试输出结果

硅谷课堂 ⋅ 今天 ⋅ 0

ffmpeg 视频格式转换

转 Mp4 格式 #> ffmpeg -i input.avi -c:v libx264 output.mp4#> ffmpeg -i input.avi -c:v libx264 -strict -2 output.mp4#> ffmpeg -i input.avi -c:v libx264 -strict -2 -s 1......

Contac ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部