GRPC协议兼容问题

最近因为GRPC协议兼容问题受困,于是做了一些实验来验证其原理

proto文件


syntax = "proto3";
package IRPC;

message REQHEADER
{
    uint32    nState=1;                    //校验位 表面数据类型,为了快速定错。0-    无数据 1-    请求数据
    uint32    nByteLen=2;                    //整个grpc请求或响应数据的总长度
    uint32    nCrc=3;                        //整个grpc请求或响应数据的crc校验---32位crc
    uint32    nEnType=4;                    //内容数据是否使用了加密 0-    无加密1-AES加密 2-SM4加密
    uint32    nErrCode=5;                    //错误码---如果是请求包,则该字段=0 如果是响应数据 则=对应的错误码
    uint32    nPort=6;                    //服务端grpc端口  用来定位问题
    string    strFunName=7;                //函数名称  请求时=请求者的函数名 响应时=服务端的函数名
    string    strUser=8;                    //进程名称  请求时=请求者的进程名称 响应时=服务端的进程名称--用来定位问题
    string    strTime=9;                    //时间戳 "2021-12-29 09:08:23:332"
    string    strKey=10;                    //加密的密钥
    string    strUuid=11;                    //每次请求的唯一ID 用于异步回调
}
message REQ
{    
    bytes         adata = 1;                //数据
    string        aa=2;
    string        ab=3;
    string        ae=4;
    REQHEADER    aheader=5;
}
message REP
{
    bytes data = 1;//数据
}
service S
{
    rpc F (REQ) returns (REP);
}
 

请求端

std::thread getIdThread([&]()
    {
        grpc_init();
        const auto len = 24 * 1024 * 1024;
        ChannelArguments arg;
        arg.SetMaxReceiveMessageSize(len);

        //arg.SetInt("grpc.max_receive_message_length", len);

        std::string addr = "127.0.0.1:8899";
        auto chan = grpc::CreateCustomChannel(addr,grpc::InsecureChannelCredentials(),arg);
        m_cli = IRPC::S::NewStub(chan);
        int index=0;
        while( true )
        {
            ClientContext ctx;

            IRPC::REQ req;
            req.set_aa("aa");
            req.set_ab("ab");
            req.set_adata("xxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzzzzz");
            req.set_ae("ae");
            IRPC::REQHEADER* pheader = req.mutable_aheader();
            pheader->set_nstate(100);
            pheader->set_nbytelen(200);
            pheader->set_ncrc(300);
            pheader->set_nentype(400);
            pheader->set_nerrcode(500);
            pheader->set_nport(666);
            pheader->set_strfunname("strfunname");
            pheader->set_struser("struser");
            pheader->set_strtime("strtime");
            pheader->set_strkey("strkey");
            pheader->set_struuid("struuid");
            IRPC::REP rep;
            Status s = m_cli->F(&ctx,req,&rep);
            if( !s.ok() )
            {
                std::cout<<"errmsg="<<s.error_message()<<endl;
                grpc::StatusCode e = s.error_code();
                std::cout<<"errcode="<<e<<endl;
            }
            int ns=req.ByteSizeLong();

            std::cout<<"send len="<<ns<<endl;
            std::cout<<"idx="<<index++<<endl;
            usleep(1000);
        }

    });
    getIdThread.detach();

服务端

.class CServ:public IRPC::S::Service
{
public:
    CServ(){}
    ~CServ(){}
    Status F(grpc::ServerContext *context, const IRPC::REQ *request, IRPC::REP *response) override;
};

Status CServ::F(grpc::ServerContext *ctx, const IRPC::REQ *req, IRPC::REP *rep)
{
    return Status::OK;
}

启动服务端

 std::thread getIdThread([&]()
    {
        grpc_init();
        m_serv= std::make_shared<CServ>();
        ServerBuilder serverBuilder;

        const auto maxSize = 24 * 1024 * 1024;
        serverBuilder.SetMaxSendMessageSize(maxSize);
        serverBuilder.SetMaxReceiveMessageSize(maxSize);
        //grpc::SslCredentials(grpc::SslCredentialsOptions());
        std::string addr = "0.0.0.0:8899";
        serverBuilder.AddListeningPort(addr, grpc::InsecureServerCredentials());
        serverBuilder.RegisterService(m_serv.get());
        std::unique_ptr<Server> server(serverBuilder.BuildAndStart());
        server->Wait();

    });
    getIdThread.detach();

实验1:请求端与服务端协议乱序

请求端:

message REQ
{    
    bytes         adata = 1;                //数据
    string        aa=2;
    string        ab=3;
    string        ae=4;
    REQHEADER    aheader=5;
}

服务端:

message REQ
{    

    string        aa=1;

    string        ab=2;
    bytes         adata = 3;  
    string        ae=4;
    REQHEADER    aheader=5;
}

结果:请求失败,错误码:StatusCode::UNIMPLEMENTED

实验2:协议对齐-请求协议尾部顺序缺少数据

请求端:

message REQ
{    
    bytes         adata = 1;                //数据
    string        aa=2;
    string        ab=3;
    string        ae=4;
    
}

服务端:

message REQ
{    
    bytes         adata = 1;                //数据
    string        aa=2;
    string        ab=3;
    string        ae=4;

    REQHEADER    aheader=5;
}

结果:请求成功,服务端收到的aheader内容均为0

实验2:协议对齐-请求协议尾部顺序多余数据

请求端:

message REQ
{    
    bytes         adata = 1;                //数据
    string        aa=2;
    string        ab=3;
    string        ae=4;
    REQHEADER    aheader=5;
}

服务端:

message REQ
{    
    bytes         adata = 1;                //数据
    string        aa=2;
    string        ab=3;
    string        ae=4;
}

结果:请求成功

结论:GRPC协议只要双方按照顺序完全对其,只能有一方协议冗余,冗余数据自动补零,向前、向后兼容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值