文章关键字 ‘Hessian’

基于apache mina 2.0.0 M4和google Protocol Buffers 2.0.3的java RPC实例(1.准备工作)

2009年01月10日,星期六

基于apache mina 2.0.0 M4和google Protocol Buffers 2.0.3的java RPC实例(1.准备工作)

1.最新的google Protocol Buffers 下载地址为:

http://protobuf.googlecode.com/files/protobuf-2.0.3.zip
http://protobuf.googlecode.com/files/protoc-2.0.3-win32.zip
来源:http://code.google.com/p/protobuf/downloads/list

2. 2.0.0-M4下载地址为:
http://apache.freelamp.com/mina/2.0.0-M4/mina-2.0.0-M4.zip
(或:http://www.eu.apache.org/dist/mina/2.0.0-M4/mina-2.0.0-M4.zip)

3.protobuf-rpc的代码:
通过svn取protobuf-rpc的代码到本地。源代码地址在:
http://protobuf-rpc.googlecode.com/svn/trunk/
来源:
http://code.google.com/p/protobuf-rpc/
不过这个例子太简单,并且没有java版本的。

4.建立目录D://protoc/javasrc,
运行命令:
protoc.exe  -I=”D:/Java/protoc/protobuf-2.0.3/src/google/protobuf” –java_out=”D:/Java/protoc/javasrc” D:/Java/protoc/protobuf-2.0.3/src/google/protobuf/descriptor.proto

很奇特,protoc.exe -–java_out=./ D:\Java\protoc\protobuf-2.0.0beta\src\google\protobuf\descriptor.proto 运行出错了。(参考:http://618119.com/archives/2008/07/08/100.html

5.复制D:\Java\protoc\javasrc\com\google\protobuf下的DescriptorProtos.java到
D:\Java\protoc\protobuf-2.0.3\java\src\main\java\com\google\protobuf。
建立java工程到E:\mywork\protobuf,将D:\Java\protoc\protobuf-2.0.3\java\src\main\java\下的文件复制到E:\mywork\protobuf\src。

(以下步骤其实是我绕的弯路)
6.E:\mywork\protobuf\src>svn checkout http://protobuf-rpc.googlecode.com/svn/trunk
/ protobuf--read-only
A    protobuf-rpc-read-only\protoc.sh
A    protobuf-rpc-read-only\protocol
A    protobuf-rpc-read-only\protocol\protobufrpc.proto
A    protobuf-rpc-read-only\LICENSE
A    protobuf-rpc-read-only\protobufrpc
A    protobuf-rpc-read-only\protobufrpc\common.py
A    protobuf-rpc-read-only\protobufrpc\tx.py
A    protobuf-rpc-read-only\protobufrpc\__init__.py
A    protobuf-rpc-read-only\setup.py
A    protobuf-rpc-read-only\setup.sh
A    protobuf-rpc-read-only\examples
A    protobuf-rpc-read-only\examples\test.proto
A    protobuf-rpc-read-only\examples\txproxy.py
A    protobuf-rpc-read-only\examples\txserver.py
取出版本 13。

7.运行命令:
D:\Java\protoc>protoc.exe  -I=”E:\mywork\protobuf\src\protobuf-rpc-read-only\protocol” –java_out=”D:/Java/protoc/javasrc” E:\mywork\protobuf\src\protobuf-rpc-read-only\protocol\protobufrpc.proto

8.将D:\Java\protoc\javasrc下的pbrpc目录复制到E:\mywork\protobuf\src

9将E:\mywork\protobuf\src\protobuf-rpc-read-only\examples下的test.proto改名为:TestRpc.proto
内容改为:

package test;

message EchoRequest {
required string text = 1;
}

message EchoResponse {
required string text = 1;
}

message PingRequest {
required int32 ping = 1;
}

message PingResponse {
required int32 pingRs = 1;
}

message MathBinaryOperationRequest {
required float first = 1;
required float second = 2;
}

message MathResponse {
required float result = 1;
}

service Test {
rpc Ping( PingRequest ) returns( PingResponse );
rpc Echo( EchoRequest ) returns( EchoResponse );
}

service Math {
rpc Add( MathBinaryOperationRequest ) returns( MathResponse );
rpc Multiply( MathBinaryOperationRequest ) returns( MathResponse );
}

10.再运行:
D:\Java\protoc>protoc.exe  -I=”E:\mywork\protobuf\src\protobuf-rpc-read-only\examples” –java_out=”D:/Java/protoc/javasrc” E:\mywork\protobuf\src\protobuf-rpc-read-only\examples\TestRpc.proto

否则因为包名和类名的冲突,会出现如下错误信息:
D:\Java\protoc>protoc.exe  -I=”E:\mywork\protobuf\src\protobuf-rpc-read-only\examples” –java_out=”D:/Java/protoc/javasrc” E:\mywork\protobuf\src\protobuf-rpc-read-only\examples\test.proto
–java_out: test.proto: Cannot generate Java output because the file’s outer class name, “Test”, matches the name of one of the types declared inside it.  Please either rename the type or use the java_outer_classname option to specify a different outer class name for the .proto file.

然后就可以编写这个例子相关接口的实现类了。

下面开始实际例子:.定义service的proto文件

先假设需求为实现一个用户查看并修改自己的个人信息的功能接口。

在D:\Java\protoc\javasrc建立qquserinfo.proto

内容如下:
[code]
package lizongbo.protobuf;
option java_package = "com.lizongbo.mobileqq";
option java_outer_classname = "QQUserInfoProtos";

option optimize_for = CODE_SIZE;// 也可以设置成 SPEED;

//用户信息定义
message QQUser {
required int32 qqNo = 1 [default = 9999];
required string nickNmae = 2 [default = "mobileq"];
required string signName = 3 [default = "手机QQ"];
required string postCode = 4 [default = "618119"];
required string address = 5 [default = "618119.com"];
}

//获取个人信息的请求
message GetUserInfoRequest {
required int32 qqNo = 1;
}
//获取个人信息的应答结果
message GetUserInfoResponse {
required int32 qqNo = 1;
required int32 result = 2;
optional QQUser userInfo = 3;
}

//更新个人信息的请求
message UpdateUserInfoRequest {
required int32 qqNo = 1;
required QQUser userInfo = 2;
}
//更新个人信息的应答结果
message UpdateUserInfoResponse {
required int32 qqNo = 1;
required int32 result = 2;
optional string message = 3;
}

//个人信息操作的service接口
service UserInfoService {

//获取个人信息
rpc getUserInfo( GetUserInfoRequest  ) returns( GetUserInfoResponse );
//与hessian不同,service里直接限制了不能有同名重载方法。
// 比如这样与下面的方法冲突 rpc updateUserInfo( GetUserInfoRequest ) returns( GetUserInfoResponse );
//出错信息为:qquserinfo.proto:45:9: "updateUserInfo" is already defined in "lizongbo.protobuf.UserInfoService".

//更新个人信息
rpc updateUserInfo( UpdateUserInfoRequest ) returns( UpdateUserInfoResponse );

}

//获取个人信息的请求
message QueryOplogRequest {
required int32 adminId = 1;//管理员id
required int32 qqNo = 2;
}
//获取个人信息的应答结果
message QueryOplogResponse {
//用户操作日志
message Oplog {
required int32 qqNo = 1;
required string opName = 2 [default = "get"];
required string opContent = 3 [default = ""];
}
required int32 qqNo = 1;
required int32 result = 2;
repeated Oplog oplogs=3;

}

//供管理员操作的service 接口
service OplogService {
rpc queryOplog(QueryOplogRequest ) returns(QueryOplogResponse);
}

[/code]

运行命令生成相关代码:
protoc.exe  -I=”D:\Java\protoc\javasrc” –java_out=”D:/Java/protoc/javasrc” D:\Java\protoc\javasrc\qquserinfo.proto
复制D:\Java\protoc\javasrc\com\lizongbo\QQUserInfoProtos.java到E:\mywork\protobuf\src\com\lizongbo\mobileqq。
协议定义的源代码就生成好了。

Tags: , , , ,

选择或设计实现远程RPC调用所需要考虑的n个方面

2008年08月27日,星期三

选择或设计实现远程RPC调用所需要考虑的n个方面

(前段时间记录的零散片段,却一直没时间仔细整理,仅记录在此,以做备忘。)
可参考协议(组件)为:
http,smtp,pop,ftp,dns,burlap,json,xml-,xmpp,smpp,rmi,soap,, , protocol buffers等等
需要考虑以下方面:

必备条件:
a.多语言支持
b.强大的序列化和反序列化(xml,text,pdu,text+stream)
c.多种传输模式

1.服务端所支持的编程语言。
,C,C++,C#,PHP等等

2.客户端支持的语言。
java,C,C++,JavaScript等

3.字节流转码。
支持GBK,UTF-8等。

4.支持的基础数据类型。
char,int,long,double,floadt,boolean,List,Map,Object(Struct)

5.同名重载方法区别

6.支持数据包的转发代理 (前端负载均衡)

7.自定义超时连接

8.数据包转换 (对象的序列化和反序列化)

9.数据类型扩展

10.类与接口实现的约束

11.是否支持负载限制 (比如超过100并发时,直接返回系统忙)

12.failover处理

13.事务控制

14.异步调用

15.数据包版本自动识别

16.TCP/UDP支持
(UDP 有1472字节限制。)

17.代码生成器(主要针对数据包的序列化)

18.与现有框架的整合难度(组件化程度)

19.大文件传输

21.数据包序列化效率

客户端连接池
应用范围

22.网络带宽约束(数据包是否支持压缩)

23.服务接口监控统计

数据包加密

SSL支持

是否需要握手消息(是需多次交互还是简单的请求应答模式)

调试抓包的方便性

是否支持双向调用(xmpp支持)

部署难易程度

参数配置难度

是否支持请求队列

请求应答的对应关系

协议可读性

支持客户端并发限制(比如同一ip每秒只能够调用10次)

断点续传和重发数据

URL设置

access.log配置与合并,自定义 logger(用于控制是否打印敏感信息)

过滤器拦截模式

接口代码可读性

常用端口选择

重启服务时的热切换

黏性会话支持(基于IP,或者基于sessionid)

安全端口

是否可以多端口

配置文件

是否能够方便获取真实客户端ip和端口
MDC支持
是否支持线程局部变量(类似webservice获取session,ICE的Current)

防雪崩(提供初始化预热加载)

Tags: , , ,

HessianServlet和HessianProxyFactory的配置参数

2008年07月27日,星期日

HessianServlet和HessianProxyFactory的配置参数

home-class,service-class,表示Service的实现类的类名

home-api,api-class,是Service的接口类名

object-class,不太了解
object-api,不太了解,

debug,调试开关,默认为false,需要设置为true的时候,值必须是”true”,区分大小写(不建议设置为true)

send-collection-type,设置SerializerFactory是否在序列化的数据里传递集合类的类型名,默认为true,需要设置为false的时候,
值必须是”false”,区分大小写(不建议设置为false)

其实 SerializerFactory还有个 _isAllowNonSerializable属性,控制是否接受对没有实现 .io.Serializable接口的对象,
通过setAllowNonSerializable来控制,
默认是不接受,为false,而HessianServlet却没提供这个参数的控制开关,因此如果要支持传输没有实现java.io.Serializable接口的对象,
则需要继承HessianServlet来加上相应控制,重载getSerializerFactory方法来设置参数或增加扩展的SerializerFactory,
而无法通过直接配置HessianServlet的初始化参数来实现。

先前提到的   3.1.5里hession2.0 有bug ,在hessian 3.1.6里依然存在,在hessian 3.2.0中将被修正.

参考: http://maillist.caucho.com/pipermail/hessian-interest/2008-July/000405.html

ServiceContext存放了线程局部变量request,
ServiceContext.getContextRequest()

HessianProxyFactory 设置的 _isOverloadEnabled 可支持同名重载方法。
不过不建议在接口中使用同名方法和变长参数。
_user和_password是设置 http basic认证的用户名和密码。
_isDebug,调试开关
_isHessian2Reply,_isHessian2Request,是否使用hessian 2.0协议发送请求。
_isChunkedPost,设置Chunked编码方式发送请求。

Tags: ,