网络并发 测试准备_1

谈到服务器的并行处理能力,人们总是会很容易想到TPS等数据指标,当然得利于前人的许多工具我们可以通过十分简单的步骤得出这些数据,然后输出一份十分养眼的报告。不得不承认这些工具提高了生产力,不过也正是这些东西让我们误以为“到此为止”了

当今许多项目,框架,甚至协议都被设为一层层的结构操作系统是的应用程序,网络中的通信协议,当然社会生活中也是这样层层分工。有了这样的结构完成目标变的非常的容易,再也不用关注”无关“的事物了。(socket正是一个这样的例子,它由操作系统实现,让网络通信变的无比简单)

不过个人认为作为保证事物按预期发展的测试人员应该了解更多,高并发到底意味着什么,socket背后的网络行为等等

其实网络数据的并发当然是个十分复杂的东西,不过前提是网络,我们不能简单的描述为”发送一次请求“,当我们向操作系统申请”发送一次请求“,后面发生了很多事情这些事情我们有必要知道

我们先简单的回忆一下必要的网络知识

以上是TCP/IP的四层模型(TCP/IP不是只包括tcp跟ip这2个东西,是一堆协议的集合),后面2层路由等设备关注可能会比较多,我们现在暂时只关注传输层

那既然是网络并发总是要”发“的吧,提到发那还必须先知道是使用合种协议去发送,主流的tcp,http等都很常见(通常很少有自己创造一种协议去进行通信的,即使有的公司内部的通信协议一般也是会基于tcp等基础传输协议)

现在以tcp协议为例,既然要发送那肯定是要先连接起来的(大多数协议都是需要连接的,即便http称是无连接的,不过http也是基于tcp的应用协议,所以连接肯定是少不了的,只是连接完成后会主动断开),为了了解连接的过程先回顾下tcp的握手过程吧

完成3次握手后连接就算完成了,那问题来了发送数据前要先连接,那连接的数量有没有限制呢,一些观点认为计算机端口的数量限制着连接数量,这种看法当然是不正确的,端口的数量只是限制着当前计算机客户端的数量而已。其实理解这个东西也十分简单,只是一直借助socket让我们对其本身少了很多思考,socket由操作系统构架与传输层与应用层直接,它的便利性让我们对端口模糊化了。而实际上在网络层的ip包并没有端口号这个数据位,显然端口其实是应用层面的数据分组,操作系统(当然包括网络设备的操作系统)接收所有数据,然后根据数据包里面的端口信息决定数据的去向,对于windows来说上层应用程序向系统申请监听xxx端口,你们操作系统会在自己接收到的包中发现是xxx端口的就会给前面的应用程序一份(还有一点提一下:端口不一定会被某一个应用程序独占)。也就是说服务器应用程序只要监听一个端口就可以收到任意计算机的任意端口的数据包。

事实上单台PC可以同时维持的tcp的连接数是十分巨大的,通过对协议的分析我们会发现,建立一个连接也只需要3次握手就完成了如果后面没有其他数据通信(如心跳什么的业务数据)这个连接是不会有什么其他消耗的,所以为了维持连接也仅仅需要储存远程客户端地址等少量信息而已,通过实际测试个人计算机的同时连接数可以轻松达到10w的数量级(由于单台pc客户端的数量有限制,而测试的pc数量有限也没有继续向上测试,有兴趣的朋友可以自己尝试下)

 1 IPAddress ip;
 2         TcpListener listener;
 3         List<Socket> mySockets;
 4         Thread myListenThread;
 5 
 6 
 7         private void Form1_Load(object sender, EventArgs e)
 8         {
 9             ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
10             //ip = IPAddress.Parse("127.0.0.1");  
11             listener = new TcpListener(ip, 8500);  
12         }
13 
14         private void bt_start_Click(object sender, EventArgs e)
15         {
16             try
17             {
18                 ip = IPAddress.Parse(tb_ip.Text);
19                 listener = new TcpListener(ip, 8500);  
20             }
21             catch(Exception ex)
22             {
23                 MessageBox.Show(ex.Message);
24                 return;
25             }
26             if (myListenThread == null)
27             {
28                 myListenThread = new Thread(new ThreadStart(StartGetSocket));
29                 myListenThread.IsBackground = true;
30                 myListenThread.Start();
31             }
32             else
33             {
34                 if(myListenThread.IsAlive)
35                 {
36                     listener.Stop();
37                     myListenThread.Abort();
38                     ShowMes("STOP");
39                 }
40                 else
41                 {
42                     myListenThread = null;
43                 }
44                 bt_start_Click(null,null);
45             }
46         }
47 
48 
49         private void StartGetSocket()
50         {
51             byte[] myBytes=new byte[1024];
52             listener.Start();
53             mySockets = new List<Socket>();
54             while(true)
55             {
56                 while(listener.Pending())
57                 {
58                     Socket nowSocket = listener.AcceptSocket();
59                     ShowMes("成功连接主机:" + nowSocket.RemoteEndPoint.ToString());
60                     mySockets.Add(nowSocket);
61                 }
62                 foreach(Socket tempSocket in mySockets)
63                 {
64                     while (tempSocket.Available > 0)
65                     {
66                         tempSocket.Receive(myBytes);
67                         ShowMes(tempSocket.RemoteEndPoint.ToString());
68                         //ShowMes(byteToHexStr(myBytes));
69                         ShowMes(Encoding.Unicode.GetString(myBytes));
70                     }
71                 }
72             }
73         }
74 
75         private void ShowMes(string mes)
76         {
77             if(this.rtb_info.InvokeRequired)
78             {
79                 rtb_info.BeginInvoke(new Action<string>((arg1) => rtb_info.AppendText(arg1)), mes+"\r\n");
80             }
81             else
82             {
83                 rtb_info.AppendText(mes + "\r\n");
84             }
85         }

以上是简单的服务端测试代码,十分清晰简单所以也没有写任何注释。

以上可以看出来连接的数量一般是不会成为瓶颈(注意连接的建立还是需要少量消耗的,当然这个消耗一般存在于网络上我们现在暂时只关注与对服务器本身的消耗),当然重要的还是发的内容,一般情况下在网络条件允许的情况下,任何个人计算机都可以发起相当的服务请求。假如数据很快通过网络设备到达服务器,这个时候服务器对这些数据的处理能力及方式就显的至关重要。打个比方操作系统但钱已经获取到1000条针对当前服务的请求,如果服务程序依次向操作系统获取然后处理那后面的请求必然会阻塞。以前面提供的code为例,即时单独开辟一条线程出来获取服务器的数据,然后再以异步的形式把数据委托到UI线程去显示,再请求过多(或每秒事物达到一定量)时,就会明显发现显示滞后。

服务器接收到的业务数据绝不是为了简单的显示,它需要做的事情更多,如何用最小的代价完成当前业务成为了制约处理能力(并发量)的关键(当然也许多分布式部署几台服务器或增加些硬件配置会有不错的效果)

若是作为测试人员就必须了解服务的应用场景,实际业务,及用户的可能行为,当然每次业务的每一步服务器的行为及消耗也应该了解,这也是制定高效测试业务流程的基础。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI科技大本营的专栏

6月Python开源项目Top 10:如何快速找到抖音上的漂亮小姐姐……

【人工智能头条导读】开源项目对大家的学习工作都非常有用,今天我们为大家推荐过去一个月受到热烈关注的 10 个开源项目。其中有一个项目非常贴近我们的日常生活:一名...

1374
来自专栏Java架构

高并发风控技术解密(下)

  •从业务中抽象及通用——如果一种业务有可能在今后重复出现,那就将其模块化,系统化(如批处理系统),发展成为平台能力

1655
来自专栏IT笔记

分布式与集群有什么区别

一个是3个字,另一个2个字 集群一般被分为三种类型,高可用集群(High-availability (HA) clusters )如RHCS、LifeKeepe...

3714
来自专栏jessetalks

前后端分离开发模式下后端质量的保证 —— 单元测试

概述   在今天, 前后端分离已经是首选的一个开发模式。这对于后端团队来说其实是一个好消息,减轻任务并且更专注。在测试方面,就更加依赖于单元测试对于API以及后...

37210
来自专栏EAWorld

元数据如何驱动微服务报文架构?

随着微服务的概念逐渐被人们接受,大家都在努力将自己的应用系统向微服务框架转型。在我们研发微服务框架的时候,就发现随着服务数量的增多,服务接口定义就需要一套统一数...

3648
来自专栏大数据文摘

5大架构:细数数据平台的组成与扩展

2468
来自专栏IMWeb前端团队

测试用例的那一回事

前言 最近,团队对测试用例十分的注重,因此,下面是我对测试用例的一些解析。 首先,我们需要知道:为什么需要测试用例? 理由很简单,就是为了在测试用例的辅助下,编...

21410
来自专栏程序员宝库

后端好书阅读与推荐(续四)

这里依然记录一下每本书的亮点与自己读书心得和体会,分享并求拍砖。 Docker生产环境实践指南 Docker生产环境实践指南 (豆瓣:https://book....

4796
来自专栏PHP在线

切到 PHP7,我们是如何节省一百万美元的?

原文出处: Badoo 译文出处:开源中国 介绍 我们(Badoo)成功把应用迁移到了php7上面(数百台机器的集群),而且运行的很好,据说我们是第...

4626
来自专栏Java架构

高并发风控技术解密(下)

1743

扫码关注云+社区