basho的riak是应用erlang编写的类dynamo kv存储,其实现贯彻了松耦合、模块化的特征,各类核心组件均可替换:
分布式组件riak_core可以用于构建其它的分布式应用,https://github.com/rzezeski/try-try-try是一个利用riak_core构建分布式应用的教学实例;
存储组件riak_kv和riak_serach是基于riak_core实现的分布式kv存储;
webmachine是基于mochiweb封装的通用REST框架;
protobuffs是erlang版的protocol buffers,最初位于https://github.com/ngerakines/erlang_protobuffs;
bitcask是riak的默认存储引擎,通过nif实现了文件读写方法,之前本博客有提到过;
eleveldb通过nif实现了对leveldb的封装;
还有很多使用的组件,项目中能用的尽量拿来用吧。
此次将分析protobuffs这个组件,它本身完成的功能倒是容易描述清楚:“google的protocol buffers提供了跨语言的数据交换方法,支持c++/java/python,但是不支持erlang,basho帮我们实现了这个愿望,根据我们的proto文件描述的数据结构,产生对应的编解码erlang头文件和源文件”,但是看到它的实现后,我突然发现,erlang世界还有很多未知的地方需要探索。
言归正传,protocol buffers的资料请各位读者自行google,这里直接开始分析protobuffs的实现,版本为0.6.0。
先定义一个proto文件rds_la.proto如下:
package rds_la;
message la_record {
required string name = 1;
required int32 timestamp = 2;
required string query = 3;
required int32 query_time = 4;
required int32 response_time = 5;
}
这是前日所开发的项目中用于传输一条日志记录的结构,其中name和query都是字符串,name最多64字节,而query最多1024字节。
利用protobuf附带的工具protoc-erl编译rds_la.proto得到rds_la_pb.hrl和rds_la_pb.erl。
rds_la_pb.hrl的内容主要为:
-record(la_record, {
name = erlang:error({required, name}),
timestamp = erlang:error({required, timestamp}),
pb_query = erlang:error({required, pb_query}),
query_time = erlang:error({required, query_time}),
response_time = erlang:error({required, response_time})
}).
为rds_la生成了一个record,名为la_record,由于message la_record的所有域均为required,可以看到,protobuffs贴心的为record la_record每个域设置了默认值erlang:error({required, name}),而如果为optional,则不设置默认值,如果为repeated,也不会设置默认值,但是如果有值,该域将会是一个列表list。
rds_la_pb.erl的主要内容为:
-file("src/rds_la_pb.erl", 1).
-module(rds_la_pb).
-export([encode_la_record/1, decode_la_record/1]).
-export([encode/1, decode/2, iolist/2]).
-record(la_record,
{name, timestamp, pb_query, query_time, response_time}).
encode_la_record(Record)
when is_record(Record, la_record) ->
encode(la_record, Record).
encode(la_record, Record) ->
iolist_to_binary(iolist(la_record, Record)).
iolist(la_record, Record) ->
[pack(1, required,
with_default(Record#la_record.name, none), string, []),
pack(2, required,
with_default(Record#la_record.timestamp, none), int32,
[]),
pack(3, required,
with_default(Record#la_record.pb_query, none), string,
[]),
pack(4, required,
with_default(Record#la_record.query_time, none), int32,
[]),
pack(5, required,
with_default(Record#la_record.response_time, none),
int32, [])].
...
enum_to_int(pikachu, value) -> 1.
int_to_enum(_, Val) -> Val.
decode_la_record(Bytes) when is_binary(Bytes) ->
decode(la_record, Bytes).
decode(enummsg_values, 1) -> value1;
decode(la_record, Bytes) when is_binary(Bytes) ->
Types = [{5, response_time, int32, []},
{4, query_time, int32, []}, {3, pb_query, string, []},
{2, timestamp, int32, []}, {1, name, string, []}],
Decoded = decode(Bytes, Types, []),
to_record(la_record, Decoded).
...
to_record(la_record, DecodedTuples) ->
lists:foldl(fun ({_FNum, Name, Val}, Record) ->
set_record_field(record_info(fields, la_record), Record,
Name, Val)
end,
#la_record{}, DecodedTuples).
...
以上便是生成的文件的内容,标注红色的地方需要读者注意,它们便是protobuffs_compile所生成的内容。
其中encode_la_record/1和decode_la_record/1是la_record的编解码函数;io_list/2则记录了编码时需要对record la_record的每个field需要做的动作;enum_to_int/2和int_to_enum/2用于enum值生成;decode/2记录了解码时生成的域应该放置在record la_record的哪个域;to_record/2记录了构造record la_record的过程。
不过这里有个很萌的pikachu是干嘛的?
未完待续...
分享到:
相关推荐
这个是在erlang项目中使用google protobuf例子,配套文章地址http://blog.csdn.net/mycwq/article/details/21864191
enif_protobuf:使用enif(Erlang nif)的Google Protobuf实现
这个erlang版本的protobuf,做了改进,效率有很大提升,配套文章地址http://blog.csdn.net/mycwq/article/details/42122439
read/1与Erlang源文件(即带有.erl后缀的文件)和Erlang二进制文件(即带有.beam后缀的文件)一起使用。 下面的行将从Erlang的内部lists模块中读取表单。 forms : read ( lists ). 同样,以下行将从开发人员提供...
这个是在erlang protobuf改进版本的代码,效率有很大提升,配套文章地址http://blog.csdn.net/mycwq/article/details/42122439
听说google proto buffer(以下简称protobuf)已经很久了,但是一直没有尝试使用它。其中一个原因是,项目组自己写了个打包和解包的工具,而且代码也简单,可以很方便的扩展到自动生成xml之类的配置文件,已经能很好...
Erlang并发编程,Erlang程序设计,Erlang中文手册。 学习erlang的好资料。 Erlang是一个结构化,动态类型编程语言,内建并行计算支持。最初是由爱立信专门为通信应用设计的,比如控制交换机或者变换协议等,因此...
erlang程序设计 erlang入门手册
erlang入门电子书 erlang编程 Introducing Erlang,作者Simon.St.Laurent
erlang 安装包
●外部接口-Erlang进程与外部世界之间的通讯使用和在Erlang进程之间相同的消息传送机制。 ●Fail-fast(中文译为速错),即尽可能快的暴露程序中的错误。 ●面向并发的编程(COP concurrency-oriented programming) ...
使用erlang语言实现连接ElasticSearch服务器的客户端代码
ErlangB和ErlangC计算工具(exe可执行文件+excel两个) ErlangB和ErlangC计算工具(exe可执行文件+excel两个)
rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统。它遵循Mozilla Public License开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器,Rabbit MQ 是建立在Erlang OTP平台上。
对同为函数式语言的Scala和Erlang进行了比较
Erlang及其应用Erlang及其应用Erlang及其应用
erlang位运算与二进制解析 erlang二进制高效编程 erlang异常处理详解 开发经验: 面对软件错误构建可靠的分布式系统 编写分布式的 Erlang 程序:陷阱和对策 硝烟中的Erlang 深入底层: erlang VM基于多核处理器的...
erlang otp25 win安装包
erlang25.0 windows版本
erlang22最新下载包 erlang22.1.tar.gz erlang22最新下载包 erlang22最新下载包