在HTTP服务器中共享不可变引用



我目前正在构建一个HTTP服务,公开对一个唯一对象的操作。我已经创建了中心对象,有几个方法使用不可变的&self引用,并在内部使用各种高效的同步结构来访问内部的数据(所有代码都是不安全的)。我的想法是,这将足以使其安全地同时使用。

然后是将其实际连接到HTTP服务器的困难部分。我目前正在尝试使用Iron,但如果它能让事情变得更容易,我可以切换到Nickel.rs或任何其他版本。

我看到的大多数HTTP服务器示例都使用了无状态处理程序,没有任何对本地变量的访问。我现在明白了为什么:这几乎是不可能做到的。

下面是我想使用Nickel.rs做的一个示例:https://gist.github.com/Gyscos/42510a335098ce935848

以下是使用Iron的类似失败尝试:https://gist.github.com/Gyscos/92e56e95baee0ebce78f

基本思想是obj只在作用域的持续时间内存在,但服务器也存在,所以这应该不是什么大不了的。。。正确的

不幸的是,我的每一次尝试都失败了。当试图给服务器一个访问self.object的闭包时,我收到一个错误,说闭包可能比引用更持久。

我看到Iron提供了一个具有Read结构的共享内存模块。它不仅对我的需求来说过于复杂,而且在我不需要的时候,我也希望避免支付Arc的价格(我对对象的生命周期有清晰的了解,真的不需要计算引用)。

我目前看到的解决方案是使用一个静态对象,而不是一个特定于MyServer的对象,但如果可能的话,我更愿意避免这种丑陋的程度。

我来自golang,在那里这不是问题(我可以使用对象绑定方法作为处理程序)。所以我的问题是:如何从Rust中的HTTP处理程序轻松访问共享的不可变引用?

请注意,我之前没有使用镍或铁的经验(就我个人而言,到目前为止我正在使用SCGI)。

我编译你的Nickel示例时遇到的错误是:

<nickel macros>:7:9: 7:70 error: captured variable `obj` does not outlive the enclosing closure

错误发生在以下代码段中:

server.utilize(router! {
get "/foo" => |_req, _res| {
obj.foo();
}
});

现在,router!只是一个奇特的宏,可以将闭包封装在Middleware中,并内置一些额外的检查。在我们的研究中,我们可能想找到根并直接使用Middleware

不幸的是,Nickel明确要求中间件具有'static生存期。这是Nickel API设计的一个怪癖,与Rust本身没有太多关系(除了Rust允许库要求用户提供这些东西)。

我看到两种选择。首先是使用我们对对象寿命的高级知识(Nickel不知道我们的对象比服务器寿命长,但我们知道)并告诉编译器这一点。编译器允许我们用有用的unsafetransmute原语来展示我们的高级知识。

它在这里,工作:unsafe.rs.

在Rust中,unsafe的意思是"这段代码是安全的,因为程序员这么说"。每一个unsafe都必须满足程序员和编译器之间的安全契约。在这种情况下,我们知道对象的寿命比服务器长,因此保持了安全保证。

第二种选择是为满足镍API要求的技巧支付价格。在这里,我们使用一个作用域线程本地存储:thread_local.rs.

一句话:镍API有一些要求,可以让你跳过一些环节,到达你想要的地方。我还没有调查过铁API。我有一种感觉,你可能会有一个更好的运气与低级别的Hyper API。

相关内容

最新更新