转载本文请联系AirPython公众号.一、前言大家好,我是安国!最近后台有个小伙伴给我留言,说他在Django写了一个上传大文件的Api接口,现在想在本地查看接口并发的稳定性,问我可以吗这篇文章取以文件上传为例说说Jmeter并发执行Python脚本的完整过程二、Python实现文件上传大文件上传包括3个步骤,分别是:获取文件信息和分片个数,分段分片,上传-API文件合并-API文件路径参数化2-1获取文件信息和分片数首先获取文件的大小然后使用预设的分片大小获取总分片数最后获取文件名和md5值importosimportmathimporthashlibdefget_file_md5(self,file_path):"""获取文件的md5值"""withopen(file_path,'rb')asf:data=f.read()returnhashlib.md5(data).hexdigest()defget_filename(self,filepath):"""获取t的原名hefile"""#后缀名filename_with_suffix=os.path.basename(filepath)#文件名filename=filename_with_suffix.split('.')[0]#后缀名suffix=filename_with_suffix.split('.')[-1]returnfilename_with_suffix,filename,suffixdefget_chunk_info(self,file_path):"""获取段信息"""#获取文件总大小(字节)file_total_size=os.path.getsize(file_path)print(file_total_size)#总个数segmentstotal_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)returnfile_total_size,total_chunks_num,filename,file_md52-2分片和分片上传使用分片总数和分片大小分片文件,调用分段文件上传接口importrequestsdefdo_chunk_and_upload(self,file_path):"""分段处理文件并上传"""file_total_size,total_chunks_num,filename,file_md5=self.get_chunk_info(file_path)#traverseforindexinrange(total_chunks_num):print('第{}次文件上传'.format(index+1))ifindex+1==total_chunks_num:partSize=file_total_size%chunk_sizeelse:partSize=chunk_size#fileoffsetoffset=index*chunk_size#generatefragmentid,从1开始chunk_id=index+1print('开始上传文件')print("Shardid:",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).textprint(resp)2-3合并文件,最后调用合并文件的接口进行分片小文件合成大文件defmerge_file(self,filepath):"""merge"""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).textprint(resp)2-4文件路径参数化对于并发执行,参数化文件上传路径#fileupload.py...if__name__=='__main__':filepath=sys.argv[1]#每个分片的大小(MB)chunk_size=2*1024*1024fileApi=FileApi(chunk_size)#SegmentuploadfileApi.do_chunk_and_upload(filepath)#MergefileApi.merge_file(filepath)3.Jmeter并发执行使用的是Jmeter在创建并发进程之前,我们需要写一个批处理脚本。执行批处理脚本时,需要和文件路径一起执行#cmd.bat@echooffsetfilepath=%1pythonC:\Users\xingag\Desktop\rpc_demo\fileupload.py%*然后,在本地新建一个CSV文件,写入multiplefilepaths#准备多个文件路径(csv)C:\\Users\\xingag\\Desktop\\charles-proxy-4.6.1-win64.msiC:\\Users\\xingag\\Desktop\\V2.0.pdfC:\\Users\\xingag\\Desktop\\HBuilder1.zipC:\\Users\\xingag\\Desktop\\HBuilder2.zip然后,就可以使用Jmeter创建并发进程了。完整的步骤如下:创建一个测试计划,在下面添加一个线程组。线程组的数量与上面的文件数量一致。线程组下,在“SynchronizationTimer”中添加“SimulatedUser”同步定时器组数“与上面参数个数一致。添加CSV数据文件设置指向上面准备的csv数据文件,设置文件format为UTF-8,设置变量名为file_path,最后设置线程共享方式为“当前线程组”添加Debugsampler,方便调试添加OS进程sampler选择上面创建的批处理文件,设置命令行参数为“${file_path}"添加查看结果数4.最后运行上面创建的Jmeter并发进程,在结果数中可以查看并发上传文件的结果当然我们可以增加并发数来模拟真实的使用场景,修改CSV数据源和Jmeter参数即可
