资讯专栏INFORMATION COLUMN

基于Webpy实现服务器策略模型

tain335 / 2139人阅读

摘要:现在我们来谈一些黑科技,希望能给大家一些启发和帮助。这里针对的情况是,两次连接之间的时间段是断开的情况。而在每一次退出执行的时候都要保存一下,除非已经执行结束了,或者执行出现了错误也相当于执行结束,才把它削除。

现在我们来谈一些(黑)科技,希望能给大家一些启发和帮助。现在我有一个策略文件addition.policy

load!: addition_delegate.py

await: first_string -> s1
apply: concat_with_time(s1) -> s1

await: second_string -> s2
apply: concat_with_time(s2) -> s2

await: return_result
apply: join_with_linefeed(s1, s2) -> result
yield: result

还有一个委托函数的Python源码addition_delegate.py

# addition_delegate.py

def concat_with_time(s):
    import time

    return str(s) + time.ctime()

def join_with_linefeed(s1, s2):
    return "%s
%s
" % (str(s1), str(s2))

这是什么语法?但是我们大抵都能明白它想干什么:先后获取两个字符串,分别将它们和时间拼接在一起,然后在获取return_result后回传结果。然后呢?然后我们有一些Web接口,简单地用web.py编写main.py

#!/usr/bin/env python

import web
from policy import resume

class first_str_view:
    def GET(self):
        resume("addition.policy", "first_str",
            value = web.input()["value"], anew = True)
        return ""

class second_str_view:
    def GET(self):
        resume("addition.policy", "second_str",
            value = web.input()["value"])
        return ""

class return_result_view:
    def GET(self):
        return resume("addition.policy", "return_result")

urls = [
    "/first_str/?", first_str_view,
    "/second_str/?", second_str_view,
    "/return_result/?", return_result_view,
]

if __name__ == "__main__":
    app = web.application(urls, globals())
    app.run()

就算没用过web.py的人都大抵能明白这个结构是什么意思了,除了那个resume有点不知所谓之外,但是结合上面的那个addition.policy,好像看上去也挺合理,大概就是从acquire处断开,然后得到输入后继续执行那个policy。如你所料:

$ ./main.py 9999 &
[1] 19121
http://0.0.0.0:9999/
$ curl "http://localhost:9999/first_str?value=First+Record+"
$ curl "http://localhost:9999/second_str?value=Second+Record+"
$ curl "http://localhost:9999/return_result"
First Record Sat Sep  5 15:59:25 2015
Second Record Sat Sep  5 15:59:28 2015

这样可以解决很多问题。比如在用户更变邮箱的时候,用户先提交新邮箱,然后还要等等他什么时候去邮箱里收验证邮件,这样更变邮箱的操作才完成。还有一些更麻烦的操作,整个流程下来,要收几次输入,然后才能真正地输入成功存进数据库。举个例子,你可以简单地写一个策略文件,让它控制整个流程,接口只需要跟用户打交道就好了:

load!: email_service
assert!: is_authenticated

await: modify_email -> address
apply: send_verf_email(address)

await: verf_email_recv
apply: save_current_user_info(address)

不得不说这种模型有点像是协程(coroutine),但是不是用它来实现的,毕竟:一次请求完成了整个线程大大小小都结束了哪里还有协程啊对吧。这也不是WebSocket能解决的:比如收验证邮件,都在第二个地方连接了,哪里还有Socket可言。这里针对的情况是,两次连接之间的时间段是断开的情况。(如果非要用设计模式来说,我觉得是一个策略+状态+解释器的组合,然而我并不喜欢被设计模式拘束)

实现思路

主要是在模拟恢复执行的时候能较好地恢复原有上下文,在Python有exec的情况下,想办法生成可配合执行Python代码是一个不错的选择。恢复执行有这些步骤:

解析策略文件

从持久存储设备中反序列化上下文

找到断点应该在哪里,按照这个位置,执行一些每次都要执行的语句(标 !号)

一直执行到下一个await点,退出执行

先看一下resume()函数的一个实现是什么样子的:

from policy import policy

import pickle
import os

def resume(pf, await_tag, value = None, anew = False):
    c = context.start_new() if anew else 
        pickle.load(file("context.dump", "rb"))
    p = policy.load(pf)

    p.load_context(c)
    p.provide(await_tag, value)

    ret = None
    
    try:
        ret = p.resume()
    finally:
        os.remove("context.dump")

    if p.is_end():
        os.remove("context.dump")

    return ret

这里的contextpolicy是我对这个模型的一个实现,可以看出这两者是分开保存的,Policy几乎就是一个常量了,硬编码在一个文件里。而Context在每一次退出执行的时候都要保存一下,除非已经执行结束了,或者执行出现了错误(也相当于执行结束),才把它削除。

Policy-Control已经推上了Github,代码很短,欢迎各位围观:https://github.com/Shihira/policy-control

附:语法清单

digit  := "0" | ... | "9"
underscore := "_"

symbol ::=
    letter | underscore
    { letter | underscore | digit }

command ::= symbol
variable ::= symbol

string ::=
    """ {
    [ 0x00 | ... | 0x21 | 0x23 | ... | 0x7f | "
" | "
" | """ | "" ]
    } """

value ::= string | variable

parameter ::= value
parameter-list ::=
    "("
    [ parameter-list "," parameter | parameter ]
    ")"

argument ::= symbol [ parameter-list ]
argument-list ::= argument-list argument | argument

command-line ::=
    command [ "!" ] ":"
    argument-list
    [ "->" variable ]

policy ::=
    policy 
 command-line | command-line

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37602.html

相关文章

  • 基于Linux环境的Web.py框架介绍

    摘要:前言在文章基于环境搭建框架方法介绍中介绍了客户端和服务器的交互过程,服务器接收客户端的请求后,由应用服务器对浏览器的请求进行处理,将生成的响应传递给服务器,再由服务器返回给客户端。 前言 在文章《基于Linux环境搭建Nginx+uWSGI+Python框架方法介绍》中介绍了客户端和Web服务器的交互过程,Web服务器接收客户端的请求后,由Web应用服务器对浏览器的请求进行处理,将生成...

    caikeal 评论0 收藏0
  • [零基础学python]python开发框架

    摘要:软件开发者通常依据特定的框架实现更为复杂的商业运用和业务逻辑。所有,做开发,要用一个框架。的性能是相当优异的,因为它师徒解决一个被称之为问题,就是处理大于或等于一万的并发。 One does not live by bread alone,but by every word that comes from the mouth of God --(MATTHEW4:4) 不...

    lucas 评论0 收藏0
  • SAE 中使用 qiniu SDK for Python

    摘要:描述实现生成的业务接口产生一系列问题在部署的过程中遇到问题问题引用包在中创建应用的过程中默认是支出的,无需安装。 描述 SAE(SinaAppEngine) + webpy + qiniu sdk 实现生成token的业务接口 产生一系列问题 在部署的过程中遇到问题 问题1 引用qiniu for python 包 在SAE 中创建python web应用的过程中默认是支出webpy ...

    VEIGHTZ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<