如何实现域名访问服务器上 Django 搭建的 API 项目?

最近的目标是用 Python 来搭建一个可访问的热门网站热榜数据 API,目前已经实现了:

  1. 本地用 Django 搭建知乎热榜 API
  2. 将本地的 Django 项目部署到云服务器上,实现了通过 ip 获取 API 数据

本篇是最后一步,要完善 API 数据的抓取和通过域名可以拿到 API 数据。要实现此目的:

  • 首先要用 nginx + uWSGI 来设置服务器上的 Django 项目和 Web 服务器
  • 注册域名,域名解析,域名备案,使得域名可以访问到该服务器
  • 服务器上的爬虫代码通过定时任务来执行

环境:本地电脑时 macOS 系统;云服务器是 CentOS 7; Django 是 Python 3.7.5

nginx + uWSGI + Django

uWSGI 概念及配置

一个web服务器面对的是外部世界。它能直接从文件系统提供文件 (HTML, 图像, CSS等等)。然而,它无法 直接与Django应用通信;它需要借助一些工具的帮助,这些东西会运行运用,接收来自web客户端(例如浏览器)的请求,然后返回响应。

一个Web服务器网关接口(Web Server Gateway Interface) - WSGI - 就是干这活的。 WSGI 是一种Python标准。

uWSGI是一种WSGI实现。在这个教程中,我们将设置uWSGI,让它创建一个Unix socket,并且通过WSGI协议提供响应到web服务器。最后,我们完整的组件栈看起来将是这样的:
the web client <-> the web server <-> the socket <-> uwsgi <-> Django

以上关于 uWSGI 的概念来自于 uWSGI 相关的文档,我们暂且理解为 uWSGI 是用来将 Django 项目与 socket 通讯的中介。我们主要来实现相关的安装部署。

基于之前实现的将 Django 项目部署到了服务器上,我们连到服务器,虚拟环境下进入自己的项目目录:

sudo ssh 175.24.134.227
# 输入密码连接到服务器
[root@VM_0_11_centos ~]# cd tedxapi/
[root@VM_0_11_centos tedxapi]# ls
myapi  myvenv
[root@VM_0_11_centos tedxapi]# source myvenv/bin/activate
(myvenv) [root@VM_0_11_centos tedxapi]# cd myapi/

在虚拟环境中安装 uWSGI:

(myvenv) [root@VM_0_11_centos myapi]# pip install uwsgi

配置 myapi_uwsgi.ini 文件:

之前我们运行 Django 项目是靠 manage.py 的 runserver 命令,配置了 uwsgi 之后,就要通过 uwsgi 来运行 Django 项目了。因为要启动项目时需要配置些参数,为了方便将参数定义在 ini 格式的文件中。保持终端路径不变,执行以下命令新建 myapi_uwsgi.ini 文件并配置相关参数。

(myvenv) [root@VM_0_11_centos myapi]# vim myapi_uwsgi.ini

执行完上面这个 vim 命令后,终端会进入该文件的编辑界面,这时按下字母 i 键进入插入模式,就可以在文件中编辑内容了,复制如下配置贴到文件中,部分数据要根据不同项目做调整:

# myapi_uwsgi.ini file
[uwsgi]

# Django-related settings
http			=:8000

# the base directory (full path)
chdir           = /root/tedxapi/myapi

# Django s wsgi file
module          = myapi.wsgi

# the virtualenv full path
home            = /root/tedxapi/myvenv

# process-related settings
# master
master          = true

# maximum number of worker processes
processes       = 2

# the socket (use the full path to be safe
socket          = /root/tedxapi/myapi/mysite.sock

# ... with appropriate permissions - may be needed
chmod-socket    = 666
# clear environment on exit
vacuum          = true

daemonize       = /root/tedxapi/myapi/uwsgi_myapi.log

safe-pidfile    = /root/tedxapi/myapi/pid_myapi.pid

配置中赋值给 socket 的 mysite.sock 文件是 uwsgi --ini 运行后所配的 socket 位置,之后 nginx 会通过该 sock 文件连接到该 socket 位置。

demonize 对应的 uwsgi_myapi.log 用来记录输出的日志。

safe-pidfile 对应的 pid_myapi.pid 用来记录uwsgi 进程的内存ID,更改 uwsgi 或 Django 更新配置后可以用记录的 ID 重新启动 uwsgi。如果不配置该文件,只能通过将 uwsgi 进程全部杀死再重启。

复制并编辑完上述内容后,先按 Esc 键退出编辑模式,然后输入 :wq 再回车,以保存并退出该 vim 模式。返回到终端命令界面后,可以 ls 指令看到路径下多了个 myapi_uwsgi.ini 文件:

(myvenv) [root@VM_0_11_centos myapi]# ls
db.sqlite3  get_website.py  hotlist  __init__.py  manage.py  myapi  myapi_uwsgi.ini

启动 uwsgi

执行 uwsgi --ini myapi_uwsgi.ini 的命令:

(myvenv) [root@VM_0_11_centos myapi]# uwsgi --ini myapi_uwsgi.ini 
[uWSGI] getting INI configuration from myapi_uwsgi.ini
(myvenv) [root@VM_0_11_centos myapi]# ls
db.sqlite3      hotlist      manage.py  myapi_uwsgi.ini  pid_myapi.pid
get_website.py  __init__.py  myapi      mysite.sock      uwsgi_myapi.log

可以看到刚提过的 mysite.sock、myapi.log 及 myapi.pid 等文件也都出现在了路径内。

配置 uwsgi_params 文件

该文件会在 nginx 配置时用到,我们可以通过 https://github.com/nginx/nginx/blob/master/conf/uwsgi_params
下载后上传至服务器,当然更简便的方式是用 vim 指令新建并编辑其中内容:

(myvenv) [root@VM_0_11_centos myapi]# vim uwsgi_params

在弹出的 vim 编辑区内,先按 i 键进入插入模式,将下列内容复制粘贴:


uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

第一行是空着的,不知道去掉会不会影响,但先保持和 GitHub 上的这种一致吧。

编辑完毕,按 Esc,输入 :wq 保存并退出 vim 编辑模式,可以看到路径内多了 uwsgi_params 文件:

(myvenv) [root@VM_0_11_centos myapi]# ls
db.sqlite3      hotlist      manage.py  myapi_uwsgi.ini  pid_myapi.pid    uwsgi_params
get_website.py  __init__.py  myapi      mysite.sock      uwsgi_myapi.log

uwsgi 大致完成,接下来我们来看 nginx~

nginx 概念及配置

nginx概念

nginx (发音为 engine-x) 是一个免费开源并且高性能的HTTP服务器和反向代理,还是一个IMAP/POP3代理服务器。
the web client <-> the web server

nginx 安装

通过 yum install 命令可以直接安装:

(myvenv) [root@VM_0_11_centos myapi]# yum install nginx

中途会提示 "Is this ok [y/d/N]: " 直接输入 y 回车即可。

配置 myapi_nginx.conf

类似 myapi_uwsgi.ini,我们也是 vim 来建立编辑 myapi_nginx.conf 文件:

# myapi_nginx.conf

# the upstream component nginx needs to connect to
upstream djangomyapi {
    server unix:///root/tedxapi/myapi/mysite.sock;
}

# configuration of the server
server {
    # the port site will be served on
    listen     8000;

    # the domain name it will serve for
    server_name 175.24.134.227;

    charset     utf-8;

    access_log /root/tedxapi/myapi/logs/access.log;
    error_log /root/tedxapi/myapi/logs/error.log;

    # max upload size
    client_max_body_size 75M;
    
    location /static {
        alias /root/tedxapi/myapi/static; # your Django project's static files - amend as required
    }
    
    location / {
        uwsgi_pass djangomyapi; # 127.0.0.1:8002;
        include /root/tedxapi/myapi/uwsgi_params;
    }
}

注意 upstream djangomyapi 中 server unix: 后确实是三个斜杠,不能删减,后面指向的就是之前提到过的 mysite.sock 文件。完成编辑后保存退出该文件。

将这个文件链接到/etc/nginx/sites-enabled,这样nginx就可以看到它了,由于 我们环境中 /etc/nginx/下没有 sites-enabled 文件夹,我们先新建该文件夹,然后建立该配置文件的软连接过去:

(myvenv) [root@VM_0_11_centos static]# cd /etc/nginx/
(myvenv) [root@VM_0_11_centos nginx]# mkdir sites-enabled
(myvenv) [root@VM_0_11_centos nginx]# sudo ln -s /root/tedxapi/myapi/myapi_nginx.conf /etc/nginx/sites-enabled/

启动 nginx

启动之前,我们先部署下静态文件:

(myvenv) [root@VM_0_11_centos myapi]# python manage.py collectstatic

可以通过 whereis nginx 查看 nginx 路径,当然如果你和我基本保持一致,使用 /usr/sbin/nginx 命令直接启动:

(myvenv) [root@VM_0_11_centos myapi]# /usr/sbin/nginx

由于我们之前启动过 uwsgi,可以先杀死所有 uwsgi 进程,然后再重新启动 uwsgi:

(myvenv) [root@VM_0_11_centos nginx]# pkill -f uwsgi -9
(myvenv) [root@VM_0_11_centos myapi]# uwsgi --ini myapi_uwsgi.ini 
[uWSGI] getting INI configuration from myapi_uwsgi.ini

然后访问 http://175.24.134.227:8000/ 即可显示 API 数据:
如何实现域名访问服务器上 Django 搭建的 API 项目?_第1张图片
点击其中的 http://175.24.134.227:8000/website/ 链接,结果如图:

如何实现域名访问服务器上 Django 搭建的 API 项目?_第2张图片
至此,通过 nginx + uwsgi 运行 Django 项目成功实现。

此外,附上我搜集到的常用、可用的 uwsgi 和 nginx 命令:

查看 nginx 进程:
ps -ef | grep nginx
从容停止   kill -QUIT 主进程号
快速停止   kill -TERM 主进程号
强制停止   kill -9 nginx


查看 uwsgi 进程:
ps aux | grep uwsgi
杀死全部 uwsgi 进程命令:
pkill -f uwsgi -9


初始化 uwsgi 命令:
uwsgi --ini myapi_uwsgi.ini
加了 safe-pidfile 后,以后可以这样重启: 
uwsgi --reload pid_myapi.pid

启动 nginx:
/usr/sbin/nginx

域名

由于注册到备案完成周期较长,我新注册的域名暂时未进行域名解析和备案,而已完成备案的域名没有做整理记录,故此部分从简。

注册域名

一般是在阿里云或腾讯云购买域名,例如我在阿里云买的 www.tedxpy.com 在腾讯云购置的 www.tedxmy.co

域名解析

除了需要认证,域名解析会将域名与服务器 ip 绑定

备案

此外,域名还需要备案,这个在腾讯云或阿里云都可以指引完成,时间也因地区而异。最终完成后即可通过域名取代服务器 ip 来实现域名访问了。

https

因为最终目的是拿该 API 接口给微信小程序开发使用,故要使用 https 来展现。

之前朋友推荐我用此链接中的方法去配置 https,但我最初尝试没能成功,估计和我最初把 Python2 软连接给改掉有关系,这个之后待验证。

我是通过阿里云免费证书完成了对 https 的配置。

首先在阿里云购买免费的云盾证书,然后按照此链接指引下载证书 .key 和 .pem 文件

与链接中不同的是,我将证书文件上传至了服务器的 /etc/nginx/cert/ 文件夹,因为 /etc/nginx 本身没有 cert 目录,故先在其中新建 cert 文件夹,然后本地直接通过 sftp 连接将 .key 和 .pem 上传至 /etc/nginx/cert/ 文件夹内。

同时由于已经拥有可用的域名 www.tedxpy.com 与服务器 ip 绑定,要将 myapi_nginx.conf 文件中的参数做修改:

# myapi_nginx.conf

# the upstream component nginx needs to connect to
upstream djangomyapi {
    server unix:///root/tedxapi/myapi/mysite.sock;

}

# configuration of the server
server {
    # the port site will be served on
    #listen     8000;
    listen      443 ssl;
    # the domain name it will serve for
    server_name www.tedxpy.com;
    
    ssl_certificate /etc/nginx/cert/3188816_www.tedxpy.com.pem;
    ssl_certificate_key /etc/nginx/cert/3188816_www.tedxpy.com.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    charset     utf-8;

    access_log /root/tedxapi/myapi/logs/access.log;
    error_log /root/tedxapi/myapi/logs/error.log;

    # max upload size
    client_max_body_size 75M;

    location /static {
        alias /root/tedxapi/myapi/static;
    }

    location / {
        uwsgi_pass djangomyapi; # 127.0.0.1:8002;
        include /root/tedxapi/myapi/uwsgi_params;
    }
}

由于升级 https,listen 8000 改为了 443 ssl;同时 server_name 也由 ip 改成了域名;同时配置了一系列 ssl 相关的参数,其中 ssl_certificate 对应的是新配置的证书.pem 文件,ssl_certificate_key 对应的是新配置的证书 .key 文件。

至于 myapi_uwsgi.ini 文件中:

# myapi_uwsgi.ini file
[uwsgi]

# Django-related settings
# the base directory (full path)
chdir           = /root/tedxapi/myapi

# Django s wsgi file
module          = myapi.wsgi

# the virtualenv full path
home            = /root/tedxapi/myvenv

# process-related settings
# master
master          = true

# maximum number of worker processes
processes       = 2

# the socket (use the full path to be safe
socket          = /root/tedxapi/myapi/mysite.sock

# ... with appropriate permissions - may be needed
chmod-socket    = 666
# clear environment on exit
vacuum          = true

daemonize       = /root/tedxapi/myapi/uwsgi_myapi.log

safe-pidfile    = /root/tedxapi/myapi/pid_myapi.pid

将之前配置的 http=:8000 去掉,无需使用端口了。

完成配置后重新运行 nginx 和 uwsgi,即可通过域名来访问 Django 项目了~

展示

我所实现的成果是:

https://www.tedxpy.com/

如何实现域名访问服务器上 Django 搭建的 API 项目?_第3张图片

https://www.tedxpy.com/weibo/

如何实现域名访问服务器上 Django 搭建的 API 项目?_第4张图片
至此,整个 Django RESTFramework API 项目在服务器上部署展现的功能就实现了。

为了实现爬取的热榜数据按时更新,我还在服务器上通过 crontab 定时任务来执行爬虫取数据的代码,后续再整理文章更新~

以上,感谢阅读~

最后,也向你推荐我的微信公众号 TEDxPY,内容涉及 Python、小程序等,来找我哦~

如何实现域名访问服务器上 Django 搭建的 API 项目?_第5张图片

你可能感兴趣的:(python资源,python学习)