ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

grpc压力测试 基于Locust 父类和client重写

2020-05-01 18:51:44  阅读:234  来源: 互联网

标签:None name pb2 grpc Locust helloworld client response


proto文件helloword.proto:

// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  bytes message = 1;
}

 grpc_server.py:

# Copyright 2015 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The Python implementation of the GRPC helloworld.Greeter server."""

from concurrent import futures
import logging

import grpc

import helloworld_pb2
import helloworld_pb2_grpc


class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message= request.name)


def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()


if __name__ == '__main__':
    logging.basicConfig()
    serve()

helloword_pb2.py

# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: helloworld.proto

from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()




DESCRIPTOR = _descriptor.FileDescriptor(
  name='helloworld.proto',
  package='helloworld',
  syntax='proto3',
  serialized_options=b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW',
  serialized_pb=b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3'
)




_HELLOREQUEST = _descriptor.Descriptor(
  name='HelloRequest',
  full_name='helloworld.HelloRequest',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='name', full_name='helloworld.HelloRequest.name', index=0,
      number=1, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=b"".decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  serialized_options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=32,
  serialized_end=60,
)


_HELLOREPLY = _descriptor.Descriptor(
  name='HelloReply',
  full_name='helloworld.HelloReply',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='message', full_name='helloworld.HelloReply.message', index=0,
      number=1, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=b"".decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  serialized_options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=62,
  serialized_end=91,
)

DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST
DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY
_sym_db.RegisterFileDescriptor(DESCRIPTOR)

HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), {
  'DESCRIPTOR' : _HELLOREQUEST,
  '__module__' : 'helloworld_pb2'
  # @@protoc_insertion_point(class_scope:helloworld.HelloRequest)
  })
_sym_db.RegisterMessage(HelloRequest)

HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), {
  'DESCRIPTOR' : _HELLOREPLY,
  '__module__' : 'helloworld_pb2'
  # @@protoc_insertion_point(class_scope:helloworld.HelloReply)
  })
_sym_db.RegisterMessage(HelloReply)


DESCRIPTOR._options = None

_GREETER = _descriptor.ServiceDescriptor(
  name='Greeter',
  full_name='helloworld.Greeter',
  file=DESCRIPTOR,
  index=0,
  serialized_options=None,
  serialized_start=93,
  serialized_end=166,
  methods=[
  _descriptor.MethodDescriptor(
    name='SayHello',
    full_name='helloworld.Greeter.SayHello',
    index=0,
    containing_service=None,
    input_type=_HELLOREQUEST,
    output_type=_HELLOREPLY,
    serialized_options=None,
  ),
])
_sym_db.RegisterServiceDescriptor(_GREETER)

DESCRIPTOR.services_by_name['Greeter'] = _GREETER

# @@protoc_insertion_point(module_scope)

helloword_pb2_grpc.py:

# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc

import helloworld_pb2 as helloworld__pb2


class GreeterStub(object):
    """The greeting service definition.
    """

    def __init__(self, channel):
        """Constructor.

        Args:
            channel: A grpc.Channel.
        """
        self.SayHello = channel.unary_unary(
                '/helloworld.Greeter/SayHello',
                request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
                response_deserializer=helloworld__pb2.HelloReply.FromString,
                )


class GreeterServicer(object):
    """The greeting service definition.
    """

    def SayHello(self, request, context):
        """Sends a greeting
        """
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')


def add_GreeterServicer_to_server(servicer, server):
    rpc_method_handlers = {
            'SayHello': grpc.unary_unary_rpc_method_handler(
                    servicer.SayHello,
                    request_deserializer=helloworld__pb2.HelloRequest.FromString,
                    response_serializer=helloworld__pb2.HelloReply.SerializeToString,
            ),
    }
    generic_handler = grpc.method_handlers_generic_handler(
            'helloworld.Greeter', rpc_method_handlers)
    server.add_generic_rpc_handlers((generic_handler,))


 # This class is part of an EXPERIMENTAL API.
class Greeter(object):
    """The greeting service definition.
    """

    @staticmethod
    def SayHello(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello',
            helloworld__pb2.HelloRequest.SerializeToString,
            helloworld__pb2.HelloReply.FromString,
            options, channel_credentials,
            call_credentials, compression, wait_for_ready, timeout, metadata)

项目结构:

demos
├─.idea
├─dependency
├─protos
└─python
└─helloword

     ---greeter_server.py

     ---helloworld_pb2.py

     ---helloworld_pb2_grpc.py

└─__pycache__

 压力测试类:

import logging
import time
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
import json
from locust import (TaskSet, task, events, Locust)
from gevent._semaphore import Semaphore
import random

log_fmt = "[%(levelname)s]%(asctime)s line %(lineno)d :\n%(message)s"
c_fmt = "[%(levelname)s]%(asctime)s %(filename)s.%(funcName)s():line %(lineno)d :\n%(message)s"
date_format = "%Y-%m-%d %H:%M:%S %a"
# 设置控制台输出level
logging.basicConfig(level=logging.INFO,
                    format=c_fmt,
                    datefmt=date_format
                    )
all_locusts_spawned = Semaphore()
all_locusts_spawned.acquire()
host = "192.168.110.135"
port = "50051"


def on_hatch_complete(**kwargs):
    all_locusts_spawned.release()


events.hatch_complete += on_hatch_complete


def run():
    """test grpc server demo """
    with grpc.insecure_channel('192.168.110.135:50051') as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        req = {"name": "jack", "id": 1001}
        body = json.dumps(req).encode("utf-8")
        response = stub.SayHello(helloworld_pb2.HelloRequest(name=body))
    print(response.message)  # str


class GrpcClient(object):
    """overide client"""

    def __init__(self):
        self.host = host
        self.port = port

    def grpc_request(self, body):
        start_time = int(time.time())
        response = None
        try:
            address = "{}:{}".format(host, port)
            channel = grpc.insecure_channel(address)
            # p2_grpc.Stub class implement new locust client
            client_stub = helloworld_pb2_grpc.GreeterStub(channel=channel)
            request_object = helloworld_pb2.HelloRequest(name=body)
            back_req = client_stub.SayHello(request_object)
            response = back_req.message
            elapsed = int((time.time() - start_time) * 1000)
            text = json.loads(response)
            logging.info("get response is {}".format(response))
            if text["retcode"] != 0:
                raise Exception("response get not expect,actual is {}".format(text))
            events.request_success.fire(
                request_type='grpc',
                name=r'/SayHello',
                response_time=elapsed,
                response_length=0
            )
        except Exception as e:
            total_time = int((time.time() - start_time) * 1000)
            events.request_failure.fire(
                request_type='grpc',
                name='/SayHello',
                response_time=total_time,
                exception=e
            )

        return response


class GrpcLocust(Locust):
    """ overide Locust to implement GrpcLocust"""

    def __init__(self, *args, **kwargs):
        super(GrpcLocust, self).__init__()
        self.client = GrpcClient()


class GrpcUserBehavior(TaskSet):
    """ super TaskSet class implement new GrpcTaskSet"""

    def on_task(self):
        """wait task event spawn"""
        all_locusts_spawned.wait()

    def on_stop(self):
        pass

    @task
    def inference_task(self):
        code = random.choice([101, 102, 0, 0])
        data = {"name": "{}".format("ZhangSan"), "retcode": code}
        body = json.dumps(data).encode("utf-8")
        response_msg = self.client.grpc_request(body)
        # print(response_msg)


class WebsiteUser(GrpcLocust):
    task_set = GrpcUserBehavior
    min_wait = 200  # think time ms
    max_wait = 500

  压力测试命令:locust -f grpc_client.py -c 4 -r 2  --run-time 15s --no-web


[2020-05-01 18:45:25,820] DESKTOP-PBNSFDJ/INFO/root: get response is {"name": "ZhangSan", "retcode": 101}
[2020-05-01 18:45:25,870] DESKTOP-PBNSFDJ/INFO/root: get response is {"name": "ZhangSan", "retcode": 101}
[2020-05-01 18:45:26,012] DESKTOP-PBNSFDJ/INFO/root: get response is {"name": "ZhangSan", "retcode": 102}
[2020-05-01 18:45:26,083] DESKTOP-PBNSFDJ/INFO/root: get response is {"name": "ZhangSan", "retcode": 101}
[2020-05-01 18:45:26,088] DESKTOP-PBNSFDJ/INFO/root: get response is {"name": "ZhangSan", "retcode": 0}
[2020-05-01 18:45:26,129] DESKTOP-PBNSFDJ/INFO/locust.main: Time limit reached. Stopping Locust.
[2020-05-01 18:45:26,130] DESKTOP-PBNSFDJ/INFO/locust.main: Shutting down (exit code 1), bye.
[2020-05-01 18:45:26,130] DESKTOP-PBNSFDJ/INFO/locust.main: Cleaning up runner...
[2020-05-01 18:45:26,131] DESKTOP-PBNSFDJ/INFO/locust.main: Running teardowns...
Name # reqs # fails Avg Min Max | Median req/s
--------------------------------------------------------------------------------------------------------------------------------------------
grpc /SayHello 158 87(35.51%) 532 10 1052 | 540 11.40
--------------------------------------------------------------------------------------------------------------------------------------------
Total 158 87(55.06%) 11.40

Percentage of the requests completed within given times
Name # reqs 50% 66% 75% 80% 90% 95% 98% 99% 100%
--------------------------------------------------------------------------------------------------------------------------------------------
grpc /SayHello 158 540 690 760 840 960 980 990 1000 1100
--------------------------------------------------------------------------------------------------------------------------------------------
Total 158 540 690 760 840 960 980 990 1000 1100

Error report
# occurrences Error
--------------------------------------------------------------------------------------------------------------------------------------------
46 grpc /SayHello: 'Exception("response get not expect,actual is {\'name\': \'ZhangSan\', \'retcode\': 101}")'
41 grpc /SayHello: 'Exception("response get not expect,actual is {\'name\': \'ZhangSan\', \'retcode\': 102}")'
--------------------------------------------------------------------------------------------------------------------------------------------

web模式:

 

标签:None,name,pb2,grpc,Locust,helloworld,client,response
来源: https://www.cnblogs.com/SunshineKimi/p/12814345.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有