Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building Python services through gRPC

Building Python services through gRPC

This presentations aims to show how to build services through gRPC in Python. It is presented 3 demos: A basic service covering all steps with Python+gRPC, a video streaming service and a TLS service. gRPC background, workflow, design and who is using are discussed as well.

Gustavo Pantuza

June 28, 2019
Tweet

More Decks by Gustavo Pantuza

Other Decks in Programming

Transcript

  1. Gustavo Pantuza

    View Slide

  2. Agenda
    ● What is gRPC?
    ● Background
    ● Who is using
    ● gRPC Workflow
    ● Demo 0
    ● gRPC Design
    ● Demo 1
    ● Security
    ● Demo 2
    ● References

    View Slide

  3. What is gRPC?
    "A high performance, open-source
    universal RPC framework"
    Project site: https://grpc.io
    Github: https://github.com/grpc

    View Slide

  4. What is gRPC?
    ● Remote Procedure Call
    ● Type Safe
    ● Polyglot
    ● Binary message format
    ● Multiplexed connections

    View Slide

  5. What is gRPC?
    A bunch of best practices gathered together
    to build a simple distributed systems tool
    My personal opinion

    View Slide

  6. What is gRPC?

    View Slide

  7. Background
    ● General-purpose RPC infrastructure called Stubby
    Open Source

    View Slide

  8. Background
    Connect the large
    number of
    microservices running
    within and across our
    data centers

    View Slide

  9. Background
    Cloud Native
    Computing
    Foundation To Host
    gRPC from Google

    View Slide

  10. Who is using?
    "We’ve also seen a
    squishing and a
    narrowing of our
    latency windows"
    https://www.cncf.io/netflix-case-study/

    View Slide

  11. Who is using?
    "Implementing
    GRPC/Telemetry on
    XR devices"
    https://community.cisco.com/t5/service-providers-documents/implementing-grpc-telemetry-on-xr-devices/ta-p/3393966

    View Slide

  12. Who is using?
    "distribution layer is
    the first layer to
    communicate with
    other nodes"
    https://www.cockroachlabs.com/docs/stable/architecture/distribution-layer.html

    View Slide

  13. Who is using?
    "more compact and
    efficiently serializable
    RPC payload"
    https://cilium.io/blog/grpc/

    View Slide

  14. Who is using?
    "layers the best
    features of
    IDL-specified RPC
    onto a standard"
    https://linkerd.io/2017/01/11/http2-grpc-and-linkerd/#_ga=2.36853351.619173598.1561427300-69268088.1561427300

    View Slide

  15. Who is using?
    https://stackshare.io/grpc

    View Slide

  16. gRPC Workflow
    ● The Message Protocol

    View Slide

  17. gRPC Workflow
    ● The Message Protocol
    Message
    definition
    protoc
    Compiler
    Python
    Go
    C++

    View Slide

  18. syntax = "proto3";
    package cheesefarm;
    Define the
    version and the
    package
    gRPC Workflow

    View Slide

  19. syntax = "proto3";
    package cheesefarm;
    message Cheese {
    int32 age = 1;
    CheeseType type = 2;
    }
    enum CheeseType {
    EMMENTAL = 0;
    BRIE = 1;
    PECORINO = 2;
    ROQUEFORT = 3;
    CANASTRA = 4;
    }
    message CheeseRequest {
    CheeseType type = 1;
    }
    Create your
    messages
    gRPC Workflow

    View Slide

  20. syntax = "proto3";
    package cheesefarm;
    message Cheese {
    int32 age = 1;
    CheeseType type = 2;
    }
    enum CheeseType {
    EMMENTAL = 0;
    BRIE = 1;
    PECORINO = 2;
    ROQUEFORT = 3;
    CANASTRA = 4;
    }
    message CheeseRequest {
    CheeseType type = 1;
    }
    service CheeseService {
    rpc Order(CheeseRequest) returns (Cheese);
    }
    Describe your
    Service interface
    gRPC Workflow

    View Slide

  21. $> # Install gRPC libraries
    $> pip install grpcio
    $> pip install grpcio-tools
    Install gRPC
    Python libraries
    gRPC Workflow

    View Slide

  22. $> # Compile gRPC files with Python
    $> # as target language in
    $> # the current directory
    $> python -m grpc_tools.protoc \
    -I. \
    --python_out=. \
    --grpc_python_out=. \
    cheese.proto
    Compilation
    time
    gRPC Workflow

    View Slide

  23. $> # Two new files generated:
    $> # 1. cheese_pb2.py
    $> Protocol Buffer message
    $> # 2. cheese_pb2_grpc.py
    $> gRPC Service Client/Server
    $> ls cheese_pb2*
    cheese_pb2.py cheese_pb2_grpc.py
    Compilation
    Results
    gRPC Workflow

    View Slide

  24. # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
    import grpc
    import cheese_pb2 as cheese__pb2
    class CheeseServiceStub(object):
    # missing associated documentation comment in .proto file
    pass
    def __init__(self, channel):
    """Constructor.
    Args:
    channel: A grpc.Channel.
    """
    self.Order = channel.unary_unary(
    '/cheesefarm.CheeseService/Order',
    request_serializer=cheese__pb2.CheeseRequest.SerializeToString,
    response_deserializer=cheese__pb2.Cheese.FromString,
    )
    class CheeseServiceServicer(object):
    # missing associated documentation comment in .proto file
    pass
    def Order(self, request, context):
    # missing associated documentation comment in .proto file
    pass
    context.set_code(grpc.StatusCode.UNIMPLEMENTED)
    context.set_details('Method not implemented!')
    raise NotImplementedError('Method not implemented!')
    Resulted code
    example
    gRPC Workflow

    View Slide

  25. import grpc
    from concurrent import futures
    from time import sleep
    from random import randint
    # Imports all Protoc generated classes/code
    import cheese_pb2
    import cheese_pb2_grpc
    class CheeseService(cheese_pb2_grpc.CheeseServiceServicer):
    """ Extends the auto generated CheeseServiceServicer class from Protoc
    compiler. In this class we implement the service layer code
    """
    def Order(self, request, context):
    """ Simulates a Cheese Order load and returns a Cheese """
    # Implementation here
    def main():
    # gRPC server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # Binds our service implementation to a gRPC server through the
    # auto generated function add_CheeseServiceServicer_to_server
    cheese_pb2_grpc.add_CheeseServiceServicer_to_server(CheeseService(), server)
    print('Listening on localhost:4000')
    server.add_insecure_port('localhost:4000')
    server.start()
    # server.start() will not block, so we run a sleep-loop to keep
    # alive server alive until an interruption
    try:
    while True:
    sleep(60 * 60) # Each hour the loop continues
    except KeyboardInterrupt:
    server.stop(0)
    Server
    Implementation
    gRPC Workflow

    View Slide

  26. from random import randint
    import grpc
    # Imports all Protoc generated classes/code
    import cheese_pb2
    import cheese_pb2_grpc
    def main():
    # gRPC channel
    channel = grpc.insecure_channel('localhost:4000')
    # create a stub (client) of our service
    stub = cheese_pb2_grpc.CheeseServiceStub(channel)
    while True:
    # Do cheeses orders
    cheese_request = cheese_pb2.CheeseRequest(type=randint(0, 4))
    cheese = stub.Order(cheese_request)
    print("[gRPC] Received={0}".format(
    cheese_pb2.CheeseType.Name(cheese.type)))
    if __name__ == "__main__":
    main()
    Client
    Implementation
    gRPC Workflow

    View Slide

  27. Demo 0
    The Cheese
    Service

    View Slide

  28. Demo 0

    View Slide

  29. gRPC Design
    Http/2 by design
    ● Binary payload
    ● Multiplexed connections
    ● Extensible

    View Slide

  30. gRPC Design
    Streaming
    // From Server to Client
    rpc ListFeatures(Rectangle) returns (stream Feature) {}
    // From Client to Server
    rpc RecordRoute(stream Point) returns (RouteSummary) {}
    // Bidirectional
    rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
    The classic pair Send() and Recv() from socket library

    View Slide

  31. gRPC Design
    Server streaming
    // From Server to Client
    rpc Watch(Match) returns (stream Video) {}

    View Slide

  32. gRPC Design
    Client streaming
    // From client to Client
    rpc Upload(stream chunks) returns (Done) {}

    View Slide

  33. Demo 1
    The Soccer
    Match Service

    View Slide

  34. syntax = "proto3";
    package stream;
    message Match {
    string id = 1;
    }
    message Video {
    bytes data = 1;
    string data_type = 2;
    string data_shape = 3;
    }
    service Soccer {
    rpc Watch (Match) returns (stream Video) {}
    }
    Protocol
    Buffer
    Demo 1

    View Slide

  35. class SoccerService(stream_pb2_grpc.SoccerServicer):
    """ Soccer Matches stream service based on gRPC """
    def Watch(self, request, context):
    """ Returns a stream to a Match stream """
    print("[gRPC] Match={0}".format(request.id))
    file_path = "{0}.mp4".format(request.id)
    match = cv2.VideoCapture(file_path)
    while match.isOpened():
    ret_val, frame = match.read()
    if not ret_val:
    break
    video = stream_pb2.Video(
    data=frame.tobytes(),
    data_type=frame.dtype.name,
    data_shape=str(frame.shape),
    )
    yield video
    match.release()
    Server
    Implementation
    Demo 1

    View Slide

  36. def main():
    channel = grpc.insecure_channel('localhost:4000')
    stub = stream_pb2_grpc.SoccerStub(channel)
    match = stream_pb2.Match(id="KKNuUdn4wI4")
    iterator = stub.Watch(match)
    try:
    for video in iterator:
    frame = np.frombuffer(
    video.data,
    dtype=video.data_type
    ).reshape(literal_eval(video.data_shape))
    cv2.imshow(match.id, frame)
    if cv2.waitKey(1) == 27:
    break # esc to quit
    cv2.destroyAllWindows()
    except grpc._channel._Rendezvous as err:
    print(err)
    sleep(3)
    Client
    Implementation
    Demo 1

    View Slide

  37. Demo 1
    The Soccer
    Match Service

    View Slide

  38. gRPC Design
    Bidirectional streaming
    // Bidirectional
    rpc Chat(stream video) returns (stream video) {}

    View Slide

  39. gRPC Design
    Blocking & Non-Blocking

    View Slide

  40. gRPC Design
    Cancellation & Timeout

    View Slide

  41. gRPC Design
    Pluggable
    Large distributed systems need:
    ● Security
    ● Health-checking
    ● Load-balancing
    ● Failover
    ● Monitoring
    ● Tracing
    ● logging
    Python Interceptor example

    View Slide

  42. gRPC Design
    Standardized Status Codes
    CODE NUMBER
    OK 0
    CANCELLED 1
    UNKNOWN 2
    INVALID_ARGUMENT 3
    ... ...
    https://github.com/grpc/grpc/blob/master/doc/statuscodes.md

    View Slide

  43. gRPC security
    Supported and
    Authentication
    methods
    https://grpc.io/docs/guides/auth/

    View Slide

  44. gRPC security
    TLS
    On the Server
    # gRPC server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    cheese_pb2_grpc.add_CheeseServiceServicer_to_server(CheeseService(), server)
    # Load SSL files
    ssl_key = open("ssl/private.key", "rb").read()
    ssl_cert = open("ssl/cert.pem", "rb").read()
    credentials = grpc.ssl_server_credentials([(ssl_key, ssl_cert)])
    print('Listening on localhost:4000')
    server.add_secure_port('localhost:4000', credentials)
    server.start()

    View Slide

  45. gRPC security
    TLS
    On the Client
    # Load Certificate file
    trusted_cert = open("ssl/cert.pem", "rb").read()
    credentials = grpc.ssl_channel_credentials(root_certificates=trusted_cert)
    # gRPC channel
    channel = grpc.secure_channel('localhost:4000', credentials)
    # create a stub (client) of our service
    stub = cheese_pb2_grpc.CheeseServiceStub(channel)

    View Slide

  46. Demo 2
    The Cheese
    SECURE Service

    View Slide

  47. gRPC References
    ● Official project site
    ● Official project Repositories
    ● Awesome gRPC project
    ● Official examples for other languages
    ● Protocol Buffer official site

    View Slide

  48. gRPC Python Examples
    ● A simplified guide to gRPC in Python
    ● gRPC Basics - Python
    ● Python Quick Start
    ● Python gRPC official example
    ● Tutorial – Writing your first gRPC service in Python

    View Slide

  49. Hey developers,
    please,
    play with me <3

    View Slide