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项目中使用protobuf例子”指的是在Erlang编程环境中使用Protocol Buffers(protobuf)这一数据序列化工具。protobuf是由Google开发的一种高效、跨语言的数据表示和序列化格式,它允许开发者定义...
`erl_protobuffs`为Erlang开发者提供了一种高效的protobuf实现,增强了Erlang系统与外部世界的数据交换能力。通过其优化的编码和解码过程,以及对Erlang特性的良好适应,它在处理大量数据时表现出色,是构建高性能、...
6. **集成到Erlang生态系统**:enif_protobuf使得Erlang系统能够无缝地与使用Protobuf的外部服务交互,如分布式系统中的数据交换。 在实际应用中,开发人员首先需要定义protobuf消息类型,然后使用Google提供的...
5. **编译工具链改进**:可能是对protobuf编译器的Erlang绑定进行了优化,使得生成的Erlang代码更加高效或者易于使用。 配套的文章地址(http://blog.csdn.net/mycwq/article/details/42122439)可能提供了更多关于...
read/1与Erlang源文件(即带有.erl后缀的文件)和Erlang二进制文件(即带有.beam后缀的文件)一起使用。 下面的行将从Erlang的内部lists模块中读取表单。 forms : read ( lists ). 同样,以下行将从开发人员提供...
Erlang Protobuffs是一个用于Erlang的协议缓冲区(Protocol Buffers)实现,它允许Erlang程序与使用Google Protobuf编译器生成的消息格式进行交互。Google Protobuf是一种高效的数据序列化协议,广泛应用于跨语言的...
听说google proto buffer(以下简称protobuf)已经很久了,但是一直没有尝试使用它。其中一个原因是,项目组自己写了个打包和解包的工具,而且代码也简单,可以很方便的扩展到自动生成xml之类的配置文件,已经能很好...
**Erlang程序设计与入门** Erlang是一种并发、函数式编程语言,主要用于构建分布式、高可用性、容错性强的系统。它的设计灵感来源于电信行业的需求,由瑞典爱立信公司于1986年开发。Erlang以其独特的并发模型、轻量...
它负责解释Erlang字节码,提供内存管理、垃圾回收和并发调度等功能。 ### 10. 语言特性 Erlang的语法简洁,支持模式匹配、函数式编程、列表处理和递归等特性。它的动态类型系统和强大的类型推断让代码更加灵活。 ...
RabbitMQ是一种广泛使用的开源消息代理和队列服务器,它基于Erlang编程语言构建。Erlang以其并发能力、容错性和分布式特性而闻名,是实现RabbitMQ的理想选择。正确地匹配RabbitMQ和Erlang的版本对于确保系统的稳定性...
标题中的"C#与Erlang的群通信"指的是在编程领域中,使用C#和Erlang两种不同的编程语言进行集群或分布式系统间的通信。这两种语言各有特点,C#是微软开发的面向对象的编程语言,常用于Windows平台的开发,而Erlang则...
在Erlang中,与MySQL对接的关键在于选择合适的驱动程序,文件名为"erlang-mysql-driver"很可能是指一个Erlang的MySQL驱动库。这样的驱动库允许Erlang应用程序通过标准的数据库接口与MySQL进行通信。在Erlang中,这种...
本项目提供了一个使用Erlang编写的聊天室服务器端代码以及Java编写的客户端代码,这为我们深入理解Erlang的并发特性和Java与Erlang的交互提供了实践案例。 一、Erlang聊天室服务器端 1. 并发处理:Erlang的轻量级...
### 并发需求下的Scala及Erlang语言的比较与使用 在当今的高并发、大数据处理场景下,选择合适的编程语言对于系统性能至关重要。在众多编程语言中,Scala和Erlang因其强大的并发处理能力和函数式编程特性而受到关注...
Erlang是一种面向并发的、函数式编程语言,主要用于构建高度可扩展的、容错性强的分布式系统。在IT行业中,Erlang因其强大的实时性和处理大量并发连接的能力而被广泛应用于电信、互联网基础设施和实时系统。RabbitMQ...
Erlang是一种高级编程语言,特别适用于并发、分布式和实时系统。它由Ericsson公司开发,主要用于构建高可用性、容错性和可扩展性的软实时系统。Erlang的25.0版本是该语言的一个更新,针对Windows操作系统进行了优化...
在IT领域,Erlang是一种面向并发的、...总的来说,使用Erlang连接Elasticsearch客户端,可以帮助开发者高效地与ES服务器交互,利用Erlang的强大并发性和函数式编程特性,实现稳定、高性能的搜索和数据分析解决方案。
本项目是一个基于Erlang的小型游戏服务器,使用了Mnesia数据库来存储游戏数据。 Mnesia是Erlang内置的一个分布式数据库管理系统,支持事务处理和实时查询,非常适合实时性要求高的游戏场景。在这个小型游戏服务器中...
Erlang是一种面向并发的、函数式编程语言,由瑞典电信设备制造商Ericsson为了实现分布式实时、高可靠性系统而开发。Erlang以其强大的并行处理能力、容错性和易于构建大规模分布式系统的特点,在电信、金融和互联网等...
Erlang是一种面向并发的、函数式编程语言,主要用于构建高度可扩展的、容错性强的分布式系统。在IT行业中,Erlang因其强大的实时性、并发性和内存管理机制而被广泛应用于网络通信、数据库系统以及消息中间件,如...