【学习之路】005.重读 Hypercorn 文档,进一步提升服务器性能

在之前的一篇文章()中,我们实现了一个基于 Flask 和 Hypercorn 的简单服务器的搭建,并实现了 HTTP2 协议。但这样的一个服务器显然不能满足一个现代(2023年)高性能服务器的需求,需要使用更多的新技术来进一步提升服务器性能与质量。

今天,重读 Hypercorn 文档,温故而知新,在上一次的基础上取得了一些突破。

启用 ASGI

WSGI (Web Server Gateway Interface) 和 ASGI (Asynchronous Server Gateway Interface) 都是用于构建 Web 应用的服务器中间件标准。

WSGI 是一种单调用、同步接口。当应用处理请求时,服务器不能处理其他请求,这会导致阻塞。

ASGI 是一种异步的接口,它使用事件循环来处理请求。当应用处理请求时,服务器可以同时处理多个请求,这可以避免阻塞。

因此,ASGI 比 WSGI 具有更高的性能,可以在高流量环境下更好地工作。同时,ASGI 还支持一些 WSGI 不支持的功能,例如 WebSocket 和异步 I/O。

显然,使用 ASGI 可以获得更高的性能和更多的功能,因此应尽可能地使用 ASGI。

在 2.0 以上版本的 Flask 里已经支持使用 ASGI 服务器。但由于 Flask 是一个 WSGI 应用框架,所以如果你想使用 ASGI 服务器,就需要使用一个能将 WSGI 转换为 ASGI 的中间件。在 Flask 官方文档中,推荐使用 asgiref 提供的 WsgiToAsgi 适配器(adapter)来实现这一点。

然后你就可以使用 ASGI 服务器为 asgi_app 提供服务。例如使用 Hypercorn :

HTTP 重定向

在上一次搭建的服务器中,为绑定(bind)80 端口,无法使用 HTTP 访问服务器。当输入域名或 IP 地址时,由于浏览器默认使用 HTTP 访问网站,就无法获取网站内容。因此,启用 HTTP ,并强制将 HTTP 请求 重定向为 HTTPS 请求,是一个十分必要的功能。

首先,我们需要在 Hypercorn 的配置中启用 80 端口:

 注意,在启用 HTTP2 时,bind 绑定的是 HTTPS 请求,而 HTTP 请求需要使用“不安全绑定”(insecure_bind)。

此时还不能实现  HTTP 请求重定向到 HTTPS,需要使用 Hypercorn 中间件(middleware)模块中的 HTTPToHTTPSRedirectMiddleware:

这样,当我们访问 http://127.0.0.1 时,就能重定向到 https://127.0.0.1 了。

注意,使用这一中间件的前提是 Flask 启用了 ASGI ,这在其源代码中可以清晰看到。传入的 app 必须是 ASGIFramework,否则会引发未知错误(亲测):

日志

Hypercorn 有两个日志记录器(logger),一个记录访问日志,另一个记录错误日志。在默认情况下仅启用了错误日志。当配置项中的 accesslog 与 errorlog 的值为 ‘-‘ 时,日志将被输出到标准输出(stdout 和 stderr)中, 任何其他值都将被视为目标日志文件的路径。

在实际的服务器中,我们往往是将日志记录到专门日志文件:

另外,也可配置 Web 服务器访问日志的格式。

默认情况下,Hypercorn 会选择 %(h)s %(l)s %(l)s %(t)s “%(r)s” %(s)s %(b)s “%(f)s” “%(a)s 作为格式。这个格式由一些原子(atoms)组成,每个原子代表一个信息字段,如 请求的方法、URL、来源 IP 地址、用户代理信息、状态码和响应时间等。

可以使用配置变量 access_log_format 来指定日志格式:

配置

在 Hypercorn 中,除了之前使用到的通过实例化 Config 类来配置以外,还有其他几种方式。

1.通过 TOML 文件

2.通过 Python 模块

Python 模块或 Python 模块中的实例可用于配置 Hypercorn 。

3.通过 Python 文件

在实际情况中,最常用的配置方法是从配置文件中加载配置:

另外,Hypercorn 中还有一些比较有用的配置项,值得引起注意。

1.include_server_header

Server 响应头是一个标准的 HTTP 响应头,用于指示服务器软件的名称和版本。

如果服务器响应头包含了 Server 字段,则恶意用户可能会利用这些信息来寻找漏洞进行攻击。例如,如果服务器使用的是某个版本的软件,并且有知名的漏洞存在,那么恶意用户可能会尝试利用该漏洞进行攻击。

因此,为了避免这种情况,应该尽量避免在响应头中包含 Server 字段,或者将 Server 字段设置为不敏感的值。

在 Hypercorn 中,提供了删除 Server 字段的功能,仅需将 include_server_header 配置为 False 即可。

2.use_reloader

use_reloader 是一个 Hypercorn 配置选项,它控制是否在代码更改时重新加载服务器。

当 use_reloader 设置为 True 时,Hypercorn 会监视你的代码,如果有更改,则会自动重新加载服务器。这对于开发和调试非常方便,因为你可以在保存代码时立即看到更改的效果。

当 use_reloader 设置为 False 时,Hypercorn 不会自动重新加载服务器。这可以避免不必要的资源浪费,提高生产环境的性能。

总的来说,use_reloader 配置是一个方便的功能,可以帮助你在开发和调试时更快速地看到代码更改的效果。在生产环境中,你可以设置为 False 以提高性能。

3.wsgi_max_body_size

在 WSGI 模式下,可以使用这一配置来改变服务器可接受的最大请求体大小,默认大小是 16 MB(16 * 1024 * 1024 * BYTES)。

当然,在 ASGI 模式下,这一配置不起作用。

延伸阅读

  1. ASGI — Flask Documentation (2.2.x):https://flask.palletsprojects.com/en/2.2.x/deploying/asgi/

  2. 2020你的工具箱里该出现ASGI了——ASGI介绍:https://zhuanlan.zhihu.com/p/102325052

  3. Configuring — Hypercorn 0.14.3+dev documentation:https://hypercorn.readthedocs.io/en/latest/how_to_guides/configuring.html

  4. HTTP to HTTPS Redirects — Hypercorn 0.14.3+dev documentation:https://hypercorn.readthedocs.io/en/latest/how_to_guides/http_https_redirect.html

  5. Logging — Hypercorn 0.14.3+dev documentation:https://hypercorn.readthedocs.io/en/latest/how_to_guides/logging.html

资源下载: