Better Call Timmy!

20240108-WSGI and Static Files

字数统计: 2.3k阅读时长: 9 min
2024/01/08

Web 和 Django 开发中的一些笔记总结。
Summary of Some Knowledge in Web and Django Development.

Introduction to WSGI

A Web Server Gatway Interface (WSGI) server implements the web server side of the WSGI interface for running Python web applications.

  • A traditional web server does not understand or have any way to run Python applications. In the late 1990s, a developer named Grisha Trubetskoy came up with an Apache module called mod_python to execute arbitrary Python code.
  • However, this module stalled and security vulnerabilities were discovered. Then, the community realized that a consistent way to execute Python code for web applications was needed.
  • Therefore the Python community came up with WSGI as a standard interface that modules and containers could implement. WSGI is now the accepted approach for running Python web applications.


WSGI’s Purpose and Example

WSGI gives us flexibility: Application developers can swap out(更换)web stack components for others.

  • For example, a developer can switch from Gunicorn to uWSGI without modifying the application or framework that implements WSGI. 换言之,WSGI 规定了统一的接口。我们无需关心网络堆栈组件的具体结构如何,我们只需要根据 WSGI 接口的要求实现我们底层的函数即可。
  • The availability and widespread use of such an API in web servers for Python would separate choice of framework from choice of web server.

WSGI servers promote scaling: WSGI servers handle processing requests from the web server and deciding how to communicate those requests to an application framework’s process. The segregation of responsibilities is important for efficiently scaling web traffic.

  • Serving thousands of requests for dynamic content at once is the domain of WSGI servers, not frameworks. 在我们开发 Django 的时候,因此不需要考虑高并发的情况,我们需要关注的是程序对于内存的应用,以及是否重复创建了某些东西,或内存碎片是否被及时回收。

WSGI is by design a simple standard interface for running Python code.

  • WSGI container is a separate running process that runs on a different port than your web server.
  • A web server’s configuration specifies what requests should be passed to the WSGI server to process. Once a request is processed and generated by the WSGI server, the response is passed back through the web server and onto the browser.

If you’re using a standard web framework such as Django, Flask, or FastAPI, or almost any other current Python framework, you don’t need to worry about how frameworks implement the application side of the WSGI standard. Likewise, if you’re using a standard WSGI container such as Green Unicorn, uWSGI, mod_wsgi, or gevent, you can get them running without worrying about how they implement the WSGI standard.

For exmaple, this Nginx web server’s configuration specifies that Nginx should handle static assets (such as /IMAGES/WEB, JavaScript, and CSS files) under the /static directory and pass all other requests to the WSGI server running on port 8000:

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
32
33
# 指定了一个后端服务器(WSGI服务器)的地址为 localhost:8000。
# 这是 Django 应用程序的 WSGI 服务器的地址和端口。
upstream app_server_djangoapp {
server localhost:8000 fail_timeout=0;
}

# 定义了一个监听端口为 80 的虚拟主机,意味着 Nginx 将监听来自客户端的HTTP请求。
server {
listen 80;

# 当请求的路径是以 /static 开头时,Nginx 将会返回静态文件,
# 这些文件存储在 /srv/www/assets 目录中。
# 这是为了提供静态文件的直接访问,而不必通过 WSGI 服务器。
location /static {
autoindex on;
alias /srv/www/assets;
}

# 当请求路径不是以 /static 开头时,
# Nginx 将会代理请求给上述定义的 app_server_djangoapp。
location / {
# 配置代理头。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off; # 禁用了对代理重定向的处理。

# 如果文件不存在,就代理请求给 app_server_djangoapp,
# 否则,继续处理其他 Nginx 指令。
if (!-f $request_filename) {
proxy_pass http://app_server_djangoapp;
break;
}
}

如果 Django 需要调用静态文件,只需要:

  1. 在 Django 设置中配置静态文件路径;
    1
    2
    3
    4
    # settings.py
    STATIC_URL = '/static/' # 在模板或视图中引用静态文件的基本 URL。
    STATIC_ROOT = '/path/to/your/static/folder/'
    # 静态文件的实际存储路径。
  • 在开发环境中,Django 通常会自动处理静态文件,但在生产环境中,可能需要运行 collectstatic 命令来将静态文件从应用程序复制到 STATIC_ROOT 目录中。
  1. 在 Nginx 配置中指定 Django 的静态文件路径。

About Static Files

本章节主要总结一下对于静态文件的理解。

以我的项目的 STATIC 部分为例:

1
2
3
4
5
STATIC_URL = '/static/'  
STATIC_ROOT = os.path.join(BASE_DIR, 'collect_static')
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
  • STATIC_URL 是静态文件的 URL 前缀,被 Django 用来生成静态文件的 URL。例如,如果 STATIC_URL/static/,那么一个名为 my_app/example.jpg 的静态文件的 URL 就会是 `/static/my_app/example.jpg。
  • STATIC_ROOT 是所有静态文件在 collectstatic 后被复制到的位置。我们可以将前端的 web 服务器指向这个 STATIC_ROOT 文件夹,从而从一个位置提供静态文件
  • STATICFILES_DIRS 是一个包含了 Django 在查找静态文件时需要考虑的额外目录的列表。对于同名文件,Django 会按照 STATICFILES_DIRS 中的顺序来解析这些文件。

在 Django 中,collectstatic 是一个命令行工具,用于将项目中的静态文件(如 CSS、JavaScript、图像等)收集到一个单独的目录,通常称为 STATIC_ROOT。这有助于在生产环境中更有效地提供静态文件,而不需要在每个请求中由 Django 来处理。

collectstatic 过程中,Django 会检查已安装的各个应用中的 static 文件夹,以及 STATICFILES_DIRS 中配置的其他目录,以及 Django 自身的 admin 应用中的 static 文件夹,然后将这些静态文件全部汇总到 STATIC_ROOT 中,以供 Nginx、Apache 或其他静态文件服务器提供给用户浏览器。

为了让在开发环境还是在运行 collectstatic 后的生产环境,使用的一些静态文件都指向正确的位置,我们需要做一些修改,还是以我的代码为例:

1
MODELS_PATH = osp.join(BASE_DIR, 'static', 'models') 

这在开发环境时是没有问题的,但是生产环境时我们需要指向 collect_static 目录下,于是我们这样修改:

1
2
3
4
5
6
from Project_release.settings import BASE_DIR, DEBUG

if DEBUG:
MODELS_PATH = osp.join(BASE_DIR, 'static', 'models')
else:
MODELS_PATH = osp.join(STATIC_ROOT, 'models')

这样,无论是在开发环境还是在生产环境,MODELS_PATH 都会指向正确的路径。


About the Reverse and Forward Proxy Server

正向代理是客户端和其他所有服务器的代理者,而反向代理是客户端和所要代理的服务器之间的代理。

A reverse proxy server is an intermediate connection point positioned at a network’s edge. It receives initial HTTP connection requests, acting like the actual endpoint. A reverse proxy operates by:

  • Receiving a user connection request.
  • Completing a TCP three-way handshake, terminating the initial connection
  • Connecting with the origin server and forwarding the original request

对于反向代理,如果他反向代理了两个服务,那么之后客户端访问这两个服务器的时候,该代理服务器才会给它代理,也就是说,这里的代理服务器只对该代理服务器所代理的服务器负责。

反向代理的主要作用是代理目标服务器向客户端提供服务,通常用于负载均衡、高可用性和安全控制等方面。反向代理需要目标服务器显式地指定代理服务器,否则请求无法被转发。实现方式通常是将代理服务器配置在目标服务器的前面,例如通过负载均衡器将请求分发到多台目标服务器上。客户端发送请求时,请求会先被转发到代理服务器,代理服务器再将请求转发到目标服务器中的一台上。在这个过程中,客户端与代理服务器之间的联系是直接的,而客户端与目标服务器之间的联系则是通过代理服务器来实现的。

In contrast, a forward proxy server is also positioned at your network’s edge, but regulates outbound traffic according to preset policies in shared networks. Additionally, it disguises a client’s IP address and blocks malicious incoming traffic. Forward proxies are typically used internally by large organizations, such as universities and enterprises, to:

  • Block employees from visiting certain websites
  • Monitor employee online activity
  • Block malicious traffic from reaching an origin server
  • Improve the user experience by caching external site content

一般的正向代理,比如翻墙,任何可以连接到该代理服务器的软件,就可以通过代理服务器访问任何的其他服务器,然后把数据返回给客户端,这里代理服务器只对客户端负责。

正向代理的主要作用是代理客户端向目标服务器请求资源,通常用于翻墙、加速访问和隐藏客户端身份等方面。正向代理需要客户端显式地指定代理服务器,否则请求无法被转发。实现方式通常是将代理服务器配置在客户端上,例如通过浏览器的代理设置来指定代理服务器。客户端发送请求时,请求会先被转发到代理服务器,代理服务器再将请求发送到目标服务器。在这个过程中,客户端与目标服务器之间并没有直接的联系,目标服务器只知道请求来自代理服务器,而不知道客户端的真实 IP 地址。

正向代理和反向代理是一个相对的概念。一般在工作中正向代理就是代理的客户端,反向代理就是代理的服务端。

CATALOG
  1. 1. Introduction to WSGI
  2. 2. WSGI’s Purpose and Example
  3. 3. About Static Files
  4. 4. About the Reverse and Forward Proxy Server