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