动手玩protocol buffers
我记得第一次编译thrift文件是运行一个脚本,可能是处于好奇心吧,看了看脚本里的内容,大概只有一行,但是是没有工程意识去认真研究。所以对rpc的认知,还是停留在纸面上。这种滞后持续了一年多,直到现在。所以是否动手有着截然不同的结果。
最近看了些protocol buffer的文章,要是以前定要跳过这些繁琐的细节,因为这是黑盒的。而现在我花时间去看看这个细节,更愿意动手来个quick start。
首先要安装,这个步骤我就费了好些周折,一开始安装的是最新版本,后来退回到了一个比较低的版本,不过这没有任何影响。
sudo apt-get install autoconf automake libtool 安装依赖,不可或缺
wget https://github.com/google/protobuf/archive/v2.6.1.zip
unzip v2.6.1.zip -d ./
cd protobuf-2.6.1
./autogen.sh
最后一个命令发生异常,原因是什么?怎么解决?
修改
curl http://googletest.googlecode.com/files/gtest-1.5.0.tar.bz2 | tar jx
mv gtest-1.5.0 gtest
为
wget https://github.com/google/googletest/archive/release-1.5.0.tar.gz
tar xzvf release-1.5.0.tar.gz
mv googletest-release-1.5.0 gtest
./configure
make
make check (check结果可能会有错误,但不用管她,因为暂时那些功能用不到)
make install
protoc --version
执行最后一个命令报错。原因是什么?怎么解决?
protoc: error while loading shared libraries: libprotoc.so.8: cannot open shared
错误原因:
protobuf的默认安装路径是/usr/local/lib,而/usr/local/lib 不在Ubuntu体系默认的 LD_LIBRARY_PATH 里,所以就找不到该lib
解决方法:
1). 创建文件 /etc/ld.so.conf.d/libprotobuf.conf,在该文件中输入如下内容:
/usr/local/lib
2). 执行命令
sudo ldconfig
安装好了,然后使用:protoc --java_out=. xxx.proto,会生成Xxx.java
把这个java文件拷贝到工程里,发现报错,因为缺少依赖。
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.6.1</version>
</dependency>
一定要注意版本,不然可能报错。
数据格式文件:rpc.proto
message Person {
required int32 id = 1;
required string name = 2;
optional string email = 3;
repeated string friends = 4;
}
测试代码:
// 按照定义的数据结构,创建一个Person
Rpc.Person.Builder personBuilder = Rpc.Person.newBuilder();
personBuilder.setId(1);
personBuilder.setName("叉叉哥");
personBuilder.setEmail("xxg@163.com");
personBuilder.addFriends("Friend A");
personBuilder.addFriends("Friend B");
Rpc.Person xxg = personBuilder.build();
// 将数据写到输出流,如网络输出流,这里就用ByteArrayOutputStream来代替
ByteArrayOutputStream output = new ByteArrayOutputStream();
xxg.writeTo(output);
// -------------- 分割线:上面是发送方,将数据序列化后发送 ---------------
byte[] byteArray = output.toByteArray();
// -------------- 分割线:下面是接收方,将数据接收后反序列化 ---------------
// 接收到流并读取,如网络输入流,这里用ByteArrayInputStream来代替
ByteArrayInputStream input = new ByteArrayInputStream(byteArray);
// 反序列化
Rpc.Person xxg2 = Rpc.Person.parseFrom(input);
System.out.println("ID:" + xxg2.getId());
System.out.println("name:" + xxg2.getName());
System.out.println("email:" + xxg2.getEmail());
System.out.println("friend:");
List<String> friends = xxg2.getFriendsList();
for(String friend : friends) {
System.out.println(friend);
}