Derecho: Group communication at the speed of light

Version 0.9.1

Derecho is a new distributed system out of Cornell University

The function tier

The function tier represents the initial ingress layer of our sample application. Its job is to receive requests via Google’s gRPC protocol, to select a backend node to handle the request, and to forward that request along via Derecho’s p2p_send. Let’s take a look at the header:

#pragma once
#include <derecho/core/derecho.hpp>
#include <derecho/mutils-serialization/SerializationSupport.hpp>
#include <function_tier.grpc.pb.h>
#include <grpcpp/grpcpp.h>
#include <memory>
#include <mutex>

namespace sospdemo {

#define FUNCTION_TIER_GRPC_PORT_BASE (28000)


class FunctionTier : public mutils::ByteRepresentable,
                     public derecho::GroupReference,
                     public FunctionTierService::Service {
protected:
    std::map<uint64_t, ssize_t> tag_to_shard;

    std::atomic<bool> started;
    std::mutex service_mutex;
    std::unique_ptr<grpc::Server> server;

    virtual grpc::Status Whatsthis(grpc::ServerContext* context,
                                   grpc::ServerReader<PhotoRequest>* reader,
                                   PhotoReply* reply) override;
    virtual grpc::Status InstallModel(grpc::ServerContext* context,
                                      grpc::ServerReader<InstallModelRequest>* reader,
                                      ModelReply* reply) override;
    virtual grpc::Status RemoveModel(grpc::ServerContext* context,
                                     const RemoveModelRequest* request,
                                     ModelReply* reply) override;

    virtual void start();
    virtual void shutdown();

public:
    FunctionTier() {
        started = false;
        start();
    }
    FunctionTier(std::map<uint64_t, ssize_t>& rhs) {
        this->tag_to_shard = std::move(rhs);
        started = false;
        start();
    }
    virtual ~FunctionTier();
    static auto register_functions() { return std::tuple<>(); };
    DEFAULT_SERIALIZATION_SUPPORT(FunctionTier, tag_to_shard);
};

} 

Much of this code is required to implement the gRPC layer. We’ll highlight those as needed, but mostly focus on the Derecho components of this class.

Includes and superclasses

#include <derecho/core/derecho.hpp>
#include <derecho/mutils-serialization/SerializationSupport.hpp>
#include <function_tier.grpc.pb.h>
#include <grpcpp/grpcpp.h>
#include <memory>
#include <mutex>

The thing to notice here is that, beyond including the derecho/core/derecho.hpp header included by most Derecho-using components, we’re also including the SerializatonSupport.hpp header. This is a lightweight serialization framework which provides macros via which one can generate serialization and deserialization code. We’re also including two libraries (function_tier.grpc.pb.h, grpcpp/grpcpp.h) to support gRPC, and some standard C++ libraries.

More interesting is the superclasses extended by our function tier:

class FunctionTier : public mutils::ByteRepresentable,
                     public derecho::GroupReference,
                     public FunctionTierService::Service

The ByteRepresentable class works with SerializationSupport to mark this class as serializable.

The GroupReference class, taking inspiration from the std::enable_shared_from_this, will provide a member pointer called group which can be used within the FunctionTier to access the group to which this FunctionTier instance belongs.

The FunctionTierService::Service class is generated by gRPC, and provides entry points for receiving gRPC messages.

gRPC entry points

    virtual grpc::Status Whatsthis(grpc::ServerContext* context,
                                   grpc::ServerReader<PhotoRequest>* reader,
                                   PhotoReply* reply) override;
    virtual grpc::Status InstallModel(grpc::ServerContext* context,
                                      grpc::ServerReader<InstallModelRequest>* reader,
                                      ModelReply* reply) override;
    virtual grpc::Status RemoveModel(grpc::ServerContext* context,
                                     const RemoveModelRequest* request,
                                     ModelReply* reply) override;

These method signatures are generated by gRPC to receive requests as defined by our protocol files. These requests will then be forwarded on to the categorizer tier via Derecho. The Whatsthis request receives a photo to identify and a list of previously-installed image models to use when recognizing the photo. The InstallModel request installs a new model for use when recognizing images. The RemoveModel request removes a previously-installed model.

Derecho Registration

Way down at the bottom of the class, we have two lines which are required for Derecho:

    static auto register_functions() { return std::tuple<>(); };
    DEFAULT_SERIALIZATION_SUPPORT(FunctionTier, tag_to_shard);

The first line (register_functions) specifies which methods for this class should be invokable via p2p_send or ordered_send. Since this class does not receive unsolicited messages from within Derecho, we don’t have to register any particular functions as Derecho RPC targets.

The second line tells the serialization framework which fields of this class should be serialized as part of this class. In this case, we’re only serializing the map tag_to_shard; we leave off the other fields, as we don’t want to try and send an atomic boolean or mutex over the network!

The parts of this class which we didn’t highlight are largely straightforward, or boilerplate required by the gRPC layer.

Last updated on 22 Oct 2019
Published on 22 Oct 2019
Edit on GitHub