Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sofa-pbrpc cookie功能设计 #79

Open
zd-double opened this issue Mar 18, 2016 · 7 comments
Open

sofa-pbrpc cookie功能设计 #79

zd-double opened this issue Mar 18, 2016 · 7 comments

Comments

@zd-double
Copy link
Collaborator

背景

在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();
    }
@zd-double
Copy link
Collaborator Author

@qinzuoyan ,左言有什么建议?

@qinzuoyan
Copy link
Collaborator

这个和sofa里面的cookie机制是一样的吗?实现上有什么区别?

@zd-double
Copy link
Collaborator Author

sofa里的cookie是在库里边实现的,即数据格式规定是kv map。这个设计在库里边增加了RpcAttachment基类、序列化反序列化接口以及用户接口,cookie作为插件在用户层继承RpcAttachment,定义了数据格式和序列化、反序列化操作等。

@qinzuoyan
Copy link
Collaborator

恩,明白了,这个要赞,用户可定制自己的attachment,更灵活。

另外我建议,可以实现一些常见的实现,在编译的时候,可以类似protobuf一样生成一个lite库和一个full库。譬如可以在full库中提供这些常见实现:

  • Cookie,实现RpcAttachment接口;
  • BufferAttachment,实现RpcAttachment接口,用于传输大数据,避免通过Message的string字段传输时增加序列化/反序列化代价,使用者可以之间在Buffer上进行操作。这个对实现传输数据量很大的系统(譬如DFS)非常有用;
  • ZookeeperAddressProvier,实现AddressProvider接口,用于从Zookeeper动态获取server地址,参见生产环境中的上线切流量问题 #78

@zd-double
Copy link
Collaborator Author

@qinzuoyan ,左言有时间帮忙审核一下pr#81?

@qinzuoyan
Copy link
Collaborator

Ok, 最近找时间review

On Mon, Apr 4, 2016 at 10:44 PM, zd-double [email protected] wrote:

@qinzuoyan https://github.com/qinzuoyan ,左言有时间帮忙审核一下pr#81
#81?


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#79 (comment)

@stonehuang1024
Copy link

赞!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants