bad-param无法微信分享 bad param到朋友圈,该怎么解决啊?

二次元同好交流新大陆
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
软件工程师
电力系统装置软件、办公管理软件、财务软件、GPS电子地图软件开发,短信平台软件。
流媒体制作:图像、音频、视频
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(1942)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_080070',
blogTitle:'怎样在C++Builder中创建使用DLL',
blogAbstract:'\n  自从C++Builder从去年浪漫情人节上市以来,吸引了大量的Delphi、VC、Vb的程序员到它的怀抱,大量的C、C++程序员感叹道:总算有了C的可视化开发工具,对我也是一样,从BC、Delphi到C++Builder。&\n  动态链接库(DLL)是Windows编程常遇到的编程方法,下面我就介绍一下在BCB&(C++Builder下简称BCB)&中如何创建使用DLL和一些技巧。&\n  一、创建:&\n  使用BCB&File|NEW建立一个新的DLL工程,并保存好文件BCB,生成一个DLL的程序框架。&\n  1.DllEntryPoint函数为一个入口方法,如果使用者在DLL被系统初始化或者注销时被调用,用来写入对DLL',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:3,
permalink:'blog/static/',
commentCount:1,
mainCommentCount:1,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'软件工程师\n电力系统装置软件、办公管理软件、财务软件、GPS电子地图软件开发,短信平台软件。\n流媒体制作:图像、音频、视频',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}QQ空间分享到朋友圈是出现bad param_百度知道
QQ空间分享到朋友圈是出现bad param
QQ空间分享到朋友圈是出现bad param
苹果5s手机空间说说分享到朋友圈失败、出现这样bad-param的是什么原因.试试看哦.、我认为认真上网搜索一下大约协助你解决问题吧
来自团队:
其他类似问题
为您推荐:
param的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁二次元同好交流新大陆
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
北冥有鱼,其名为鲲,鲲之大不知其几千里也,
化而为鸟,其名为鹏,鹏之背不知其几千里也,
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
message&Rpc&{&&&&&&repeated&Request&request&=&1;&&&&&&repeated&Response&response&=&2;&&}&&message&Request&{&&&&&&required&string&method&=&1;?&&?&&?&&//&name&of&a&method_descriptor&&&&&&optional&bytes&serialized_request&=&2;?&&//&pb2-encoded&message&&&&&&optional&uint32&id&=&3;&&}&&message&Error&{&&&&&&required&sint32&code&=&1;&&&&&&optional&string&text&=&2;&&}&&message&Response&{&&&&&&optional&bytes&serialized_response&=&1;?&&//&pb2-encoded&message&&&&&&optional&Error&error&=&2;&&&&&&required&uint32&id&=&3;&&}&&
不知道大家有没有注意到 message Rpc 里的两个字段都是 repeated 的!我设想,这个设计的有以下特点:同一个数据包里可以有多个
request 或 response,甚至是返回 response 的同时丢若干 request 回去给另一端,相当地灵活。
再来看 Request.method,注释是 name of a method_descriptor,实际上是
service_descriptor 的 name 加上 method_descriptor 的 name
来的,不过如果你不看代码无法知道这一点(代码见:/p/protobuf-rpc/source
/browse/trunk/python/protobufrpc/synchronous.py#60);这样做的好处是你可以在同一个端口
host 若干个 service。但是这跟不上变化的注释和隐晦的字段名,真的让人很纠结,破代码的典范。
id 字段居然是 optional 的,让我有点迷惑,特别是看到 Response.id 居然是 required,额……天哪,Request
不是自带 id 的话拿什么东西来设置 Response 哦!事实上,从代码来看,Request.id 都是有设置的,读的时候也是当这个字段是
required 来处理。
Error 的设计中规中矩,不过 code 就没有先用 enum 包装一下,预设几种常见错误,有点过于自由化了。
最后,因为看到 Request.serialized_request 和 Response.serialized_response 都是
optional,我惊了一下,以为 protobuf 的 RPC
可以没参数和返回值的,但又想起从来没见文档提到过。最后还是小马过河,自己写了一个没有参数的 RPC 去编译,protoc
老实不客气地丢出来一句“Expected type name.”,确认了 RPC
都需要参数和返回值。所以这个Request.serialized_request 的 optional 应该改用 required;而
Response.serialized_response 则可以是 optional,因为当 RPC 执行错误的时候,无法返回 Response
实例,只能返回 Error 实例,所以需要 optional 来满足这个灵活性。作者这货真不严谨。
多看了三五个 rpc 实现之后,这个事儿就变得很有趣了,今儿来看 fepss-rpc 和 casocklib,分别基于 java 和 C++ 开发。
它的简介是Protocol Buffers RPC Server Implemention based on Mina(2.0.0-RC1) and Protobuf(2.1.0),基本的包格式见:
,全文如下:
[c-sharp] package&com.fepss.rpc.&&option&java_package&=&"com.fepss.rpc.client";&&option&java_outer_classname&=&"RpcProtobuf";&&option&optimize_for&=&SPEED;&&&&//&Possible&error&reasons&&enum&ErrorReason&{&&&&&&BAD_REQUEST_DATA&=&0;&&&&&&BAD_REQUEST_PROTO&=&1;&&&&&&SERVICE_NOT_FOUND&=&2;&&&&&&METHOD_NOT_FOUND&=&3;&&&&&&RPC_ERROR&=&4;&&&&&&RPC_FAILED&=&5;&&&&&&CLIENT_FAILED=6;&&&&}&&message&Request&{&&&&//&RPC&service&full&name&&&&required&string&service_name&=&1;&&&&&&&//&RPC&method&name&&&&required&string&method_name&=&2;&&&&&&&//&RPC&request&proto&&&&required&bytes&request_proto&=&3;&&}&&message&Response&{&&&&//&RPC&response&proto&&&&optional&bytes&response_proto&=&1;&&&&&&&//&Eror,&if&any&&&&optional&string&error&=&2;&&&&&&&//&Was&callback&invoked&&&&optional&bool&callback&=&3&[default&=&false];&&&&&&&&&&//&Error&Reason&&&&optional&ErrorReason&error_reason&=&4;&&}&&
可以看到 ErrorReason 定义了几个常见的错误:比如没有 Service,或有 Service 却没有相应的 method
等等,不过我对 BAD_REQUEST_DATA、BAD_REQUEST_PROTO、CLIENT_FAILED
表示不淡定,原因是对于前两者,我推崇发现非法协议就断开连接甚至采取更严厉的手段,而后者,客户端都出问题了,那 response 还能发送过去吗?
这个 Request 的设计比 protobuf-rpc 要好得多,因为它把 service_name 和 method_name
作为两个字段,非常明晰。但是它采用了无 id 设计,所以没有办法实现 Parallel Pipelining,肯定并发性能很差。关于
pp,我借用 msgpack-rpc 的一张图来说明一下:
而 Response 类的设计,我比较不明白 callback 的意图,还请读者中的行家赐教一二,多谢先。这里采用了 ErrorReason 和
error 分为两个字段的设计,我个人觉得有会让人有点小困惑,还不如 protobuf-rpc 的 Error 设计,通过 optional
实现 union。
看完一个 python 的 rpc,一个 java 的 rpc,终于来了一个 C++ 的,先看它的简介:An asynchronous communication library for C++,而它基本包格式见:
[c-sharp] package&casock.rpc.protobuf.&&enum&ResponseType&{&&&&RESPONSE_TYPE_OK&=&1;&&&&RESPONSE_TYPE_ERROR&=&2;&&};&&message&RpcRequest&{&&&&required&uint32&id&=&1;&&&&required&string&operation&=&2;&&&&optional&bytes&request&=&3;&&}&&message&RpcResponse&{&&&&required&uint32&id&=&1;&&&&required&ResponseType&type&=&2;&&&&optional&bytes&response&=&3;&&}&&
代码很短,采用了相当轻量级的设计。首先旗帜鲜明地声明了响应包的种类:成功以及失败,对于失败,并没有细分。RpcRequest.id 使用 32
位无符号整型,跟 protobuf-rpc 一样,不过这里的 operation 却跟后者的 method 不一样,operation
是货真价实的 MethodDescriptor.name,从代码(
)可以证实。因为每一个 RpcRequest.operation 都不带 service name,所以使用 Casocklib 是无法将多个 service host 到同一个端口的。
RpcResponse 因为带了一个 ResponseType,所以可以知道 method 到底有没有执行成功,同理 response 就设计成 optional 了,因为执行错误就不需要返回 response 了呀。
===========
未完待续,明天讲一个重量级一点的,设计独特的,基于 c++ 的 rpc 实现。protobuf-remote
嘎~再来一枚 C++ 系的 RPC,它的简介是 RPC implementation for C# and C++ using Protocol Buffers,比之前的几个 rpc 实现都要复杂。基本格式见:
,全文如下:
[c-sharp] package&ProtoBufR&&message&RpcMessage&{&&&&required&int32&id&=&1;&&&&optional&Call&call_message&=&2;&&&&optional&Result&result_message&=&3;&&&&message&Call&{&&&&&&required&string&service&=&1;&&&&&&required&string&method&=&2;&&&&&&&&&&repeated&Parameter&parameters&=&3;&&&&&&&&&&required&bool&expects_result&=&4;&&&&}&&&&message&Result&{&&&&&&optional&bool&is_failed&=&1;&&&&&&&&&&optional&string&error_message&=&2;&&&&&&optional&Parameter&call_result&=&3;&&&&}&&&&message&Parameter&{&&&&&&&&&&optional&bytes&proto_param&=&1;&&&&&&optional&string&string_param&=&2;&&&&&&&&&&optional&sint32&int_param&=&3;&&&&&&&&&&optional&uint32&uint_param&=&4;&&&&&&&&&&optional&sint64&int64_param&=&5;&&&&&&&&&&optional&uint64&uint64_param&=&6;&&&&&&&&&&optional&bool&bool_param&=&7;&&&&&&&&&&optional&float&float_param&=&8;&&&&&&&&&&optional&double&double_param&=&9;&&&&&&&&&&optional&bool&is_null&=&10;&&&&}&&}&&
只有一个大定义:message RpcMessage,它即是 request 又是 response,这一点跟之前的
protobuf-rpc 的 Rpc 相同;但不同的是它把 id 从 call/result(对应常用的
request/response)中抽取出来作为 RpcMessage
的共有属性,不过我没看到它的做法的时候,还真没想过要抽取出来,看来我重构能力有待加强。
从 Call 来看,采用了 service 和 method 分开两个字段的设计,所以 multi-service
是没有问题的。repeated Parameter parameters 让我有点困惑,因为之前所看的设计,应该都是使用 bytes
存储序列化好的 message 对象,那么这个 parameters
是否有独到之处,有的话又是什么呢?抱着这样的疑惑,我翻开了它的代码(额,测试代码,因为简单好懂,见:
[c-sharp] TEST_F(RpcClientTest,&Call)&&{&&&&&&&&&&EXPECT_CALL(m_controller,&Send(AllOf(Truly(IsCallMessageCorrect),&&&&&&&&&&&&&&&&&&Property(&RpcMessage::call_message,&Property(&RpcMessage::Call::expects_result,&Eq(true))))))&&&&&&&&&&&&&&&&&&.WillOnce(Invoke(this,&&RpcClientTest::SendResult));&&&&&&&&&&RpcMessage&&&&&&&&&&&MutableParameterList&parameters(&message);&&&&&&&&&&parameters.Add().SetInt(42);&&&&&&&&&&PendingCall*&call&=&m_client-&Call("ServiceName",&"MethodName",&parameters);&&&&&&&&&&call-&Wait();&&&&&&&&&&EXPECT_EQ(43,&call-&GetResult()-&GetInt());&&&&&&&&&&m_client-&ReleaseCall(call);&&}&&
可以看到声明了一个 RpcMessage 变量,然后用它实例化了一个 MutableParameterList(这个
MutablePararmeterList 可以看作是 Call.parameters 的适配器),然后往里加入了一个整型参数 42,然后再调用
Call 方法把请求发送到服务器端。至此我们可以明白 parameters 的作用是让我们声明 rpc
的时候,不再需要详细定义相应的参数和返回值类型了,统一写成:
[c-sharp] rpc&XXXX(RpcMessage)returns(RpcMessage);&&
即可,唯一需要变化的是用真正的方法名替换掉 XXXX。而 repeated Parameter parameters 中 repeated
的作用是为了传入复合参数,比如按常规传入 protobuf 官方示例中的 message Person 参数的话,可能在这里是这样的:
[c-sharp] parameters.Add().SetString(name);&&parameters.Add().SetInt(id);&&parameters.Add().SetString(email);&&
不过如果有定义 message Person 的话,也可以这样:
[c-sharp] parameters.Add().SetProto(person);&&
可见各种方案都有利弊,获得了 rpc 声明的简洁,就需要牺牲代码的简洁为代价。虽然说作者的思路的确是如同天马行空般开阔,但如果是我的话,我不会采用这种方案,换作你呢,又会如何?
Call.expects_result 字段是告诉服务器端要不要把结果(包括是否出错)返回给客户端,很好理解。不过 Result.call_result 是 optional,而不是 repeated,让我觉得怪怪地,难道只准多个参数,不许多个返回值?protobuf-rpc-pro
不知道你还记不记得 protobuf-rpc,这货在后面加了个 pro,就真的重量级了许多。照例先看看简介:A java
ProtocolBuffers RPC implementation featuring bidirectional
calls,特点是双向调用,跟之前的看的 rpc 都不一样。姑且按下不表,单来看看基本格式文件,
,全文如下:
[c-sharp] //&&//&TcpClient-&TcpServer&:&PullRequest&&//&TcpClient-&TcpServer&:&PushRequest&&//&TcpServer-&TcpClient&:&Chunk&&//&TcpClient-&TcpServer&:&CloseNotification&(&for&closing&pulls&before&transfer&end.&)&&//&TcpServer-&TcpClient&:&CloseNotification&(&for&closing&pushes&before&transfer&end.&)&&//&&option&java_package&=&"com.googlecode.protobuf.pro.stream.wire";&&option&java_outer_classname&=&"StreamProtocol";&&//&This&is&default,&but&it's&nice&to&be&explicit&&option&optimize_for&=&SPEED;&&message&PullRequest&{&&&&&&required&int32&correlationId&=&1;&&&&&&required&bytes&requestProto&=&2;&&}&&message&PushRequest&{&&&&&&required&int32&correlationId&=&1;&&&&&&required&bytes&requestProto&=&2;&&}&&message&CloseNotification&{&&&&&&required&int32&correlationId&=&1;&&}&&message&Parameter&{&&&&&&&&&&required&string&name&=&1;&&&&&&&&&&required&string&value=&2;&&}&&message&Chunk&{&&&&&&required&int32&correlationId&=&1;&//&unique&for&each&push/pull&per&channel&&&&&&required&ChunkTypeCode&chunkType&=&2;&&&&&&required&int32&seqNo&=&3;&//&incremented&for&each&sent&chunk&&&&&&repeated&Parameter&parameter&=&4;&&&&&&optional&bytes&payload&=&5;&&}&&enum&ChunkTypeCode&{&&&&START&=&0;&&&&MIDDLE&=&1;&&&&END&=&2;&&}&&message&WirePayload&{&&&&&&&&&&optional&Chunk&chunk&=&1;&&&&&&&&&&optional&PullRequest&pull&=&2;&&&&&&&&&&optional&PushRequest&push&=&3;&&&&&&&&&&optional&CloseNotification&close&=&4;&&}&&
哇,好长好长,一定是场硬仗。Protobuf-rpc-pro 的特点就是双向调用,所以有 pull 和 push 两种 request
message,让人纠结的是,其实他们是一样的,简单地采用 32 位 ID 加序列化后的 message 方案。响应包叫做
Chunk,独特的地方是一个响应包,可以分在若干个 Chunk 中发送到另一端,这样的话如果返回的结果很大,也算是有内置的解决方案了。带了一个
pro 的东西,就是比较重量级啊。这个特性是通过 chunkType 和 seqNo 两个字段共同来完成的,chunkType
用以标识起始点,而 seqNo 用来组织顺序。repeated Parameter parameter
的作用是传递一些扩展的参数,这些参数可能在处理 payload 的时候用得着,而这个 payload 是序列化的
message,它才是调用返回的结果(或结果的一部分)。
最后来看一下 WirePayload,现在来看,这货就简单了,跟 protobuf-rpc 中的 message Rpc 或 protobuf-remote 中的 message RpcMessage 是一样的封装类,见得多了也就没什么好说。
看来带 pro 的设计的确是考虑得比较周全,刚才还有一个 message CloseNotification 一直压着没谈,现在来说一下:它用来告知另一端自己马上就要关闭服务了。关于这一点,我觉得利用 TCP 本身的是半关闭特性就够了,没有必要做这个。
server1 出自国人之手,是一个利用了 Boost 的 a c++ network server/client framework,它的作者 xiliu tang 是我的前同事。server1 的代码还是非常简明的,先来看一下基础格式:
,全文如下:
[c-sharp] package&ProtobufLineF&&message&MetaData&{&&&&enum&Type&{&&&&&&REQUEST&=&1;&&&&&&RESPONSE&=&2;&&&&};&&&&required&Type&type&=&1;&&&&required&uint64&identify&=&2;&&&&//&the&request&should&bring&the&response&identify.&&&&optional&uint64&response_identify&=&3;&&&&required&bytes&content&=&4;&&};&&
很简单,只有一个 message MetaData?对的。感觉上跟 protobuf-rpc 差不多,两个不同:一是 MetaData 带了一个
Type,用来标明它是请求还是响应;还有一个是 MetaData 使用了无符号 64 位整型作为 ID。使用 type 字段我个人感觉比
repeated/optional 的方式比起来有点没有充分利用到 protobuf 特性的感觉,不过相当地清晰明了。还有就是
response_identify 我专门在 GTalk
上问过作者,他说记不起为什么要加这个字段了……囧。我的看法是这个字段是不必要的。嗯,这个设计真的很简洁,不过,我不喜欢 Meta 这个命名。快刀斩乱麻,祭上最后两个 rpc 分析,再整上我自己的设计,这个系列就完结了。
protobuf-socket-rpc
好,废话不多说,看看这个 protobuf-socket-rpc,简介是 Java and Python protobuf rpc
implementation using tcp/ip sockets,听说支持 java 的服务器和 python
的客户端,有点怪怪地哈?基本格式见:
,引用全文如下:
[c-sharp] package&protobuf.&&option&java_package&=&"com.googlecode.protobuf.socketrpc";&&option&java_outer_classname&=&"SocketRpcProtos";&&message&Request&{&&&&//&RPC&service&full&name&&&&required&string&service_name&=&1;&&&&&&&//&RPC&method&name&&&&required&string&method_name&=&2;&&&&&&&//&RPC&request&proto&&&&required&bytes&request_proto&=&3;&&}&&message&Response&{&&&&//&RPC&response&proto&&&&optional&bytes&response_proto&=&1;&&&&&&&//&Error,&if&any&&&&optional&string&error&=&2;&&&&&&&//&Was&callback&invoked&&&&optional&bool&callback&=&3&[default&=&false];&&&&&&&//&Error&Reason&&&&optional&ErrorReason&error_reason&=&4;&&}&&//&Possible&error&reasons&&//&The&server-side&errors&are&returned&in&the&response&from&the&server.&&//&The&client-side&errors&are&returned&by&the&client-side&code&when&it&doesn't&&//&have&a&response&from&the&server.&&enum&ErrorReason&{&&&&//&Server-side&errors&&&&BAD_REQUEST_DATA&=&0;&//&Server&received&bad&request&data&&&&BAD_REQUEST_PROTO&=&1;&//&Server&received&bad&request&proto&&&&SERVICE_NOT_FOUND&=&2;&//&Service&not&found&on&server&&&&METHOD_NOT_FOUND&=&3;&//&Method&not&found&on&server&&&&RPC_ERROR&=&4;&//&Rpc&threw&exception&on&server&&&&RPC_FAILED&=&5;&//&Rpc&failed&on&server&&&&&&&//&Client-side&errors&(these&are&returned&by&the&client-side&code)&&&&INVALID_REQUEST_PROTO&=&6;&//&Rpc&was&called&with&invalid&request&proto&&&&BAD_RESPONSE_PROTO&=&7;&//&Server&returned&a&bad&response&proto&&&&UNKNOWN_HOST&=&8;&//&Could&not&find&supplied&host&&&&IO_ERROR&=&9;&//&I/O&error&while&communicating&with&server&&}&&
很眼熟啊,是的,跟之前看过的 fepss-rpc
几乎一样,除了这里定义了更多的错误类型,连注释都几乎一模一样啊,不知道谁抄谁的。所以没啥好说的了,唯一可以唠叨一下的是它跟 fepss-rpc
都采用无 ID 的设计,所以不能 parallel pipelining,细节见(
txprotobuf
以 Python 始,再以 Python 终,最后一个是 protocol buffers
(/p/protobuf/) RPC implemented using python
twisted framework.,基于 twisted 的 rpc,虽然我不喜欢 twisted,但不影响我看 txprotobuf
哈。它的基本格式见:
,照例全文引过来:
[c-sharp] //&Copyright&(c)&2008&Johan&Euphrosine&&//&See&LICENSE&for&details.&&message&Call&{&&&&required&uint32&token&=&1;&&&&required&string&method&=&2;&&&&required&bytes&request&=&3;&&}&&message&Result&{&&&&required&uint32&token&=&1;&&&&required&bytes&response&=&2;&&}&&message&Box&{&&&&optional&bytes&call&=&1;&&&&optional&bytes&result&=&2;&&}&&
简洁,跟 casocklib 相似的设计。唯一能够说一下的就是只有 method 字段而没有 service 字段所以没有办法做到 multi-service。另外,Box 这个命名我很喜欢。
我自己的设计
本来想单独作为一篇的,后来发现前两个实在没啥好说啊,干脆就整合在一起得了。好,上代码:
[c-sharp] enum&PackageType&{&&&&&&HEARTBEAT&=&0;&&&&&&ERROR&=&1;&&&&&&REQUEST&=&2;&&&&&&RESPONSE&=&3;&&};&&message&Heartbeat&{&&};&&message&Error&{&&&&&&required&string&info&=&1;&&};&&message&Request&{&&&&&&required&string&service&=&1;&&&&&&required&string&method&=&2;&&&&&&optional&bytes&request&=&3;&&};&&message&Response&{&&&&&&optional&bytes&response&=&1;&&};&&message&Package&{&&&&&&required&PackageType&type&=&1;&&&&&&required&uint32&identify&=&2;&&&&&&required&bytes&serialized&=&3;&&};&&message&Placeholder&{&&};&&
首先是学习 server1 定义了几种数据包的类型,不过我扩展了一下,加了心跳和错误这两种包。心跳在这里就是简单的一个空包,只是激活一下 TCP 连接,以免超时断开。如果要复杂一点的,可以参考陈硕《分布式系统的工程化开发方法》 p.51 心跳协议的设计(
message Error 很简单,只有一个 info
字段。之前也在想要不要加个数字枚举来让调用端了解一下基本出了啥错,后来我想还是不要了。主要是出错了对于调用端来说没有什么挽救手段啊,只能是往日志
里写一句,然后该干啥干啥去,既然如此,又何必多此一举呢,直接把错误的文本从服务器端传过来就好了。
message Request 带了 service 和 method 字段,为的是明晰地表达咱支持 multi-service。而的
request 字段是 optional 的,为的是支持“空”参数调用 RPC。Message Response 的 optional
bytes response 也是类似,为了支持“空”返回值。因为 protobuf 的 rpc 声明不支持 rpc
XXX()returns() 这样的无参数无返回值的声明,所以我又在后面声明了一个 message Placeholder,这样 rpc
声明就可以写成 rpc XXX(Placeholder)returns(Placeholder)。调用代码时,可以直接写成
proxy.service.XXX() 这样子,由我们自己的 Proxy/Channel 实现去处理好这个占位参数和返回值就行了。
最后,整个连接上传输的数据包就只有一种:message Package,不论是 Heartbeat、Error、Rquest 或 Response,最后都会序列化到 Package.serialized 里去。
对比这么多实现,我的这个版本既没有像 protobuf-remote 般自由开放的调用参数机制,也没有 protobuf-rpc-pro 可以返回超大块数据的内置方案。不过我还是比较满意,太自由和太重量的方案不符合我的技术观。
我打算基于 gevent 实现这个 rpc。
===== 完 ======
阅读(158)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'以小见大——那些基于 protobuf 的五花八门的 RPC(1)',
blogAbstract:'http://blog.csdn.net/gzlaiyonghao/article/details/6313243赖勇浩(
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}}

我要回帖

更多关于 ct bad param 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信