Skip to content

sofa-pbrpc cookie功能设计 #79

Description

@zd-double

背景

在rpc的应用场景中,用户需要传输非protobuf协议封装的数据,数据的格式和操作由用户定义,这些数据最终都以字节流的方式在client和server之间传输。需要在sofa-pbrpc内部实现一套attachment机制,支持用户自定义附加数据的格式和操作,用户在client端设置附加数据,server端接受并进行操作。基于该机制为用户提供默认的Cookie插件,用于存储和传输logid等client端的状态信息。

功能

实现sofa-pbrpc attachment机制,支持用户附加数据,附加数据的定义和操作在用户层实现。并基于此机制实现cookie插件

接口设计

  • 在sofa-pbrpc中实现RpcAttachment的基类,包括Serialize和Deserialize的接口,用户层实现插件继承RpcAttachment并在此基础上实现增删改查的操作,用户在client中通过RpcController的set_request_attachment的接口设置附加数据,并调用Serialize接口将用户附加数据进行序列化,Append在request_buffer之后进行发送。
  • 在RpcServer端对收到的请求数据反序列化,在请求数据的末尾获取用户的附加数据,通过controller传输给用户。用户调用RpcController::
    GetRequestAttachment(RpcAttachment& attach), 利用attach对象的Deserialize接口将附加数据反序列化。Server端可以对attachment数据进行增删改查

Attachment基类:

class RpcAttachment
{
public:
    virtual ~RpcAttachment() { }
    virtual bool Serialize(ReadBufferPtr attactment_buffer) = 0;
    virtual bool Deserialize (ReadBufferPtr attachment_buffer) = 0;
};

RpcController增加接口:

RpcAttachmentPtr_request_attachment; //RPC请求的附加数据buffer
RpcAttachmentPtr _response_attachment; //RPC应答的附加数据buffer
ReadBufferPtr _request_attach_buffer; //RPC请求的附加数据buffer
ReadBufferPtr _response_attach_buffer; //RPC应答的附加数据buffer
//用户接口
//设置请求的附加数据
void SetRequestAttachment(RpcAttachment* request_attachment);
//获取请求的附加数据
void GetRequestAttachment(RpcAttachment* request_attachment);
//设置应答的附加数据
void SetResponseAttachment(RpcAttachment* response_attachment);
//获取应答的附加数据
void GetResponseAttachment(RpcAttachment* response_attachment);
//Rpc内部接口
//设置request_attachment_buffer
void SetRequestAttachmentBuffer(const ReadBufferPtr& attachment_buffer);
//获取request_attachment_buffer
const ReadBufferPtr& GetRequestBuffer() const;
//设置response_attachment_buffer
void SetResponseAttachmentBuffer(const ReadBufferPtr& attachment_buffer);
////获取response_attachment_buffer
const ReadBufferPtr& GetResponseBuffer() const;

使用方法

Cookie插件:

Class RpcCookie : public sofa::pbrpc:: RpcAttachment
{
    virtual bool Serialize(ReadBufferPtr& attactment_buffer) ;
    virtual bool Deserialize (const ReadBufferPtr& attachment_buffer);
    void Get(const std::string key, std::string& value);
    void Set(const std::string& key, const std::string value); 
    void Erase(const std::string& key);
    void Clear();
}

Client端示例:

    sofa::pbrpc::RpcController* cntl = new sofa::pbrpc::RpcController();
    cntl->SetTimeout(3000);
    CookiePtr cookie(new Cookie());
    cookie->set("type", "sync");
    cntl->SetRequestAttachment(cookie.get());
    sofa::pbrpc::test::EchoRequest* request = new sofa::pbrpc::test::EchoRequest();
    request->set_message("Hello from client");
    sofa::pbrpc::test::EchoResponse* response = new sofa::pbrpc::test::EchoResponse();
    sofa::pbrpc::test::EchoServer_Stub* stub =new sofa::pbrpc::test::EchoServer_Stub(&rpc_channel);
    stub->Echo(cntl, request, response, NULL);
    if (cntl->Failed())
    {
        SLOG(ERROR, "request failed: %s", cntl->ErrorText().c_str());
    }
    else
    {
        cookie.reset(new Cookie());
        cntl->GetResponseAttachment(cookie.get());
        std::string version;
        cookie->Get(“version”, version);
        SLOG(NOTICE, "request succeed: %s, version: %s", response->message().c_str(), version.c_str());
    }

Server端示例:

   virtual void Echo(google::protobuf::RpcController* controller,
                      const sofa::pbrpc::test::EchoRequest* request,
                      sofa::pbrpc::test::EchoResponse* response,
                      google::protobuf::Closure* done)
    {
        sofa::pbrpc::RpcController* cntl = static_cast<sofa::pbrpc::RpcController*>(controller);
        SLOG(INFO, "Echo(): request message from %s: %s",
                cntl->RemoteAddress().c_str(), request->message().c_str());
        CookiePtr cookie(new Cookie());
        cntl->GetRequestAttachment(cookie.get());
        cookie->Set(“version”, “1.00”);
        cntl->SetResponseAttachment(cookie.get());
        response->set_message("echo message: " + request->message());
        done->Run();
    }

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions