Varlink:人机界面描述格式和协议

2021-01-04 20:18:37

每个人都明白。 Varlink使用简单的人类和机器可读文本文件来描述具有所有数据类型,方法调用和错误的接口。简单来说,该文本文件不需要任何特定知识即可加入有关API设计,开发和维护的讨论。

它在来源和网上记录了自己。 Varlink接口将其描述为对人类可读并可由机器可靠使用的接口。 Varlink服务在运行时是自省的。 Varlinkinterfaces提供其文档以及接口说明。

一切都是可读的。 Varlink使用纯文本消息,没有幻数,没有未命名的值,可以很容易地使用strace,netcat,jq等进行调试。

Varlink本身比使用它的服务简单。 Varlink使用直接连接,具有中央消息处理组件,易于调试,保护,隔离,测试。

Varlink可以在任何面向连接的传输上实现。最常见的示例是streamingsockets,但也可以在内核特殊文件(例如设备节点)上实现或封装在其他协议(例如HTTP,GSS-API或SASL)中。

Varlink连接可以变成监视器连接,它们在客户端和服务之间经过软协商。客户端要求服务器尽可能多地回复,服务器回复并指示它可能有更多回复,客户端应等待它们。

为了避免在读取当前状态和订阅更新之间出现争用情况,非典型varlink监视器方法调用首先返回当前状态,然后在随后的回复中发送更改,以对相同连接上的相同请求进行后续回复。

Varlink在连接上运行,所有消息严格按顺序在同一连接上,并且始终按其发送顺序进行接收。连接支持消息管道,但不支持多路复用。复杂的接口可以同时使用多个连接。

如果需要,供应商可以扩展varlink消息头。添加的密钥应使用反向域名,包括供应商的名称。这个概念类似于用于HTTP标头的X前缀,但是供应商既不应该添加它们,也不要添加裸关键字,因为它们可能与其他供应商或将来的varlink协议规范发生冲突。

varlink消息的最简单的传输方法是原始流套接字,该套接字转发由NUL字符分隔的JSON记录。从概念上讲,NUL字符属于传输而不是varlink消息。如果将varlink消息封装在HTTP中,则HTTP将指定记录长度,并且不使用NUL字节。

像JSON一样,在这方面故意未指定varlink。该实现应使用足够大的整数来承载带符号的整数值,如果无法处理收到的数字,则返回错误。

varlink类型系统指定不直接映射到JSON的功能,如何对它们进行序列化?

枚举被序列化为JSON名称/值对,而枚举值则为astring。地图被序列化为JSON对象,每个地图元素均以名称/值对的形式表示。

Varlink故意不支持特定于运输的功能或副作用。将varlink消息封装在其他协议中,然后通过代理传递它们是varlink的要求。

Varlink应该是可远程的,因此您不应将远程服务指向客户端本地的文件。只需发送内容和文件的标识符/名称即可。

您可以将数据作为字符串发送,也可以使用“升级的”连接功能,在这种情况下,您可以在调用将升级头字段设置为true的方法后选择退出varlink协议。发送此消息后,您可以通过该连接发送任何内容。要再次使用varlink协议与服务,您需要打开一个新连接。升级的varlinkconnections与websocket概念相似。

在方法调用中设置单向表示该服务将不发送答复。当许多消息作为一个事务的一部分发送时,并且只需要一个答复就可以确认该事务,这可能很有用。对于调试接口等非关键数据,将往返处理减至最少也可能很有用。

从一开始就添加此功能的最重要原因是,以后无法将其添加到协议中,因为所有实现都需要立即支持它才能正确处理严格的消息排序要求。

Varlink错误是特定于接口的,并由字符串标识。如果需要,接口可以将消息字段添加到包含人类可读文本的错误参数。 varlink错误的主要焦点是机器消耗,在大多数情况下,精心选择的描述性CamelCase错误足以将错误描述给人类。

在定义的varlink URI上具有org.varlink.resolver接口可访问的系统上,客户端可以调用org.varlink.resolver.Resolve(interface:string)方法。 (地址:字符串)。

varlink命令行工具以及某些varlink语言绑定提供了通过网桥连接到服务的可能性。

网桥命令通常是ssh< host>。 varlink网桥,在远程主机上调用varlink网桥。 varlink bridge命令解析stdin上的所有方法调用,查询远程系统上的org.varlink.resolver以获取接口地址,连接到该地址并将与接口名称匹配的所有方法调用转发到远程计算机上的本地服务。答复并将它们传递回stdout。代替ssh,可以使用任何其他连接命令。代替varlink bridge,可以使用提供相同功能的任何其他实用程序。

Varlink接口没有版本号,它们仅具有由接口定义详细描述的功能集,该定义是有线协议的一部分。

如果您的界面有用户,则不要破坏该界面,只能对其进行扩展,切勿删除或以不兼容的方式更改可能已经在使用的东西。客户可以完全自检一项服务,并弄清该接口支持的功能;这比任何简单的编号方案都更具表现力。如果您破坏了API或删除了内容,只需使用新名称发布它,通常是通过在接口名称上添加一个数字来完成,例如org.example.interface2。

Varlink在其接口定义或线路中不使用位置参数或固定大小的对象,所有参数均由其名称标识,以后可以扩展。

typedef struct {/ *…* / / * *保留空间,以允许将来可能的扩展而不会破坏ABI。您不应该触摸它们,因为这些变量的*名称可能会更改。 * / uint32_t reserved_int1; uint32_t reserved_int2; uint32_t reserved_int3; uint32_t reserved_int4;} my_service_struct_foo;

扩展现有结构应通过可选字段(可能为空类型)完成。当传递不带可选字段的参数时,方法的结果应与旧版本中的结果相同。方法参数可以用相同的方式扩展。应记录省略字段/参数的预期行为。删除字段,类型,错误或方法不向后兼容,应避免。

Varlink语言绑定通常实现systemd套接字激活协议。已启动服务的环境将使用变量LISTEN_FDS,LISTEN_NAMES,LISTEN_PID进行扩充。

服务可以通过套接字激活按需启动。 当没有正在运行的后台任务并且没有客户端连接到该服务时,该服务可以决定关闭侦听套接字并退出。 来自客户端的新连接将再次激活该服务。 因为varlink严格是点对点的,所以不涉及任何缓冲,并且服务激活器会将所有传入消息排队,因此可以无竞争地实现空闲退出。 最常用的方法是依靠文件系统中UNIX套接字的权限。需要更细粒度访问控制的服务可以检查unixsocket的连接凭据并决定每个调用是否要代表 客户端。如果将varlink包装在GSS-API中,例如 Kerberos票证可用于更细粒度的访问控制。