过程笔记和总结

尝试一、locust 测试百万Tcp并发

另一种方式是使用jmeter

基础环境

  • 服务端

虚拟机:Centos7.2

jdk 1.8

  • 客户端

虚拟机: Centos7.2

python : 3.7.3 Anaconda3

locust : 0.14.5


基础知识:

  • tcp协议:三次握手进行连接,四次挥手断开,稳定长连接,比Http更占用资源,比udp协议更稳定,保证数据不丢失,但速度比较慢。
  • 每个tcp连接大概占用4kb内存,且断开连接后默认两分钟之后才会释放资源
  • linux打开文件限制(open-files)
  • linux端口限制
  • tcp-socket 网络编程
  • python中类继承 super 用法
  • python中发送16进制数据包

Q&A

客户端调优

  1. 客户端端口限制导致的tcp连接不超过4000,通过修改打开文件限制来增加可使用的端口数量,注意修改后需要重启生效,具体配置参考
--   /etc/sysctl.conf 

# 系统级别最大打开文件
fs.file-max = 100000 # 单用户进程最大文件打开数
fs.nr_open = 100000 # 是否重用, 快速回收time-wait状态的tcp连接
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1 # 单个tcp连接最大缓存byte单位
net.core.optmem_max = 8192 # 可处理最多孤儿socket数量,超过则警告,每个孤儿socket占用64KB空间
net.ipv4.tcp_max_orphans = 10240 # 最多允许time-wait数量
net.ipv4.tcp_max_tw_buckets = 10240 # 从客户端发起的端口范围,默认是32768 61000,则只能发起2w多连接,改为一下值,可一个IP可发起差不多6.4w连接。
net.ipv4.ip_local_port_range = 1024 65535
--  /etc/security/limits.conf 

# 最大不能超过fs.nr_open值, 分别为单用户进程最大文件打开数,soft指软性限制,hard指硬性限制
* soft nofile 100000
* hard nofile 100000
root soft nofile 100000
root hard nofile 100000

服务端调优

2. 服务端需要接受的链接数需要超过100w,根据需要修改虚拟机配置;可参考文章https://www.jianshu.com/p/490e2981545c

  • 优化局部句柄限制

查看 ulimit-n

soft和hard为两种限制方式,其中soft表示警告的限制,hard表示真正限制,nofile表示打开的最大文件数。整体表示任何用户一个进程能够打开1000000个文件。注意语句签名有 号 表示任何用户

--  /etc/security/limits.conf
# 文末加两行
*hard nofile 1000000
soft nofile 1000000

shutdown -r now 重启并查看生效

  • 突破全局句柄的限制

    cat /proc/sys/fs/file-max

    file-max 表示在linux 中最终所有x线程能够打开的最大文件数

sudo vi /etc/sysctl.conf

# 在文末增加
fs.file-max=1000000

让文件生效

sudo sysctl -p


Locust分布式说明

因单台node最大tcp连接6w,故测试百万连接需要对Locust做分布式处理;

Locust分布式注意点:

每台机器上都要有client文件,且必须相同

slave虚拟机环境、Locust版本、python版本必须相同,否则预期出现未知错误

slave节点较多时需要并行管理工具pdsh的使用吗,同时启动多个slave节点,减少人工启停时间成本

遇到的问题

locust 分布式执行问题

单机启动可发送60000,两台120000

集群启动发送60000 服务端ip无法超过60000 限制

已解决:

locust master 节点不作为负载机进行发送数据,slave 一个节点最多可以增加6w个长连接(linux共有端口65535, 一般1-1023 端口是系统保留的,1024-65535 是用户使用的,可用端口有6w多个)

运维管理工具 pdsh

作用:快速分发命令,启动slave节点

1、 配置ssh信任

修改主机名称 vim /etc/hostname

master 可设为node0,slave 可设为 node1~16

参考:https://blog.csdn.net/ctypyb2002/article/details/80572181

2、 安装pdsh

参考:https://www.cnblogs.com/liwanliangblog/p/9194146.html

tar -jxvf **.tag.bz2
./configure --with-ssh --with-rsh --with-mrsh--with-mqshell --with-qshell --with-dshgroups--with-machines=/etc/pdsh/machines --without-pam
make
make install

客户端代码

## locustfile.py
# coding:utf-8
import time
import random
# from socket import socket, AF_INET, SOCK_STREAM
import socket
from locust import Locust, TaskSet, events, task class TcpSocketClient(socket.socket):
# locust tcp client
# author: ShenDu
def __init__(self, af_inet, socket_type):
super(TcpSocketClient, self).__init__(af_inet, socket_type) def connect(self, addr):
start_time = time.time()
try:
super(TcpSocketClient, self).connect(addr)
except Exception as e:
total_time = int((time.time() - start_time) * 1000)
events.request_failure.fire(request_type="tcpsocket", name="connect", response_time=total_time, exception=e)
else:
total_time = int((time.time() - start_time) * 1000)
events.request_success.fire(request_type="tcpsocket", name="connect", response_time=total_time,
response_length=0) def send(self, msg):
start_time = time.time()
try:
super(TcpSocketClient, self).send(msg)
except Exception as e:
total_time = int((time.time() - start_time) * 1000)
events.request_failure.fire(request_type="tcpsocket", name="send", response_time=total_time, exception=e)
else:
total_time = int((time.time() - start_time) * 1000)
events.request_success.fire(request_type="tcpsocket", name="send", response_time=total_time,
response_length=0) def recv(self, bufsize):
recv_data = ''
start_time = time.time()
try:
recv_data = super(TcpSocketClient, self).recv(bufsize)
except Exception as e:
total_time = int((time.time() - start_time) * 1000)
events.request_failure.fire(request_type="tcpsocket", name="recv", response_time=total_time, exception=e)
else:
total_time = int((time.time() - start_time) * 1000)
events.request_success.fire(request_type="tcpsocket", name="recv", response_time=total_time,
response_length=0)
return recv_data class TcpSocketLocust(Locust):
"""
This is the abstract Locust class which should be subclassed. It provides an TCP socket client
that can be used to make TCP socket requests that will be tracked in Locust's statistics.
"""
def __init__(self, *args, **kwargs): super(TcpSocketLocust, self).__init__(*args, **kwargs)
self.client = TcpSocketClient(socket.AF_INET, socket.SOCK_STREAM)
ADDR = (self.host, self.port)
self.client.connect(ADDR) class TcpTestUser(TcpSocketLocust):
host = "192.168.5.58"
port = 6667
min_wait = 100
max_wait = 1000 class task_set(TaskSet):
@task
def send_data(self):
data = "7e0200003f000004021895000b00000000000400030158ccaa06cb7" \
"9f50095000000001601051654150104000069740202000003020000" \
"2504000000002b040000000030010031010b3201467c7e"
# self.client.send(data.encode("utf-8"))
self.client.send(bytes.fromhex(data))
data = self.client.recv(2048).decode("utf-8")
print(data) if __name__ == "__main__":
import os
os.system("locust -f sendTcp.py")

单节点启动

locust -f locustfile.py

分布式启动

# master执行
locust -f locustfile.py --master
# slave执行
locust -f locustfile.py --slave --master-host = 127.0.0.1
# pdsh 同时启动slave节点, node 可使用ip代替
pdsh -w node[1-16] "locust -f /root/loadtest/locustfile.py --slave --master-host=node0"

python编写的简易服务端

调试程序使用的服务端代码

#coding: utf-8
from __future__ import print_function
from gevent.server import StreamServer
import gevent # sleeptime = 60
'''
python 编写的简单tcp socket server,作为服务端测试使用
'''
def handle(socket, address):
# print(address)
# data = socket.recv(1024)
# print(data)
while True:
gevent.sleep(sleeptime)
try:
socket.send("ok")
except Exception as e:
print(e) if __name__ == "__main__":
import sys
port = 80
if len(sys.argv) > 2:
port = int(sys.argv[1])
sleeptime = int(sys.argv[2])
else:
print("需要两个参数!!")
sys.exit(1)
# default backlog is 256
server = StreamServer(('0.0.0.0', port), handle, backlog=4096)
server.serve_forever()

参考文章:

  • 百万并发:https://blog.csdn.net/jackliu16/article/details/81294741
  • bytes和hex字符串之间的转换:https://blog.csdn.net/wowocpp/article/details/79701739
  • 性能测试 - Locust TCP socket client: https://blog.csdn.net/max229max/article/details/79277295
  • 深入浅出Locust:https://juejin.im/post/58c29457128fe10060297328
  • 官文: https://docs.locust.io/en/latest/quickstart.html
  • locust&jmeter比较:https://www.jianshu.com/p/dd0fcfdfa561

TCP 百万并发 数据连接测试 python+locust的更多相关文章

  1. 基于管道通知的百万并发长连接server模型

    0.前言 最近突然想了解怎样设计一个支持百万连接的后台server架构. 要设计一个支持百万连接的后台server,我们首先要知道会有哪些因素限制后台server的高并发连接,这里想到的因素有以下几点 ...

  2. MarioTCP:一个单机可日30亿的百万并发长连接服务器

    原文:http://blog.csdn.net/everlastinging/article/details/10894493 注:如果用此服务器做变长data的传输,请在业务处理函数中为input ...

  3. 如何在mysql数据库生成百万条数据来测试页面加载速度

    1.首先复制一条sql 在复制前,需要确定该记录是否有主键 若无,则代码非常简单, "; 复制的表名↑                                   粘贴的表名↑    ...

  4. 测试开发【提测平台】分享9-DBUntils优化数据连接&实现应用搜索和分页功能

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 从本期开始知识点讲以思维导图的形式给出,内容点会按照讲解-应用-展示的形式体现,这样会更清晰些. DBUntils连接池 在项目中链接数据 ...

  5. 面向Web应用的并发压力测试工具——Locust实用攻略

    1. 概述 该方案写作目的在于描述一个基于Locust实现的压力测试,文中详细地描述了如何利用locustfile.py文件定义期望达成的测试用例,并利用Locust对目标站点进行并发压力测试. 特别 ...

  6. python全栈开发day113-DBUtils(pymysql数据连接池)、Request管理上下文分析

    1.DBUtils(pymysql数据连接池) import pymysql from DBUtils.PooledDB import PooledDB POOL = PooledDB( creato ...

  7. Linux Mysql 安装 开启远程连接 供python agent 连接测试 Mark

    Linux     6.3 (1) cat  /etc/redhat-release uname -a 查看yum 源:   阿里源 无源运行: echo 下载阿里云的yum源配置 wget -O / ...

  8. 4-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案数据篇(云端电脑(Windows)安装配置数据库,使用本地Navicat for MySQL和手机APP 远程连接测试)

    3-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案数据篇(安装配置数据库,使用Navicat for MySQL和手机APP 连接测试) 根据前面的教程把软件复制到云 ...

  9. 3-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案数据篇(安装配置数据库,使用Navicat for MySQL和手机APP 连接测试)

    2-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案数据篇(数据库简单说明) https://www.mysql.com/ 咱用安装版的 我把自己下载的放在了这里 现在 ...

随机推荐

  1. Metasploit渗透使用攻略

    msf关于tomcat口令暴力猜解模块 use auxiliary/scanner/http/tomcat_mgr_login show options set rhosts 192.168.2.14 ...

  2. Ubuntu16.04安装搜狗输入法报错:dkpg:处理归档sogoupinyin.deb(--install)时出错,安装sogoupinyin将破坏fcitx-ui-qimpanel

    系统:ubuntu16.04 事件:安装搜狗拼音时报错 报错信息(ubuntu语言是英文的报错信息): dpkg: regarding sogoupinyin_2.3.2.07_amd64-831.d ...

  3. HarmonyOS Java UI之StackLayout布局示例

    StackLayout简介 StackLayout意为堆叠布局,用于在屏幕上保留一个区域来显示组件,实现特殊的功能.通常,堆叠布局中只应该放置一个子组件,如果存在多个子组件,则显示最新的组件.这个布局 ...

  4. FL studio系列教程(十三):如何在FL Studio步进音序器中制作节奏

    了解了FL Studio一些操作功能后,我们就要去用这些操作功能完成我们想要的作品.所以今天小编就来带领大家在FL Studio的步进音序器中制作出简单的节奏,与此同时大家也会了解到通道的几个基础功能 ...

  5. windows创建隐藏用户的powershell脚本

    通过保存并重新注册已删除用户的注册表的方式来隐藏用户,未登录时登陆界面不可见,登陆后可见 方法详情见: https://www.k0rz3n.com/2018/06/26/windows%E6%B8% ...

  6. kafka producer 概要(看源码前,最好能掌握)

        kafakproducer概要(看源码前,最好能理解) 摘要 kafak 被设计用来作为一个统一的平台来处理庞大的数据的实时工具,在设计上有诸多变态的要求 它必须具有高吞吐量才能支持大量事件流 ...

  7. Contest 984

    A 先手取最大,后手取最小,答案就是第 \(\left\lceil\frac{n}{2}\right\rceil\) 小的数. 用 nth_element 可以做到 \(O\left(n\right) ...

  8. C语言讲义——结构体struct

    结构体是一种变量类型,可以包含多个变量(变量类型不必相同). 结构体的关键字是struct也是一种值类型. 例:设计一个表示"书本"的结构体: structBook { chari ...

  9. C语言讲义——指针(pointer)

    指针是C语言最重要的特性之一, 也是最容易被误解的特性之一. 现代计算机把内存分割为字节(Byte), 每个字节都有唯一的地址(Address), 如果内存中有n个字节,可以把地址看做0~n-1的数. ...

  10. java数组作为函数返回值

    1 //将一个二维数组行和列元素互换.存到另一个二维数组 2 package test; 3 4 public class test1_8 { 5 public static int[][] huhu ...