一个UWSGI的例子

摘要:uwsgi执行顺序:启动master进程,执行python脚本的公共代码(import同一层)。然后生成worker进程,uwsgi.post_fork_hook=init_functions,初始化生成work子进程。然后请求来临时,每个子进程执行application代码

配置文件ini:



[uwsgi]
socket=192.168.62.20:8001
http=192.168.62.20:8003
master=true
pythonpath=../
module=breapi
processes=12
listen=256
disable-logging=true
daemonize=uwsgi.log
pidfile=uwsgi.pid
vacuum=true
harakiri=5
buffer-size=36384
stats=127.0.0.1:1717

原文http://pythonpaste.org/do-it-yourself-framework.html,http://blog.xsudo.com/archives/530.html
一个用来diy的框架

什么是WSGI
wsgi是一个在web服务器和应用程序app之间统一的接口,这样来规范app和web server,说的简单一点就是规范的接受web请求(request),但是不仅如此
1 你在类似CGI环境里分发传递,意味着数据可以在登录用户安全传递
2 在类似CGI环境里传递更多的上下文信息,脚本名称和路径
3 你可以扩展自身的wsgi环境,并允许回调,扩展信息并插入python对象,任何你想添加的却不能在http头里添加的
wsgi不仅仅是在web和应用之间,可以用在交互的每个层面 ,这使得应用app变成lib库,可以很好的扩展和重用

写一个wsgi应用

我们来简单的写一个wsgi的应用
简短的一个摘要
1 一个简单的wsgi应用就是一个可调用的对象比如一个function,有两个参数environ 和 start_response
2 环境environment是一个字典,python的标准字典有一些传统的http参数比如REQUEST_METHOD和HTTP_POST
3 environment可以包含一些特别的键wsgi.input 像post请求里的输入流
4 start_response是一个返回客户端结果的方法,需要提供http的状态和headers
start_response 是一个接受两个必需的固定参数和一个可选参数的 callable 对象. 为便于说明, 我们把这三个参数分别命名为: status, response_headers, 和 exc_info, 当然你也可以给他们起其他名字. 应用程序必需使用固定参数调用 start_response (比如:
start_response(status,response_headers)) , 参数 status 是一个形如 “999 Message here” 的表示状态的字符串。而 response_headers 参数是一个描述 http 响应头的列表, 其中每一个元素都是像 (header_name,header_value) 这样的元组。可选的 exc_info 参数会在后面的 start_response() callable 和 错误处理 两节中进行描述,该参数只有在应用程序产生了错误并希望在浏览器上显示错误信息的时候才用得上。

5 最后应用返回一个含有迭代器的response(通常是一个字符串列表)
例子

1
2
3
def app (environ , start_response ):
    start_response ( '200 OK' ,  [ ( 'content-type' ,  'text/html' ) ] )
     return  [ 'Hello world!' ]

然后更简单的一个server来运行这个app

1
2
3
if __name__  ==  '__main__':
     from paste  import httpserver
    httpserver. serve (app , host = '127.0.0.1' , port = '8080' )

这样就可以在本机用8080端口来请求他了

一个带有互动的例子

1
2
3
4
5
6
7
8
9
10
from paste. request  import parse_formvars
def app (environ , start_response ):
    fields  = parse_formvars (environ )
     if environ [ 'REQUEST_METHOD' ]  ==  'POST':
        start_response ( '200 OK' ,  [ ( 'content-type' ,  'text/html' ) ] )
         return  [ 'Hello, ' , fields [ 'name' ] ,  '!' ]
     else:
        start_response ( '200 OK' ,  [ ( 'content-type' ,  'text/html' ) ] )
         return  [ '<form method="POST">Name: <input type="text" '
                 'name="name"><input type="submit"></form>' ]

这些都很简单,我们需要更多的页面,测试还有运行环境

对象发布 Object publishing
一个典型的对象发布 转换 ‘/’ 为 ‘..’
/articles/view?id=5 转换为 root.articles.view(id=5)
我们必须启动相应的对象

1
2
3
4
5
6
class ObjectPublisher ( object ):
def  __init__ ( self , root ):
         self. root  = root
def  __call__ ( self , environ , start_response ):
        ...
app  = ObjectPublisher (my_root_object )

我们重写__call__方法来实现一个callable ObjectPublisher ,就像一个wsgi的方法,现在我们要做的事情就是传递environ进去,调用它,然后返回结果response

路径
WSGI会把请求的路径放到两个变量SCRIPT_NAME和PATH_INFO里
SCRIPT_NAME就是我们将要到达的地方脚本名称,PATH_INFO就是请求的路径,这是框架寻找对象的方式

我们来实现__call__方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def  __call__ ( self , environ , start_response ):
    fields  = parse_formvars (environ )
    obj  =  self. find_object ( self. root , environ )
    response_body  = obj (**fields. mixed ( ) )
    start_response ( '200 OK' ,  [ ( 'content-type' ,  'text/html' ) ] )
     return  [response_body ]
def find_object ( self , obj , environ ):
    path_info  = environ. get ( 'PATH_INFO' ,  '' )
     if  not path_info  or path_info  ==  '/':
         # We've arrived!
         return obj
     # PATH_INFO always starts with a /, so we'll get rid of it:
    path_info  = path_info. lstrip ( '/' )
     # Then split the path into the "next" chunk, and everything
     # after it ("rest"):
    parts  = path_info. split ( '/' ,  1 )
    next  = parts [ 0 ]
     if  len (parts )  ==  1:
        rest  =  ''
     else:
        rest  =  '/' + parts [ 1 ]
     # Hide private methods/attributes:
     assert  not next. startswith ( '_' )
     # Now we get the attribute; getattr(a, 'b') is equivalent
     # to a.b...
    next_obj  =  getattr (obj , next )
     # Now fix up SCRIPT_NAME and PATH_INFO...
    environ [ 'SCRIPT_NAME' ] + =  '/' + next
    environ [ 'PATH_INFO' ]  = rest
     # and now parse the remaining part of the URL...
     return  self. find_object (next_obj , environ )

现在用ObjectPublisher来包装应用,并放到一个包中去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from objectpub  import ObjectPublisher
class Root ( object ):
# The "index" method:
     def  __call__ ( self ):
         return  '''
        <form action="welcome">
        Name: <input type="text" name="name">
        <input type="submit">
        </form>
        '''

def welcome ( self , name ):
         return  'Hello %s!' % name
app  = ObjectPublisher (Root ( ) )
if __name__  ==  '__main__':
     from paste  import httpserver
    httpserver. serve (app , host = '127.0.0.1' , port = '8080' )

需要注意的是,本来WSGI是要传入一个app的方法的,于是这里用了对象,并实现了__call__方法,结果是一样的

我们会发现缺少很多东西,比较特殊的我们没有地方去设置输出的headers,还有request里的信息是很少的

1
2
3
4
5
6
7
8
9
10
11
# This is just a dictionary-like object that has case-
# insensitive keys:
from paste. response  import HeaderDict
class Request ( object ):
     def  __init__ ( self , environ ):
         self. environ  = environ
         self. fields  = parse_formvars (environ )
class Response ( object ):
     def  __init__ ( self ):
         self. headers  = HeaderDict (
             { 'content-type''text/html' } )

我们不想改变方法,但是不能让request对象和response对象在全局的变量里,因为我们想要线程安全
修改__call__方法为

1
2
3
4
5
6
7
8
9
10
11
import  threading
webinfo  =  threading. local ( )
class ObjectPublisher ( object ):
    ...
def  __call__ ( self , environ , start_response ):
        webinfo. request  = Request (environ )
        webinfo. response  = Response ( )
        obj  =  self. find_object ( self. root , environ )
        response_body  = obj (** dict (webinfo. request. fields ) )
        start_response ( '200 OK' , webinfo. response. headers. items ( ) )
         return  [response_body ]

现在在我们的方法里可以这么做

1
2
3
class Root:
     def rss ( self ):
        webinfo. response. headers [ 'content-type' ]  =  'text/xml'




uwsgi和Nginx是常用的Web服务器和应用服务器的组合。它们可以一起使用来提供高性能的Web应用程序服务。 在uwsgi和Nginx的关联中,需要进行一些配置。首先,需要修改uwsgi的配置文件,指定uwsgi与Nginx连接时使用的IP和端口。例如,可以将socket设置为127.0.0.1:8000。\[2\] 接下来,需要修改Nginx的配置文件。在server块中,可以使用location指令来配置请求的转发。例如,可以使用uwsgi_pass指令将请求转发给uwsgi服务器的IP和端口。在这个例子中,可以将uwsgi_pass设置为127.0.0.1:8000。同时,还需要包含uwsgi_params文件来传递请求参数。\[2\] 另外,Nginx还可以配置静态文件的处理。可以通过增加一个location块来指定静态文件存放的目录,使用alias指令来指定具体的目录路径。例如,可以将location设置为/static,并将alias设置为/var/www/static/。这样,当访问/static路径时,Nginx会返回对应的静态文件。\[4\] 总结起来,uwsgi和Nginx的关联可以通过修改配置文件来实现。首先需要修改uwsgi的配置文件,指定uwsgi与Nginx连接时的IP和端口。然后,需要修改Nginx的配置文件,配置请求的转发和静态文件的处理。这样,就可以实现uwsgi和Nginx的协同工作,提供高性能的Web应用程序服务。 #### 引用[.reference_title] - *1* *2* *3* [Nginx+uWSGI部署](https://blog.csdn.net/qq_41341757/article/details/113825603)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值