zoukankan      html  css  js  c++  java
  • 聊聊 Jmeter 如何并发执行 Python 脚本

    1. 前言

    大家好,我是安果!

    最近有小伙伴后台给我留言,说自己用 Django 写了一个大文件上传的 Api 接口,现在想本地检验一下接口并发的稳定性,问我有没有好的方案

    本篇文章以文件上传为例,聊聊 Jmeter 并发执行 Python 脚本的完整流程

    2. Python 实现文件上传

    大文件上传包含 3 个步骤,分别是:

    • 获取文件信息及切片数目

    • 分段切片,并上传 - API

    • 文件合并 - API

    • 文件路径参数化

    2-1  获取文件信息及切片数目

    首先,获取文件的大小

    然后,利用预设的切片大小获取分段总数

    最后,获取文件名及 md5 值

    import os
    import math
    import hashlib
    
    def get_file_md5(self, file_path):
        """获取文件的md5值"""
        with open(file_path, 'rb') as f:
             data = f.read()
             return hashlib.md5(data).hexdigest()
    
    def get_filename(self, filepath):
        """获取文件原始名称"""
        # 文件名带后缀
        filename_with_suffix = os.path.basename(filepath)
        # 文件名
        filename = filename_with_suffix.split('.')[0]
        # 后缀名
        suffix = filename_with_suffix.split('.')[-1]
        return filename_with_suffix, filename, suffix
    
    def get_chunk_info(self, file_path):
        """获取分段信息"""
        # 获取文件总大小(字节)
        file_total_size = os.path.getsize(file_path)
        print(file_total_size)
    
        # 分段总数
        total_chunks_num = math.ceil(file_total_size / self.chunk_size)
        # 文件名(带后缀)
        filename = self.get_filename(file_path)[0]
        # 文件的md5值
        file_md5 = self.get_file_md5(file_path)
        return file_total_size, total_chunks_num, filename, file_md5
    

    2-2  切片及分段上传

    利用分段总数和分段大小,对文件进行切片,调用分段文件上传接口

    import requests
    
    def do_chunk_and_upload(self, file_path):
    ​    """将文件分段处理,并上传"""
        file_total_size, total_chunks_num, filename, file_md5 = self.get_chunk_info(file_path)
    
        # 遍历
        for index in range(total_chunks_num):
            print('第{}次文件上传'.format(index + 1))
            if index + 1 == total_chunks_num:
                partSize = file_total_size % chunk_size
            else:
                partSize = chunk_size
    
            # 文件偏移量
            offset = index * chunk_size
    
            # 生成分片id,从1开始
            chunk_id = index + 1
    
            print('开始准备上传文件')
            print("分片id:", chunk_id, "文件偏移量:", offset, ",当前分片大小:", partSize, )
    
            # 分段上传文件
            self.__upload(offset, chunk_id, file_path, file_md5, filename, partSize, total_chunks_num)
    
    def __upload(self, offset, chunk_id, file_path, file_md5, filename, partSize, total):
        """分次上传文件"""
        url = 'http://**/file/brust/upload'
        params = {'chunk': chunk_id,
                    'fileMD5': file_md5,
                    'fileName': filename,
                    'partSize': partSize,
                    'total': total
                    }
        # 根据文件路径及偏移量,读取文件二进制数据
        current_file = open(file_path, 'rb')
        current_file.seek(offset)
    
        files = {'file': current_file.read(partSize)}
        resp = requests.post(url, params=params, files=files).text
        print(resp)
    

    2-3  合并文件

    最后调用合并文件的接口,将分段小文件合成大文件

    def merge_file(self, filepath):
            """合并"""
            url = 'http://**/file/brust/merge'
            file_total_size, total_chunks_num, filename, file_md5 = self.get_chunk_info(filepath)
    ​        payload = json.dumps(
                {
                    "fileMD5": file_md5,
                    "chunkTotal": total_chunks_num,
                    "fileName": filename
                }
            )
            print(payload)
            headers = {
                "Content-Type": "application/json"
            }
            resp = requests.post(url, headers=headers, data=payload).text
            print(resp)
    

    2-4  文件路径参数化

    为了并发执行,将文件上传路径参数化

    # fileupload.py
    ...
    if __name__ == '__main__':
        filepath = sys.argv[1]
    
        # 每一段切片的大小(MB)
        chunk_size = 2 * 1024 * 1024
    
        fileApi = FileApi(chunk_size)
        # 分段上传
        fileApi.do_chunk_and_upload(filepath)
    
        # 合并
        fileApi.merge_file(filepath)
    

    3. Jmeter 并发执行

    在使用 Jmeter 创建并发流程前,我们需要编写批处理脚本

    其中,执行批处理脚本时,需要跟上文件路径一起执行

    # cmd.bat
    
    @echo off
    set filepath=%1
    
    python  C:UsersxingagDesktop
    pc_demofileupload.py %*
    

    然后,在本地新建一个 CSV 文件,写入多个文件路径

    # 准备多个文件路径(csv)
    C:\Users\xingag\Desktop\charles-proxy-4.6.1-win64.msi
    C:\Users\xingag\Desktop\V2.0.pdf
    C:\Users\xingag\Desktop\HBuilder1.zip
    C:\Users\xingag\Desktop\HBuilder2.zip
    

    接着,就可以使用 Jmeter 创建并发流程了

    完整步骤如下:

    • 创建一个测试计划,下面添加一个线程组

      这里线程组数目与上面文件数目保持一致即可

    • 线程组下,添加「 同步定时器 」

      同步定时器中的「 模拟用户组的数量 」和上面参数数量保持一致

    • 添加 CSV 数据文件设置

      指向上面准备的 csv 数据文件,设置文件格式为 UTF-8,变量名称设置为 file_path,最后将线程共享模式设置为「 当前线程组 」

    • 添加调试取样器,方便调试

    • 添加 OS 进程取样器

      选择上面创建的批处理文件,命令行参数设置为「 ${file_path} 」

    • 添加查看结果数

    4. 最后

    运行上面创建的 Jmeter 并发流程,在结果数中可以查看并发上传文件的结果

    当然,我们可以增加并发数量去模拟真实的使用场景,只需要修改 CSV 数据源及 Jmeter 参数即可

    如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

    分享 Python 自动化及爬虫、数据分析实战干货,欢迎关注。
  • 相关阅读:
    hdu6229 Wandering Robots 2017沈阳区域赛M题 思维加map
    hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)
    hdu6438 Buy and Resell 买卖物品 ccpc网络赛 贪心
    hdu6441 Find Integer 求勾股数 费马大定理
    bzoj 1176 Mokia
    luogu 3415 祭坛
    bzoj 1010 玩具装箱
    bzoj 3312 No Change
    luogu 3383【模板】线性筛素数
    bzoj 1067 降雨量
  • 原文地址:https://www.cnblogs.com/xingag/p/15245085.html
Copyright © 2011-2022 走看看