uwsgi剖析

uwsgi源码

2023版uwsgi,包含119334行c代码,12w代码量级。

uwsgi源码剖析

部分源码剖析

流程(不使用gevent插件)

main
    uwsgi_setup
    	uwsgi_register_loop("simple", simple_loop);
    	uwsgi_register_loop("async", async_loop); # 这里只是注册到uwsgi.loops中
        uwsgi_start
        	/* plugin initialization 调用插件的init接口,初始化插件*/
        	for (i = 0; i < uwsgi.gp_cnt; i++) {
        		if (uwsgi.gp[i]->init) {
        			uwsgi.gp[i]->init();
        		}
        	}
        	    # 如果配置了http = :8080,则说明使用http插件的http配置,uwsgi去作为http服务器(会将http请求转发到worker监听的socket)。会使用uwsgi_opt_corerouter(会调用uwsgi_new_gateway_socket,去创建uwsgi.gateway_sockets)。这里worker不会监听这个http的fd,而是单独创建自己的fd(uwsgi.sockets)。
        	    这里调用http插件的http_init函数
        	        uwsgi_corerouter_init
        	            uwsgi_corerouter_setup_sockets
        	                uwsgi_socket_nb # 绑定http网关socket
                        register_gateway # 注册一个 uwsgi_corerouter_loop 函数
            uwsgi_bind_sockets # 这个绑定配置的socket到uwsgi.sockets
            uwsgi_respawn_worker # 这里fork出worker进程了
    uwsgi_run
            master_loop # 只有master走此逻辑,永远在此执行,不往下。worker则走下面逻辑
                gateway_respawn # 这里创建gateway进程,监听uwsgi.gateway_sockets(如果使用了http gateway的情况下)
                    这里fork一个进程,最终执行uwsgi_corerouter_loop,里面有循环监听uwsgi.gateway_sockets了
            uwsgi_map_sockets
            uwsgi_worker_run
                uwsgi_ignition
                    simple_loop(or async_loop),根据情况定
                        simple_loop_run
                            event_queue_init # epoll_fd创建
                            uwsgi_add_sockets_to_queue # 将uwsgi.sockets中的socket注册到epoll_fd
                                event_queue_add_fd_read
                            循环执行,处理请求
                            wsgi_req_setup
                            wsgi_req_accept
                            wsgi_req_recv
                                wsgi_req->socket->proto(wsgi_req)\uwsgi_proto_uwsgi_parser # read fd中的内容到缓冲区
                                uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req); # 调用插件的request,这里是python plugin的request函数(uwsgi_request_wsgi)
                                    uwsgi_request_subhandler_wsgi(因为init_uwsgi_app时:wi->request_subhandler = uwsgi_request_subhandler_wsgi;)# 调用请求handler
                                        wsgi_req->async_app = wi->callable;
                                        python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req) # 执行配置的callable入口了
                                    uwsgi_response_subhandler_wsgi (因为init_uwsgi_app时:wi->response_subhandler = uwsgi_response_subhandler_wsgi;)# 响应handler
                                        uwsgi_python_send_body
                                            uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) 
                                                uwsgi_response_writev_headers_and_body_do(wsgi_req, buf, len)
                                                    wsgi_req->socket->proto_writev\uwsgi_proto_base_writev # 往对应fd写响应内容
                            uwsgi_close_request
                                after_request(在各个plugin中实现,after_request hook,已python plugin为例)
                                    uwsgi_after_request_wsgi(python plugin中)
                                        log_request(wsgi_req); # 打印请求信息
                                            uwsgi.logit(wsgi_req); # uwsgi.logit = uwsgi_logit_simple;
                                                uwsgi_logit_simple
                            

使用gevent插件流程

main
    uwsgi_setup
    	uwsgi_register_loop("simple", simple_loop);
    	uwsgi_register_loop("async", async_loop); # 这里只是注册到uwsgi.loops中
        uwsgi_start
        	/* plugin initialization 调用插件的init接口,初始化插件*/
        	for (i = 0; i < uwsgi.gp_cnt; i++) {
        		if (uwsgi.gp[i]->init) {
        			uwsgi.gp[i]->init();
        		}
        	}
        	    # 如果配置了http = :8080,则说明使用http插件的http配置,uwsgi去作为http服务器(会将http请求转发到worker监听的socket)。会使用uwsgi_opt_corerouter(会调用uwsgi_new_gateway_socket,去创建uwsgi.gateway_sockets)。这里worker不会监听这个http的fd,而是单独创建自己的fd(uwsgi.sockets)。
        	    这里调用http插件的http_init函数
        	        uwsgi_corerouter_init
        	            uwsgi_corerouter_setup_sockets
        	                uwsgi_socket_nb # 绑定http网关socket
                        register_gateway # 注册一个 uwsgi_corerouter_loop 函数
                
                # 配置了gevent,会使用gevent loop engine,就不会再使用simple_loop
                    // set loop engine
	                uwsgi.loop = "gevent"
                    
                    uwsgi_register_loop( (char *) "gevent", gevent_loop);
            uwsgi_bind_sockets # 这个绑定配置的socket到uwsgi.sockets
            uwsgi_respawn_worker # 这里fork出worker进程了
    uwsgi_run
            master_loop # 只有master走此逻辑,永远在此执行,不往下。worker则走下面逻辑
                gateway_respawn # 这里创建gateway进程,监听uwsgi.gateway_sockets(如果使用了http gateway的情况下)
                    这里fork一个进程,最终执行uwsgi_corerouter_loop,里面有循环监听uwsgi.gateway_sockets了
            uwsgi_map_sockets
            uwsgi_worker_run
                uwsgi_ignition
                    void (*u_loop) (void) = uwsgi_get_loop(uwsgi.loop); # 这里使用了gevent配置,就会使用gevent_loop
                    u_loop();
                        gevent_loop
                        	PyObject *uwsgi_gevent_main = PyCFunction_New(uwsgi_gevent_main_def, NULL); // main greenlet waiting for connection (one greenlet per-socket) 每个socket执行一个uwsgi_gevent_main_def协程
                        	
                        	PyObject *uwsgi_request_greenlet = PyCFunction_New(uwsgi_gevent_request_def, NULL); // greenlet to run at each request 为每个到达的请求准备一个协程
                        	
                        	PyObject_CallMethod(ugevent.watchers[i], "start", "Ol", uwsgi_gevent_main,(long)uwsgi_sock); # for循环所有socket,开启每个socket的 uwsgi_gevent_main_def 协程
                        	...
                        	
                        	# py_uwsgi_gevent_main协程, 主要是接受accpet请求
                    	    py_uwsgi_gevent_main(执行uwsgi_gevent_main_def协程)
                    	        wsgi_req_simple_accept
                    	        
                    	        PyObject *new_gl = python_call(ugevent.spawn, ugevent.greenlet_args, 0, NULL); // spawn the request greenlet,执行请求协程uwsgi_request_greenlet
                        	
                        	# 请求协程uwsgi_request_greenlet,处理请求
                        	py_uwsgi_gevent_request
                        	    wsgi_req->socket->proto(wsgi_req); # \uwsgi_proto_uwsgi_parser # read fd中的内容到缓冲区
                                uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req); # 调用插件的 request,这里是python plugin的request函数(uwsgi_request_wsgi)
                                    uwsgi_request_subhandler_wsgi(因为init_uwsgi_app时:wi->request_subhandler = uwsgi_request_subhandler_wsgi;)# 调用请求handler
                                        wsgi_req->async_app = wi->callable;
                                        python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req) # 执行配置的callable入口了
                                    uwsgi_response_subhandler_wsgi (因为init_uwsgi_app时:wi->response_subhandler = uwsgi_response_subhandler_wsgi;)# 响应handler
                                        uwsgi_python_send_body
                                            uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) 
                                                uwsgi_response_writev_headers_and_body_do(wsgi_req, buf, len)
                                                    wsgi_req->socket->proto_writev\uwsgi_proto_base_writev # 往对应fd写响应内容
                            uwsgi_close_request
                                after_request(在各个plugin中实现,after_request hook,已python plugin为例)
                                    uwsgi_after_request_wsgi(python plugin中)
                                        log_request(wsgi_req); # 打印请求信息
                                            uwsgi.logit(wsgi_req); # uwsgi.logit = uwsgi_logit_simple;
                                                uwsgi_logit_simple
                            
  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值