iNeedle系统之国舜项目
一、简介
本周公司接了一个小项目,是给北京国舜科技股份有限公司做一个HTTP相关的小功能产品。大概实现功能是将交换机的源数据通过解析,分析出HTTP包配对的request和response头,并把每对的request和response头相关字段内容,通过TCP方式发送给对方的指定的服务器。
二、要求
需要一台流量设备来抓取分析交换机中的数据,流量设备通过推送的方式将解析后的数据发送到我们平台,平台基于数据进行分析,关于流量设备有下边几个需求:
1、流量设备
a.需要同时支持双向(流出,流入)流量分析
b.需能支持千兆网峰值流量
2、双方对接方案
采用TCP长连接对接,也就是通过socket以TCP长连接方式向对方服务器发送指定格式的数据内容,对方以相应的格式进行解析即可。
3、发送数据包格式
1: typedef struct {
2: unsigned int magic; // =0x4458434A,即“DXCJ”,用于同步时重新找到一个消息起始点
3: unsigned int length; // 负载数据的长度
4: char *data; // 实际数据内容
5: }
6: // 即之前定义的按照需求文档中2张表的顺序\t分隔的请求+响应数据,长度为length,之后即下一条消息的magic字段
.codearea{ color:black; background-color:white; line-height:18px; border:1px solid #4f81bd; margin:0; width:auto !important; width:100%; overflow:auto; text-align:left; font-size:12px; font-family: "Courier New","Consolas","Fixedsys","BitStream Vera Sans Mono", courier,monospace,serif}
.codearea pre{ color:black; line-height:18px; padding:0 0 0 12px !important; margin:0em; background-color:#fff !important}
.linewrap pre{white-space:pre-wrap; white-space:-moz-pre-wrap; white-space:-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word; word-break:normal}
.codearea pre.alt{ background-color:#f7f7ff !important}
.codearea .lnum{color:#4f81bd;line-height:18px}
注意:对于magic和length字段需要考虑网络字节序问题,我们设备都是小端字节序,对方要求是大端字节序,网络字节序也是大端字节序,最后转换为网络字节序传输即可。我们这边是用C语言发送数据,对方接收端程序是java语言写的,不过这都无所谓了,底层协议都是标准的,可以相互通信。
4、负载均衡
对方接收数据端会有多个主机进行数据的接收,因此存在多主机负载均衡的问题。可以通过设置配置文件,内容大概以这样的形式:host:port,多个主机就存在多个列表。这个配置文件由双方来协商,可以由对方来配置,也存在对方后续会不定时的添加主机或修改主机的情况。在发送数据时,使用轮询调度(Round-Robin Scheduling)将流量分发到各个节点上。例如,若有3个节点,发送4个消息,按如下顺序: 给节点1发一条消息,再给节点2发一条消息,再给节点3发一条消息,再从节点1开始继续循环,实现简单的负载均衡。
同时需要支持失败重试,比如3个节点有一个节点宕了,那么我这边会尽快启动,启动之前流量由另两个节点处理。待失败节点启动后,再次3台机器同时工作;通过长连接端口来判定节点失败。
5、数据格式
需求的字段有很多,有一部分字段需要额外重新解析,解析完毕各个字段之后需要以指定的格式进行发送;一个请求各字段间依照上述2个表序号顺序使用\t拼接为一整行作为一条消息发送。如果某个字段为空,不做忽略。例如,假如3个字段:Name\tAge\tAddress 如果Age为空,分隔符保留。则输出:Name\t\tAddress即可,如:liming\t\tchangpingqu。
三、实现方式
本功能实际上并不复杂,完全可以在ineedle系统基础之上做一些简单修改,形成数据消息,然后发送给对方即可。关于ineedle后续的额外功能可以摘除,以提高整个ineedle系统的效率。
四、方案设计
总共有4部分需要修改或添加
1、HTTP的请求头和相应头字段
因为之前ineedle解析的相关字段是根据后续分析需求而定的,比较少,并不全面;而这次对方需求中的字段有一大部分在ineedle中是没有的,需要再额外再次进行解析。需要在ineedle系统中的相应解码代码中作出相应的解码工作,解码方式还按照原来的实现方式,只是添加些而已,然后挂到相应mbuf上,供后续sess使用。当然首要工作还是要对这58个字段(后续又增加7个字段)进行查找和分析,找出这些字段的经典取值,以及相关作用,用于后续代码中buf长度的判断,最终暂时定为(1024*8字节)大小。
2、定时刷新主机列表
这一部分可以在ineedle系统中原来flt_main进程中的某个定时线程中做,初次可以设置为10秒钟定时周期。主要定时刷新主机:端口列表是否有修改,或者判断是否有宕机设备重新启动。在刷新主机列表之前要判断一下配置文件host_list的时间戳是否变化,如果没有变化说明这段时间内用户没有更新主机列表,我们在程序中就不会再更新主机列表。还有一点就是用来重新复活之前宕机的设备,原理是这样的,如果某个设备宕机,就加入黑名单列表,就是在激活主机列表中将该主机alive标志位置1,表示宕机,后续不再往该设备上发送消息,直到用户重启该设备并定时器刷新复活。因此如果存在一个或多个设备宕机之后,用户将设备启动之后,需要做一个操作就是修改host_list文件的时间戳,简单touch一下就行,如果不touch的话,再没有修改host_list文件内容情况下,我们程序就不会重新刷新主机列表,也就不会再复活宕机而又重启的设备,这个条件到时候要提醒对方一定要做这个操作,否则单单重启宕机设备可能是无效的。这个地方原来是这样设计的,但是对方设备不仅可能会存在宕机情况,比如也可能是程序挂掉等,也是不能通信的,这种情况发生的几率还是比较大的,不能使用上述方式来搞,比较麻烦,每次都需要用户来ssh登陆并操作,这样可能本身就是一个缺陷,现在决定暂时放弃这个做法,也就是不去判断配置文件的时间戳,每次直接去读取配置主机列表,这样应该不会有太多性能消耗,不会有太大影响。
3、HTTP报文的request和reponse配置向队列写消息
这部分不用修改太多东西,主要是将分析到的request头和response头的相关字段,组合成指定格式的消息并发送给我们的缓存队列里边。存在一点问题,就是原来的ineedle每次解析完request和response头相关信息后都是挂在mbuf结构体上,比如上次解析的request头信息挂载mbuf上,下次到response包解析时,会把上次的mbuf清空,来填写这次response报文解析的数据,因此这时得不到完整的req和res的组合信息。因此需要将req和res信息挂到sess上,因为req和res在共同的sess上,因此可以读到上次的信息,并在第二次读到正确的res包时,进行req和res数据的组合,组合完毕将数据拷贝到缓冲数组。需要注意的是一个sess中可能有多个req和res,注意后边的req和res要把前边的数据覆盖掉,保证数据清零,不要让上次数据影响到这次的数据。这里实现的一下细节,需要在mbuf中添加一些需要额外解析的字段,而且在sess表结构中添加http_req_res_buf来存储一对请求响应的数据内容。组合完毕,在发送到数据队列中。
4、启动单独线程发送消息
另外单独启动一个线程来读取缓冲队列的消息,并按照主机列表的顺序通过socket TCP方式依次发送到相应主机上,如果遇到主机宕机情况,将其加入黑名单,并后续不发送数据给它。理论上是这样,要考虑接收主机的负载均衡。通过定时不断刷新,如果之前宕机程序又重新启动,需要重新尝试连接该主机并连接tcp并继续向该主机发送消息。从缓存队列读取消息并发送消息过程,完全类似一个生产者与消费者的模型,考虑到数据读写的互斥操作,读写线程之间要用线程的条件变量和线程锁来实现互斥的功能。
五、详细设计
这里就详细介绍一下,这几部分的详细设计实现细节。
1、解码http请求和响应字段数据
这一部分没有什么特别需要注意的地方,严格参考之前的解码方式,对比原来方案,实现代码编写,然后将生成解码的值挂到mbuf结构体上。这时就需要在mbuf结构体上添加需要的字段,待后续sess汇总时要用到,其实这时候tcp连接已经完全建立,sess表已经存在,完全可以将解析的字段值直接挂到sess表上,但是这样做有点混乱,没有严格按照之前的代码方案,所以最好的方式还是按照前边的方式比较好。
2、定时刷新主机列表
定时10秒间隔不停刷新主机列表。
3、汇总req和res并向缓冲队列写消息
4、发送线程不断发送消息
六、编码工作
。。。。。。暂时可以参考代码
七、编码中遇到的问题
01、问题1 ---- MSG_NOSIGNAL
在tcp编程过程中,测试代码时,发现如果服务器端被关闭,则client端系统会自动向内核发送一个信号,直接把client程序给杀死。这是linux默认的行为,这个地方我们不需要这样,需要在send函数后边标志位设置一下MSG_NOSIGNAL标记。这样设置完毕就可以了。
八、测试中遇到的问题
01、问题1
当时设置的如果接收方宕机重启后需要手动修改时间戳,这个问题需要修复一下。这个地方只要在刷新线程中将判断时间戳函数地方注释掉即可。
02、问题2
socket状态一直关闭不正常状态,出现FIN_WAIT1?????比较多,不知道是什么原因,后来也没有发现过。后续有时间查找具体原因。
03、问题3
双方接收数据对接不成功,对方接收消息时,经常出现错误,比如接收magic和length都会有错误,当时也不确定是什么问题,或者说是双方谁的程序有问题。后来又经过后续的连续测试,双方检查程序,结果也都没有确定哪方程序有问题?最后在C程序端发送socket上设置TCP_NODELAY标记后,对方接收数据暂时正确和正常。但这样做只能告诉内核快速发送,不要有延时,这样做的话,对jar端产生的影响就是接收缓存中的msg比较简单,从而减小出现错误的可能性,现在这只是推断,还不能确定具体原因是什么?
04、问题4
ineedle程序在对方接收端全部挂掉的时候会陷入睡眠,导致看门狗没有喂狗,致使ineedle重启。这种情况是很不友好的,需要除去这种情况,就在这个地方设置了一个下标志位,每次判断一下,如果是全部宕机的情况,这时就不要像往常那样进入睡眠,直接跳转到下条数据处理流程代码即可,直接丢弃数据,这种情况是不可避免的。
九、总结
最后在国舜做测试,做ineedle开机启动,遇到了一些问题,将启动程序命令写入到/etc/init.d/rc.local文件中,单单写入/var/dz_resource/ineedle/release/ineedle这样是运行不了,需要在这个命令之前source /etc/profile文件,可能是有什么环境变量需要设置,暂时没有找到具体什么原因,后续再研究。
十、遗留问题
ineedle设备HA特性尚不支持。后续待开发。
十一、测试数据
小设备发包极限:50M/S
银灰色小设备测试ineedle性能:
最大速率达到50M/S的速率时开始丢包,算是极限速率吧。
发包数据与生成消息比例:
50M/S ----> 1.6M/S
20M/S ----> 0.65M/S
十二、发包设备(交换机)
之前是用一个设备上边跑linux_pcap程序来给待测设备进行发包,这样对于低配置的发包设备来说,发包速率很低,最高才50M/s左右;对于较高配置(如DELL R430)速率也才到90M/s,这样达不到测试程序速率的效果。为此买了一台千兆交换机,准备用三台设备同时往交换机的三个网口来打流量,这样交换机镜像口就能汇总三个设备流量到一个口上,再通过一根网线将此网口数据打到待测试设备网口上即可。三台设备每台50M/S,三台总共150M/s,此时交换机镜像口接收数据速率有且120M/S,这样的速率基本上达到千兆网速,算是打到了千兆网卡的极限了。此工具以后可以测试后续性能比较好的设备了。但是发包工具当时做了简单的修改,把修改ip、cookie、等信息给去掉了,pcap拿到数据包之后直接从端口发送出去,这样效率应该会高一些,后续有时间可以继续优化一下发包工具。
其中拿到新交换机之后,看说明书进行简单配置,其实说明书并未有卵用,简单的不能再简单,就说明了哪些端口的指示灯表示什么,什么颜色代表网口的工作状态。然后通过交换机的web界面进行了简单配置,设置了几个端口为镜像口,和监测口。在设备与交换机相连的过程中,出现了协商速率不一致问题,明明都设置的是千兆全双工,设备显示的协商速率确实百兆的,后来仔细琢磨和尝试,换了灰色的网线之后,很轻易的自动识别并协商为1000M的网速,估计是和网线有关,估计那蓝色和红色的网线不支持千兆速率的吧。
十三、设备安装遇到的问题
从国舜拿到的设备回来之后开始安装操作系统,连上显示器,死活都不会显示,而且不会出现bios界面,刚在gs还是好好的,妹的,把内存条插拔了几次,重新安装上之后,不一会就听到了滴滴2声,显示器唰唰的打印出了bios的启动信息,原来是路上设备颠簸,内存松动,这种情况不止一次出现,之前就出现过一次。这种bios都不显示信息的,一定不是系统问题,肯定是基本设备的硬件没有检测到,或者是检测不到位,这样不满足系统启动的条件,就启动不了,而且没有打印信息,连bios都启动不了,太过分了,至少也要嘀嘀嘀报警一阵子啊,变态,这也算是知识的积累,总结经验。
iNeedle系统之国舜项目的更多相关文章
- Go推出的主要目的之一就是G内部大东西太多了,系统级开发巨型项目非常痛苦,Go定位取代C++,Go以简单取胜(KISS)
以前为了做compiler,研读+实现了几乎所有种类的语言.现在看语法手册几乎很快就可以理解整个语言的内容.后来我对比了一下go和rust,发现go的类型系统简直就是拼凑的.这会导致跟C语言一样,需要 ...
- 接口管理功能全面增强!EOLINKER EPC 5.0.9版本更新:支持LDAP用户系统、加入更多项目统计图表、强化测试/自动化测试功能等
EOLINKER EPC(Enterprise Private Cloud 企业私有云产品)已于近期发布5.0.9版本:界面全面改版.支持LDAP用户系统.加入更多项目统计图表.强化测试/自动化测试功 ...
- 如何在Linuxt系统下运行maven项目
如何在Linuxt系统下运行maven项目 我们知道现在利用MAVEN来管理JAVA项目是非常常见的.比如公司一般都有一个自己的MAVEN仓库,通过MAVEN仓库来解决我们的项目依赖,更加方便的构建项 ...
- 小型APP系统开发与应用项目实训
实训项目 : 小型APP系统开发与应用项目实训 项目成品名称: 果乐多商城 项 ...
- 在Linux系统中部署NodeJS项目
在Linux系统中部署NodeJS项目 安装NodeJS 首先进入 Node 官网,下载对应的 Node包 下载下来后是一个后缀为 xz 的压缩包,我们把这个包上传到 Linux 系统中的 /usr/ ...
- 在windows系统上面部署springboot项目并设置其开机启动
前言 最近的项目需要在客户的服务器上面部署一个项目然后进行测试,服务器的系统是windows server2008的,以前部署的项目都是在linux系统上面居多,就算是在windows系统上面自己玩的 ...
- Kali系统改国内源配置和SSH配置
一.Kali系统更新源 使用官网的虚拟化镜像安装,默认为英文界面,更新源也是官方源.因为官方服务器在国外,速度不是很理想,现在就来改国内源并且更新系统. 1.使用编辑器打开系统源文本(在终端内操作,先 ...
- win10系统vs2008环境wince项目无法创建问题
文章备份,原文来自百度某个作者的博客. 昨晚,当我升级win10之后,发现系统使用还是挺顺畅的,没有当初升级win8的时候那么多错误. 但是今晚回来之后,发现之前win8.1下已经安装好的vs2008 ...
- 在裸机centos7系统中部署django项目的过程
概要 本文用一台安装了centos7.5系统的裸奔Linux机器(当然是虚拟机)详细讲解从无到有部署django项目的过程. 安装必要的工具 配置yum源 至于什么是yum源大家请自行百度,本人用的是 ...
随机推荐
- [moka同学笔记]Yii2.0给一张表中增加一个属性
1.model中建立关联 public function getUser(){ return$this->hasOne(User::className(),['id'=>'uid']) ; ...
- JS代码实用代码实例(输入框监听,点击显示点击其他地方消失,文件本地预览上传)
前段时间写前端,遇到一些模块非常有用,总结以备后用 一.input框字数监听 <!DOCTYPE html> <html lang="en"> <he ...
- C++之面向对象的三个基本特征
三大特性是:封装,继承,多态 所谓封装 就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏.封装是面向对象的特征之一,是对象和类概念的主要特性. ...
- Spring4学习笔记1-HelloWorld与IOC和DI概述
1.安装环境 1.1安装eclipse,jdk 1.1安装Spring tool suite(非必要项) 2.spring HelloWorld 2.1 需要的jar包(spring官网下载:http ...
- SQLServer2005+分页SQL
declare @pagenum int = 1; declare @pagesize int = 3; WITH Tmp AS ( SELECT ROW_NUMBER() OVER (ORDER B ...
- 命令行工具解析Crash文件,dSYM文件进行符号化
备份 文/爱掏蜂窝的熊(简书作者)原文链接:http://www.jianshu.com/p/0b6f5148dab8著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 序 在日常开发 ...
- [deviceone开发]-数据绑定示例
一.简介 这个示例详细介绍了do平台数据bind的灵活使用方式.所有UI组件都支持binddata的方式,可以绑定到do_HashData,do_ListData对象.初学者推荐. 二.效果图 三.相 ...
- 浅析css布局模型1
css是网页的外衣,好不好看全凭css样式,而布局是css中比较重要的部分,下面来分析一下常见的几种布局. 流动模型 流动模型是网页布局的默认模式,也是最常见的布局模式,他有两个特点: 1.块状元素都 ...
- listview复用机制研究
Listview在第一次的时候会先把屏幕上绘制的item都new出来,为了讲解方便我把new出来的item都用红色背景,复用的则用绿色背景. 可以看到这个list种有三种item.在第一次展示的时候, ...
- 浅谈TabLayout(ViewPager+Tab联动)
google发布了的Android Support Design库中提供了TabLayout 通过TabLayout+ViewPager实现导航栏效果,点击Tab ,ViewPager跟随变化,滑动V ...