Python_サービス・エンドのパフォーマンスが高い同時テスト

5513 ワード

背景


会社の業務は上昇期にあるが、サービス側はdemoのようにlowし、サービス側の再構築が始まった.テストについては、この業界をテストするのは多くのインターネット会社で失敗しており、テストをするのはこのような感じがするはずです.しかし、私はラッキーだと思います.CTOはテストを重視しているので、彼の口癖はテストできないプログラムが信頼できないので、うちの会社のすべてのプログラムにはセットのテストツールがあります.この文書のツールは,サービス側を専門にテストしてシミュレートしたクライアントTSPである.

ビジネスニーズ


サービス・エンドを再構築し、百万クライアント・レベルにアクセス

実装の原理

  • サービス側は3つのポートをリスニングし、この3つのポートはすべてデバイス起動
  • である.
  • tspはクライアント接続サービス側論理をシミュレートし、それによって設備、ユーザーオンライン
  • に達する.
  • プロセスプールネストスレッドプール方式を採用し、高同時の目的
  • を達成する.
  • コードには、発注時間平均値、受入時間平均値、受入バイトサイズ平均値、受入エラー率が統計される.
  • サービス側はハードウェア構成、cpu負荷、メモリ負荷、ディスクioなどを収集し、より多くのパラメータ
  • を知りたい.

    具体的な実装


    1.メインプロセスを構築し、socket要求に基づく送受信パケットを完成する
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #
    from socket import socket,AF_INET,SOCK_STREAM
    
    import struct
    
    from log import log
    log=log()
    class socket_main:
    
        def __init__(self,who,conn_data):
            self.conn_data = conn_data
            self.who = who
            self.__conn(conn_data)
    
        def __conn(self,addr):
    
            try:
                log.debug('{} _conn data:{}'.format(self.who,addr))
                self.tcpCliSock = socket(AF_INET, SOCK_STREAM)
                self.tcpCliSock.connect(addr)
                self.tcpCliSock.setblocking(1)
                self.tcpCliSock.settimeout(1)
                # self.tcpCliSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,8192)
                log.debug('{} socket data:{}'.format(self.who,'success'))
            except BaseException as msg:
                log.error('{} socket conn_result:{}'.format(self.who,msg))
    
        def send(self,data):
            try:
                try:
                    result = self.tcpCliSock.send(data)
                except BaseException as msg:
                    # self.__conn(self.conn_data)
                    # result = self.tcpCliSock.send(data)
                    log.error(msg)
                    raise msg
                log.debug('{} socket send_len:{}'.format(self.who, result))
                return result
            except BaseException as msg:
                raise log.error('{} socket send_error:{}'.format(self.who,msg))
    
        def recv(self,size,code):
            result =''
            try:
                try:
                    result = self.tcpCliSock.recv(int(size))
    
                    while len(result)
  • プロセスプール、スレッドプールセット
  • を構築
    def main():
      print ' '
    
    class MyThread(threading.Thread):
        def __init__(self, func, args, name=''):
            threading.Thread.__init__(self)
            self.name = name
            self.func = func
            self.args = args
    
        def run(self):
            apply(self.func, self.args)
    
    def main_thread():
        global sn
        threads = []
        nloops = xrange(thread_num)# thread_num 
        for i in nloops:
            mac, mac_real, sn = getMacSn()
            t = MyThread(main, (mac,mac_real,sn))
            threads.append(t)
        for i in nloops:
            threads[i].start()
        for i in nloops:
            threads[i].join()
    
    
    if __name__=='__main__':
        result = ''
        pool = multiprocessing.Pool(processes=proc)# processes 
        log.info("main process(%d) running..." % os.getpid())
        for i in xrange(proc_num):# proc_num  
            result = pool.apply_async(main_thread)
        pool.close()
        pool.join()
    
        if not result.successful():
            log.error(' :{}'.format(result.successful()))
        else:
            log.info('goodbye: ({}) '.format(os.getpid()))
    
    
  • は、ビジネス・コードで統計パラメータを計算し、メモリに積算して計算し、指定レベルのログに出力します.主な方法は、グローバル変数を設定することによって統一的に計算することです.
  • .
    class globalMap:
        #     map   
        map = {}
    
        def set_map(self, key, value):
            if(isinstance(value,dict)):
                value = json.dumps(value)
            self.map[key] = value
            log.debug(key + ":" + str(value))
    
    
        def set(self, **keys):
            try:
                for key_, value_ in keys.items():
                    self.map[key_] = str(value_)
                    log.debug(key_+":"+str(value_))
            except BaseException as msg:
                log.error(msg)
                raise msg
    
        def del_map(self, key):
            try:
                del self.map[key]
                return self.map
            except KeyError:
                log.error("key:'" + str(key) + "'   ")
    
    
        def get(self,*args):
            try:
                dic = {}
                for key in args:
                    if len(args)==1:
                        dic = self.map[key]
                        log.debug(key+":"+str(dic))
                    elif len(args)==1 and args[0]=='all':
                        dic = self.map
                    else:
                        dic[key]=self.map[key]
                return dic
            except KeyError:
                log.warning("key:'" + str(key) + "'   ")
                return 'Null_'
    
    

    まとめ


    マルチプロセスの方式とマルチスレッドを比較すると,Pythonグローバルロックの制限によりスレッドに多少の欠陥が生じるが,プロセスと比較して同時よりもいくつかのブロックを振ることができる.このように高密度のビジネスロジック操作を行うことで、サービス側のボトルネックを簡単に見つけることができます.
    @スモッグ-朝、布団の中-2018-01-14 10:17:13