云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

负载均衡_培训学校网站建设_试用

小七 141 0

介绍lua-capnproto:lua中更好的序列化

当我们需要将数据从一个程序传输到另一个程序时,无论是在计算机内还是从一个数据中心到另一个程序,都需要某种形式的序列化。序列化将存储在内存中的数据转换成可以通过网络或进程间发送的格式,然后再转换回程序可以直接使用的数据。在CloudFlare,我们在世界各地都有数据中心。当数据从一个数据中心传输到另一个数据中心时,我们需要一种非常有效的串行化数据的方法,既节省时间又节省网络带宽。我们看了一些序列化项目。例如,一种流行的序列化格式是JSON,对于我们的一些Go程序,我们使用gob,并且我们在过去使用了协议缓冲区。但是最近我们一直在使用一种新的串行化协议Cap'nproto。Cap'n Proto吸引了我们,因为它与其他序列化项目相比具有非常高的性能。它看起来有点像协议缓冲区的更好版本,Cap'nproto的作者Kenton是Protocol Buffers version 2的主要作者。在CloudFlare,我们将NGINX与Lua一起用于前端web服务、代理和流量过滤。我们需要在Lua中序列化我们的数据并通过Internet传输。但不幸的是,Cap'n Proto没有Lua模块。因此,我们决定编写luacapnproto,并将其作为CloudFlare开源贡献的另一部分发布。luacapnproto提供了非常快速的数据序列化和一个非常易于使用的API。在这里,我将向您展示如何使用luacapnproto执行序列化和反序列化。安装lua capnproto要安装luacapnproto,首先需要安装Cap'nproto、luajit2.1和luarocks。然后可以使用以下命令安装lua capnproto:git克隆https://github.com/cloudflare/lua-capnproto.gitcd-lua-capnproto公司sudo luarocks制造要测试lua capnproto是否成功安装,可以使用capnp编译器生成Cap'n Proto示例之一的lua版本,如下所示:capnp编译-olua proto/示例.capnp如果一切顺利,您应该不会看到错误和一个名为example的文件_卡普纳卢亚在proto目录下生成。写一个Cap'n原型定义下面是一个示例Cap'n Proto定义,它将存储在一个名为地址簿.capnp:@0xdbb9ad1f14bf0b36;#唯一文件ID,由capnp ID生成结构人{id@0:UInt32;名称@1:Text;电子邮件@2:Text;电话@3:List(电话号码);结构电话号码{数字@0:Text;类型@1:type;枚举类型{移动@0;家@1;工作@2;}}就业:工会{失业@4:Void;雇主@5:Text;学校@6:Text;个体户@7:Void;#我们假设一个人只是其中之一。}}结构通讯录{人@0:List(人);}我们有一个名为AddressBook的根结构,其中包含一个名为people的列表,其成员也是结构。我们要做的是序列化一个地址簿结构,然后从序列化数据中读取该结构。有关Cap'n Proto定义的更多细节,可以在这里查看它的文档。准备你的数据准备数据非常简单。您需要做的就是生成一个对应于根结构的Lua表。下表给出了帮助您编写此表的规则。左边是Cap'n Proto数据类型,右边是对应的Lua数据类型。struct->Lua哈希表列表->Lua数组表bool->Lua布尔值int8/16/32或uint8/16/32或float32/64->Lua编号int64/uint64->LuaJIT 64位编号枚举->Lua字符串void->Lua字符串"void"group->Lua哈希表(与struct相同)union->Lua哈希表,只有一个值集注意事项:因为Lua number type表示实数(双精度浮点),而Lua没有整数类型,所以默认情况下,不能使用number类型存储64位整数而不丢失精度。LuaJIT有一个支持64位整数的扩展。您需要在数字的末尾加上ULL或LL(ULL表示无符号整数,LL表示有符号整数)。因此,如果您需要序列化一个64位整数,请记住将ULL或LL附加到您的数字中。例如:id@0:Int64;->id=12345678901234LL枚举值会自动从字符串转换为它们的值,您不需要自己进行转换。默认情况下,枚举将转换为带下划线的大写形式。可以使用批注更改此行为。lua capnproto文档有更多细节。下面是一个例子:类型@0:type;枚举类型{二进制地址@0;文本地址@1;}->类型="文本地址"虚空是Cap'n Proto中的一种特殊类型。为了简单起见,我们只使用一个字符串"Void"来表示Void(实际上,在序列化时,除了nil之外的任何值都可以工作,但是我们使用"Void"来保持一致性)。示例数据表如下所示:本地数据={人员={{id="123",name="爱丽丝",电子邮件="alice@example.com",电话={{number="555-1212",type"]="移动",},},就业={school="麻省理工",},},{id="456",name="鲍勃",电子邮件="bob@example.com",电话={{number="555-4567",type"]="家",},{number="555-7654",type"]="工作",},},就业={失业="无效",},},}}编译并运行现在让我们编译Cap'n Proto文件:capnp编译-olua地址簿.capnp你不应该看到任何错误和一个名为AddressBook的文件_卡普纳卢亚在当前目录下生成。要使用这个文件,我们只需要写一个名为主.lua(或任何您想要的名称),并准备好所有必需的模块。本地地址簿=需要"地址簿\u capnp"本地capnp=需要"capnp"现在我们可以开始使用我们已经准备好的数据进行序列化。本地bin=地址簿.addressBook.serialize(数据)就这样。只有一行代码。所有序列化工作都已完成。现在变量bin(一个Lua字符串)保存序列化的二进制数据。您可以将此字符串写入文件或通过网络发送。想要反序列化吗?这就像序列化一样简单。本地解码=地址簿.addressBook.parse(垃圾箱)现在,variable decoded保存一个与数据相同的表。你可以在这里找到完整的代码。请注意,您需要LuaJIT来运行代码。性能如果您对API满意,这里有更好的消息。我们选择Cap'n Proto是因为它具有令人印象深刻的高性能。所以在写lua capnproto的时候,我也尽了最大的努力让它快点。在一个项目中,我们从lua cjson(一个非常快速的lua JSON库)切换到lua capnproto进行序列化。让我们看看lua capnproto和lua cjson相比有多快。

性能

你也可以跑步基准.lua您自己(包括在源代码中)来了解lua capnproto与机器上的lua cjson相比有多快。未来我们已经在CloudFlare的生产中使用lua capnproto,它在过去的一个月里运行得非常好。但是lua capnproto仍然是一个非常年轻的项目。一些功能缺失,未来还有很多工作要做。我们将继续使luacapnproto更加稳定和可靠,并且很乐意接受来自开源社区的贡献。