来,让咱们作一个数据流的"分光镜"吧

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


这是来源在一个网易平台的网络广告推荐算法的更新测试实例。(做者是网易的)
因为推荐算法会不断的更新,若是产生了推送广告不是用户想要的,就会形成很大的负面影响,
那么,使用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");git

相关文章
相关标签/搜索