最近终于有部分时间继续开发爬虫,主要的任务是客户端和服务器端分离,这就涉及到远程调用的问题,所以研究了RPC,主要对象是Hessian、JMI、Dubbo、Thrift。进而想用几篇博文分享一下几种远程调用协议的一些东西,以后再接着聊爬虫。有兴趣可以访问我的爬虫项目:https://gitee.com/coliza/MongooCrawler
经过研究最终选择了自定义协议的方式完成RPC协议,以下是部分协议代码:
public class CrawlerTransferProtocol<T> {
private int type;
private Class<T> cls;
private T content;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public Class<T> getCls() {
return cls;
}
public void setCls(Class<T> cls) {
this.cls = cls;
}
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
public byte toTypeByte() throws Exception {
switch (type) {
case 0:
return 0x0;
case 1:
return 0x1;
case 2:
return 0x2;
case 3:
return 0x3;
default:
throw new Exception("协议解析错误");
}
}
public int getContentLen() {
return JSONObject.toJSONString(content).getBytes().length;
}
public byte[] toContentBytes() {
return JSONObject.toJSONString(content).getBytes();
}
}
type是类型,爬虫需要传输的数据分为三类,分别是命令、URL、网页文本;cls是发起端传输的具体类型,主要用于序列化和反序列化,这里的序列化和反序列化协议选择使用json协议;content代表需要传输的信息对象,根据cls和content就能在被调用端反序列化生成被调用对象。
客户端发起RPC调用的过程是这样的:
Dubbo、Thrift的rpc大同小异,各自选择的编码方式不一样,为了提高性能还会对传输的数据进行压缩处理,尤其是Thrift这样的跨语言RPC需要兼容多种语言,字节码编码需要充分考虑各语言的细节差异并屏蔽掉这些差异,往往是以牺牲性能为代价的。爬虫的应用领域比较特殊,不需要兼顾这些方面,以上相当于实现了一个简化版的RPC协议。有兴趣的读者可以留下评论。