5个版本
0.1.4 | 2024年2月21日 |
---|---|
0.1.3 | 2024年2月18日 |
0.1.2 | 2024年2月18日 |
0.1.1 | 2024年2月17日 |
0.1.0 | 2023年7月8日 |
#194 在 HTTP服务器
每月160次下载
21KB
213 行
Norgopolis
Norgopolis是用于桌面上的Neorg rust-native模块生态系统的一个轻量级通信、启动和实用程序服务客户端。它设计用于连接、启动和管理诸如Norgberg数据库系统等模块的实例,这些模块在每个桌面上只能存在一次,但为多个前端(如多个neovim进程)提供服务,无需进行中间进程所有权变更或进程重新启动。
Norgopolis还提供了下载和连接不同服务的能力,而无需重新编译或完全重新启动,这使得普通用户可以轻松修改和扩展。
为什么?
Norgopolis解决了四个问题
-
我们如何在有多个前端的同时提供如数据库-over-notes这样的单例服务?
-
我们如何确保第一个启动的前端(必须启动所有后台服务)的退出不会导致服务丢失、服务中断、无法传递给另一个线程或类似问题?
- 我们如何确保在最后一个前端确实退出时进程退出?
-
我们如何允许人们在不重新编译或需要不稳定共享对象动态加载的情况下,使用新原生模块扩展他们的安装?
-
我们如何以轻量级、高效的方式让这些模块相互通信以及与任何前端调用者通信?
Norgopolis解决了这些问题。
工作原理
Norgopolis由两部分组成:客户端和服务器后端。它们使用gRPC相互通信。
当启动客户端时,它尝试查找现有的服务器实例。如果找不到现有实例,它将以独立进程的方式启动服务器。如果找到了现有服务器,它将连接到该服务器并以客户端会话登录。
Norgopolis服务器跟踪注册的客户端引用计数。如果客户端死亡或在没有通信的情况下超时一段时间,它们将从引用计数中删除。如果引用计数达到零,Norgopolis将优雅地退出自己及其所有子进程。
诺哥波利斯的核心是前端gRPC连接和当前加载的模块集之间的通信路由器。"模块"是符合诺格原生模块标准的可执行二进制文件。该标准定义了一个基于stdin/stdout通信通道的protobuffer gRPC接口。模块必须能够接受方法调用调用,并在启动时提供一条消息,声明其名称、语义版本号和潜在依赖项。诺伯格就是这样一种模块的示例,提供数据库服务。
与路由器相关的是诺哥波利斯的加载能力。诺哥波利斯使用gRPC协议缓冲数据中指定的模块名称进行调用路由。如果没有在路由器上注册此类模块,诺哥波利斯将尝试在给定目录中找到该二进制文件,并将其作为子进程启动。这允许内在的懒加载。模块可以在其启动信息结构中声明瞬态模块依赖项,在这种情况下,诺哥波利斯加载器将验证其可用性,如果依赖项不可用,则加载失败。同样,无法定位可执行二进制文件将优雅地失败。
模块只需要是编译后的二进制文件或可执行的程序。它们作为诺哥波利斯的独立子进程运行。注意:这意味着如果诺哥波利斯存在,这些子进程也会存在。这是设计的一部分,应该谨慎绕过。诺哥波利斯退出时会广播关闭gRPC消息。
这还描述了诺哥波利斯提供的工具:它们与模块的加载、管理和关闭有关。
客户端接口
客户端公开了面向Lua的Rust函数和接口,并作为一个独立的crate。这用于在gRPC中桥接方法调用,执行服务器的状态化启动注册逻辑,以及解包和传递方法调用返回值。
路由器接口
路由器通过gRPC与任何它维护的客户端或其他外部调用者进行通信,这些调用者不是模块。请注意,这意味着您可以从任何其他应用程序(如果它在运行)通过它调用任何模块,例如Web插件或一次性脚本,只要它们具有正确的协议缓冲区和mpack规范。
模块通过stdin/stdout管道化的protobuffer与路由器以及调用者和其他模块进行通信,服务器提供异步路由。
诺哥波利斯安全启动
作为一项一般政策,诺哥波利斯设计为同时服务n个前端客户端。这固有的安全含义是,诺哥波利斯默认不会拒绝来自连接的新客户端。如果需要更多安全性,诺哥波利斯可以以单连接模式启动,作为单个前端的孩子。这会隔离通信和可调用性,但会导致任何进一步的客户端启动失败。
[!NOTE] 此行为目前尚未实现。
有趣的技巧和影响
由于诺哥波利斯以子进程的形式启动可执行文件,并使用stdin/stdout上的协议缓冲进行通信,任何符合我们规范的可执行文件都可以作为模块加载。这不仅有助于抵御Rust ABI版本之间的变化,还允许加载用其他语言编译(或现场解释)的模块。但请注意性能影响,并且模块通常被认为是持久的,直到通过向服务器或服务器退出发送命令来卸载,以及所有模块线程。尽管如此,您也可以作为模块自行退出。再次提醒,请注意影响。
自我加载
在Norgopolis中,由于安全设计,加载新模块的能力受到限制。然而,如果将模块执行文件放置在加载文件夹中,然后在gRPC连接上作为客户端调用该模块的方法调用,就可以按需加载模块。这将启动加载和执行。这可以用于从外部脚本执行较大的批处理类型活动,使用外部脚本作为启动器和控制器,并将您的自定义模块作为Norgopolis系统上的内部工作者。
默认懒加载
Norgopolis默认情况下,只有在接收到调用且没有激活的该模块名称的线程可以路由到时,才会尝试加载模块。这种隐式懒加载可以用于减少启动时间。Norgopolis具有自动启动某些服务的能力,部分原因是其瞬态依赖性检查,但这是建立在懒加载行为之上的。
依赖关系
~7–19MB
~222K SLoC