首页 文章 精选 留言 我的

精选列表

搜索[增量式],共10000篇文章
优秀的个人博客,低调大师

TCPcopy:分布式TCP压力测试工具

线下的传统压力测试,难以模拟真实流量,尤其难以模拟正常流量混杂着各色异常流量。所以,线下压得好好的系统,上线后可能某天突然雪崩,说好能支撑 5 倍流量的系统重构,也许流量一翻倍就彻底挂了。 但办法总比问题多。 系统重构或重要变更上线前,可以拷贝线上真实流量,实时模拟线上流量,甚至可以放大真实流量,进行压力测试,以评估系统承载能力。 反过来也可以这样,如果线上跑着跑着发现有性能瓶颈,但线下环境难以复现,还不如把真实流量拷贝到线下重放,毕竟线下环境便于上各种排查手段,重放几遍都行,直到找到问题。 如何实时拷贝线上真实流量呢?TCPCopy 2010年,网易技术部的王斌在王波的工作基础上开发了 TCPCopy - A TCP Stream Replay Tool。2011年9月开源。当前版本号是 1.0.0。很多公司的模拟在线测试都是基于 TCPCopy 做的,如一淘。 TCPCopy 是一种请求复制(复制基于 TCP 的 packets)工具 ,通过复制在线数据包,修改 TCP/IP 头部信息,发送给测试服务器,达到欺骗测试服务器的TCP 程序的目的,从而为欺骗上层应用打下坚实基础。 TCPCopy是如何工作的 基于 Server 的请求回放领域,一般分为离线回放和在线实时复制两种。 其中请求实时复制,一般可以分为两类: 1)基于应用层的请求复制 , 2)基于底层数据包的请求复制。 如果从应用层面进行复制,比如基于服务器的请求复制,实现起来相对简单,但也存在着若干缺点: 1)请求复制从应用层出发,穿透整个协议栈,这样就容易挤占应用的资源,比如宝贵的连接资源 2)测试跟实际应用耦合在一起,容易影响在线系统, 3)也因此很难支撑压力大的请求复制, 4)很难控制网络延迟。 而基于底层数据包的请求复制,可以做到无需穿透整个协议栈,路程最短的,可以从数据链路层抓请求包,从数据链路层发包,路程一般的,可以在IP层抓请求包,从IP层发出去,不管怎么走,只要不走TCP,对在线的影响就会小得多。这也就是 TCPCopy 的基本思路。 从传统架构的 rawsocket+iptable+netlink,到新架构的 pacp+route,它经历了三次架构调整,现如今的 TCPCopy 分为三个角色: Online Server(OS):上面要部署 TCPCopy,从数据链路层(pcap 接口)抓请求数据包,发包是从IP层发出去; Test Server(TS):最新的架构调整把 intercept 的工作从 TS 中 offload 出来。TS 设置路由信息,把 被测应用 的需要被捕获的响应数据包信息路由到 AS; Assistant Server(AS):这是一台独立的辅助服务器,原则上一定要用同网段的一台闲置服务器来充当辅助服务器。AS 在数据链路层截获到响应包,从中抽取出有用的信息,再返回给相应的 OS 上的 tcpcopy 进程。 tcpcopy项目地址:https://github.com/session-replay-tools/tcpcopy Online Server 上的抓包: tcpcopy 的新架构在 OS 上抓请求数据包默认采用 raw socket input 接口抓包。王斌则推荐采用 pcap 抓包,安装命令如下: yum install libpcap-devel git clone git://github.com/session-replay-tools/tcpcopy.git cd tcpcopy ./configure make make install 这样就可以在内核态进行过滤,否则只能在用户态进行包的过滤,而且在 intercept 端或者 tcpcopy 端设置 filter(通过 -F 参数,类似 tcpdump 的 filter),达到起多个实例来共同完成抓包的工作,这样可扩展性就更强,适合于超级高并发的场合。 为了便于理解 pcap 抓包,下面简单描述一下 libpcap 的工作原理。 一个包的捕捉分为三个主要部分: 面向底层包捕获, 面向中间层的数据包过滤, 面向应用层的用户接口。 这与 Linux 操作系统对数据包的处理流程是相同的(网卡->网卡驱动->数据链路层->IP层->传输层->应用程序)。包捕获机制是在数据链路层增加一个旁路处理(并不干扰系统自身的网络协议栈的处理),对发送和接收的数据包通过Linux内核做过滤和缓冲处理,最后直接传递给上层应用程序。如下图2所示: Online Server 上的发包: 如图1所示,新架构和传统架构一样,OS 默认使用 raw socket output 接口发包,此时发包命令如下: ./tcpcopy -x 80-测试机IP:测试机应用端口 -s 服务器IP -i eth0 其中 -i 参数指定 pcap 从哪个网卡抓取请求包。 此外,新架构还支持通过 pcap_inject(编译时候增加--enable-dlinject)来发包。 Test Server 上的响应包路由: 需要在 Test Server 上添加静态路由,确保被测试应用程序的响应包路由到辅助测试服务器,而不是回包给 Online Server。 Assistant Server 上的捕获响应包: 辅助服务器要确保没有开启路由模式 cat /proc/sys/net/ipv4/ip_forward,为0表示没有开启。 辅助服务器上的 intercept 进程通过 pcap 抓取测试机应用程序的响应包,将头部抽取后发送给 Online Server 上的 tcpcopy 进程,从而完成一次请求的复制。 实验 1.机器别表 192.168.0.11 -- onlie server 192.168.0.12 -- test server 192.168.0.13 -- Assistant server 2.online server操作 安装tcpcopy yum install libpcap-devel git clone git://github.com/session-replay-tools/tcpcopy.git cd tcpcopy ./configure make make install 启动TCPCOPY ./sbin/tcpcopy -x 80-192.168.0.12:80 -s 192.168.0.13 -c 192.168.0.11 -x 参数指定本机哪个端口的流量转发到哪台机器的哪个端口,格式为localip:80-targetip:port -s 参数指定Assistant server -c 指定本机 可以添加-n参数来放大流量,比如说 -n 2 代表放大2倍流量 可以添加-r参数来复制一部分流量。比如说,-r 20 代表复制20%的流量 可以添加-d参数来让tcpcopy后台运行 3.test server操作 route add host 192.168.0.11 gw 192.168.0.13 这一步很重要,之前我就是因为这个路由设置不正确,一直没搭建成功 4.Assistant server操作 安装intercept yum install libpcap-devel git clone git://github.com/session-replay-tools/intercept.git cd intercept ./configure make make install 启动intercept ./sbin/intercept -i eth0 -F tcp and src port 80 -d -i 指定网卡 -F 指定copy的是tcp还是udp -d 代表后台运行 我这里默认online server还有test server都启动了nginx。当你访问online server上的http服务的时候。你会发现test server上也有访问log存在。可以通过监控test server上的负载,来判断机器的运行情况 转自:路飞 PHP后端学习https://mp.weixin.qq.com/s/ycx5XhehhdDVWCgVnROVOg

优秀的个人博客,低调大师

android组件通讯 Intent Filter隐式实现Intent

Intent Filter是android里非常有特色的一个概念。他的用户体验和windows下的文件管理器的弹出菜单里的“打开方式”非常相似。在windows中,当用户选择了打开方式菜单后,系统让用户选择应用来打开所选择的文件。而在android中的文件已经被uri资源代替了。 Intent Filter在android中的应用非常普遍,尤其在资源共享中。例如,当用户选择了一个图片,选择了共享,我们常常会发现一个选择列表。这个选择列表是动态生成的,不是一成不变的。假如你新安装了facebook应用,那么facebook就会出现在这个列表里面。从这个例子可以发现,intent filter的设计使得android系统显得更加灵活了。 要实现一个Intent Filter, 我们要在AndroidManifest.xml中加入必要的设置,以通知系统某个activity都能够处理什么类型的URI资源,然后要在activity的onCreate中加入必要的代码以处理系统传递过来rui资源。 一个Service、 Activity 或者 Brodcast Reciever 的Intent Filter , 的事件过滤器, 我们用着大家都很了然的说法来描述之吧, 实际上描述了拥有这些过滤器组建在系统中所具有能力。 Filter 的创建都是通过 manifest.xml 文件, 但是对于 Broadcast Reciever 用Context.registerReceiver()来创建。Filter 可以包含三种类型的过滤条件 <action> <category> <data> 一个Intent 是否能够通过一个过滤器到达对应的处理器取决于, Intent 所包含的 所有Categroy 是够都在 过滤器中的catergory 列表里出现。 换句话说, 没有 catergory字段的Inteng 可以通过任何过滤器, 而一个过滤器, 必须至少要有一个可以通过的限定,Category 或者 Action。 对于Action 也一样, 能够通过Filter 的Itent的 Action必须被列与 Category中。同样, 没有Action 的Intent 也可以通过所有的Filter。 对于<data>过滤条件稍微复杂点, 但是总的原则还是, 只有Intent 能够通过 Filter, 那么Intent 中的信息,必须出现在Filter中。 <data> 需要指定scheme://host:port/path , 条件顺序的优先级随着范围缩小而降低,相当于,看作目录,在子目录下匹配。比如, Filter指定了 scheme, 那么所有具有这个 scheme 的 Intent 都能通过,这个Filter, 类似的通配符的情况也是允许的。 这里翻译文档中的四个例子情况: a.如果没有定义URI 和数据类型, 则,该Intent只能通过没有定义URI和 数据类型的 过滤器。 b.只定义了URI的 Intent 只能通过只定义了 URI 的过滤器。 c.只定义了 数据类型的 Intent 也只能通过只定义了 数据类型的过滤器。 d. 如果一个Intent同事定义了URI和 数据类型, 或者数据类型可以由URI推定, 则只有具备了对应的数据类型,或者 content: 或者 file: 类型,并且没有定义URI的过滤器。(这种情况, 你自己代码一下就明白了, 在写下去,我也不鸟鸟了。) 如果通向Activities 的Intent 引起了多个响应, 就会出现需要用户指定的提示, 或者是异常。 差不多就是这样的情况了, android 的这种机制非常适合移动设备之间的应用相互调用, 以便在更大的粒度上达成复用。很强大。 /Chapter06_Intent_Filter/src/com/amaker/ch06/app/MainActivity.java 代码 packagecom.amaker.ch06.app; importcom.amaker.ch06.app.R; importandroid.app.Activity; importandroid.content.Intent; importandroid.net.Uri; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; /** * *IntentFilter测试 */ publicclassMainActivityextendsActivity{ //声明Button privateButtonbtn; privatestaticfinalStringACTION1="com.amaker.ch06.app.TEST_ACTION1"; privatestaticfinalStringACTION2="com.amaker.ch06.app.TEST_ACTION2"; privatestaticfinalStringACTION3="com.amaker.ch06.app.TEST_ACTION3"; privatestaticfinalStringCATEGORY1="com.amaker.ch06.app.CATEGORY1"; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //设置内容布局 setContentView(R.layout.main); //实例化按钮 btn=(Button)findViewById(R.id.Button01); Stringa=Intent.ACTION_VIEW; //添加单击监听器 btn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewview){ Intentintent=newIntent(); //intent.setAction(ACTION1); //Uridata=Uri.parse("content://com.amaker.ch07.app/abc"); //intent.setData(data); intent.addCategory(CATEGORY1); intent.setAction("android.intent.action.VIEW"); intent.setData(Uri.parse("http://www.google.com")); startActivity(intent); } }); } } /Chapter06_Intent_Filter/src/com/amaker/ch06/app/TestActivity.java 代码 packagecom.amaker.ch06.app; importcom.amaker.ch06.app.R; importandroid.app.Activity; importandroid.os.Bundle; /** *测试IntentFilter */ publicclassTestActivityextendsActivity{ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main1); } } /Chapter06_Intent_Filter/res/layout/main.xml 代码 <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:text="测试IntentFilter" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout> /Chapter06_Intent_Filter/res/layout/main1.xml 代码 <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:text="测试IntentFilter" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> </LinearLayout> /Chapter06_Intent_Filter/AndroidManifest.xml 代码 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.amaker.ch06.app" android:versionCode="1" android:versionName="1.0"> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activityandroid:name="TestActivity"> <intent-filter> <actionandroid:name="com.amaker.ch06.app.TEST_ACTION1"/> <actionandroid:name="com.amaker.ch06.app.TEST_ACTION2"/> <actionandroid:name="com.amaker.ch06.app.TEST_ACTION3"/> <actionandroid:name="android.intent.action.VIEW"/> <dataandroid:scheme="content"android:path="com.amaker.ch07.app/abc"/> <dataandroid:scheme="http"android:path="www.google.com"/> <categoryandroid:name="android.intent.category.DEFAULT"/> <categoryandroid:name="android.intent.category.BROWSABLE"/> <categoryandroid:name="com.amaker.ch07.app.CATEGORY1"/> </intent-filter> </activity> </application> <uses-sdkandroid:minSdkVersion="3"/> </manifest> 本文转自linzheng 51CTO博客,原文链接:http://blog.51cto.com/linzheng/1080659

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册