如何使用 Snap Framework 维护服务器端状态?

发布于 2024-09-27 05:45:33 字数 84 浏览 5 评论 0原文

服务器端会话还不是 Snap 框架的一部分。有没有办法添加某种服务器端状态?

假设我想为每个 HTTP 请求增加一个计数器。我该怎么做呢?

Server-side sessions are not [yet] part of the Snap Framework. Is there a way to add some sort of server side state?

Let's pretend I want to increment a counter for each HTTP request. How would I do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云仙小弟 2024-10-04 05:45:33

上面的答案是正确的,但它没有解决一些实际问题。

首先是服务器重新启动。如果您的存储不仅仅是缓存,那么它需要在服务器重新启动后保持持久性。

其次是代码重新加载。 Snap 的未来版本,从 0.3 开始(可能在 12 月初)将在开发使用中动态重新加载代码。就开发速度而言,这是一个巨大优势,但它使服务器本地状态成为一项有趣的智力练习。如果程序员更改了服务器本地状态的类型/初始化/任何内容,则需要重新初始化。那里存在一些巨大的工程挑战。

当我为 0.3 编写动态重新加载代码时,我为这个问题苦苦挣扎了一段时间。然后我又看了看其他平台。 PHP?将所有内容存储在外部(数据库、内存缓存等)。内存中根本没有交叉请求存储。 Ruby on Rails?相同的。

结合第一个问题固有的挑战,我得出的结论是,除了可能的缓存优化之外,服务器应该是无状态的。将耐久性问题留给为其设计的库/外部流程。

因此,我设计了生产和开发加载器(一个使用静态加载,另一个使用动态加载)使用的通用接口,以采用 3 个函数:初始化函数、清理函数和使用初始化函数返回的状态的处理程序。在生产模式下,编译为在服务器启动时调用初始化,并在服务器关闭时调用清理。在开发模式下,它编译为:对于每个请求,动态加载所有 3 个请求,然后运行 ​​init、handler、cleanup。显然,没有任何状态能够在这种方式的交叉请求中生存下来。

然后我的答案变成:通过某种具有内置持久性的机制进行交叉请求存储,并让服务器状态只是其接口。如果您想在进程内工作,请使用 happstack-state 或 sqlite 之类的东西;如果您想在本地进程之外工作,请使用数据库或其他外部存储。

作为补充说明,由于添加了 MonadSnap 接口,管理“全局”资源(如连接池等)在 Snap 0.3 中也变得更加容易。

The above answer is correct as far as it goes, but it doesn't deal with some real issues.

First up is server restarts. If your storage is more than caching, it needs to be durable across server restarts.

Second is code reloading. Future versions of Snap, starting with 0.3 (probably due in early December) will have dynamic code reloading in development use. This is a huge advantage in terms of development speed, but it makes server-local state an interesting mental exercise. If the programmer changes the type/initialization/whatever of the server-local state, it needs to be re-initialized. There are some tremendous engineering challenges there.

When I was writing the dynamic-reloading code for 0.3, I struggled with that issue for for a while. Then I looked at other platforms. PHP? Stores everything externally (database, memcache, whatever). No cross-request storage in-memory at all. Ruby on Rails? Same.

When combined with the challenges inherent in the first issue, I came to the conclusion that the server should be stateless, aside from possible caching optimizations. Leave durability concerns for libraries/external processes that are designed for it.

So I designed the common interface used by the production and development loaders (one uses static loading, the other dynamic loading) to take 3 functions: An initialization function, a cleanup function, and a handler that uses the state returned by the initialization function. In production mode, that compiles down to calling initialize at server startup, and cleanup at server shutdown. In development mode, it compiles down to: for each request, dynamically load all 3, then run init, handler, cleanup. Obviously, no state will survive cross-request that way.

And then my answer becomes: Do your cross-request storage via some mechanism with built-in durability, and have the server state just be the interface to that. Use something like happstack-state or sqlite if you want to work in-process, or a database or some other external store if you want to work outside the local process.

Just as an added note, managing "global" resources like a connection pool or the like is also far easier in Snap 0.3, due to the addition of the MonadSnap interface.

几味少女 2024-10-04 05:45:33

最简单的方法是将状态放在 mvar 后面:

fooHandler :: MVar Int -> Snap ()
fooHandler mvar = do
    x <- liftIO $ modifyMVar mvar $ \y -> let y'=y+1 in (y',y')
    writeBS $ S.pack $ "Incremented counter to: " ++ show x

在站点初始化时初始化 mvar。希望这有帮助。

Easiest way is to put the state behind an mvar:

fooHandler :: MVar Int -> Snap ()
fooHandler mvar = do
    x <- liftIO $ modifyMVar mvar $ \y -> let y'=y+1 in (y',y')
    writeBS $ S.pack $ "Incremented counter to: " ++ show x

Initialize the mvar when the site is initialized. Hope this helps.

伤痕我心 2024-10-04 05:45:33

我找到了两个与会话相关的包:

snap-auth 由 Snap Framework 团队制作,或者至少由其作者之一制作/贡献者(Ozgun Ataman)。它的目标是身份验证和会话管理。会话管理是使用 ByteString 到 ByteString 的映射来完成的,这意味着您只能存储已经序列化为 ByteString 的数据:

type Session = Map ByteString ByteString

另一方面,mysnapsession 允许您使用任意类型来建模你的会议。然而,Map 类型的会话有一些辅助函数。更多详细信息请参见此处。作者 Chris Smith 也是 Snap Framework 项目的成员。

I found two session-related packages:

snap-auth is made by the the Snap Framework team, or at least by one of its authors/contirbutor (Ozgun Ataman). It targets authentication and session management. The session management is done using a map of ByteString to ByteString, implying you can only store data that has already been serialized to a ByteString:

type Session = Map ByteString ByteString

On the other hand, mysnapsession allows you to use an arbitrary type to model your session. There is however some helper functions for sessions of the Map type. More details here. The author, Chris Smith, is also part of the Snap Framework project.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文