• <学习笔记>从零开始自学Python-之-web应用框架Django( 十四)上线部署(阿里云+Nginx+uwsgi+MySQL)


            好了,我们现在有了一个完整的网站,在自己电脑上跑起来没问题了,但是我们做网站肯定不只是为了在本机上自己欣赏,总要放到网上去让别人来浏览。这一章我们就完整跑一遍Django项目的生产环境部署。

    1、基本原理

    想让你的网站在公网上让别人访问,最基本的需要有以下条件:

    1.1服务器

    无论是物理意义上的还是虚拟的都可以,所有程序和数据都要放在这上面

    1.2公网IP

    就是服务器得能上网,一般购买云服务器的话云供应商会提供,如果自建服务器的话,看网络提供商的配置

    1.3域名

    让别人可以通过网址来访问,而不是网络IP,这个要去申请、备案

    网络访问的过程就是别人通过域名经过解析为IP地址来访问你的服务器,实现浏览等功能。

    2、我的配置方案

    2.1 服务器和域名选择

    对个人网站来说,自己搭建物理服务器费钱费力,现在一般都是选择云服务器,我这里选择的是阿里云ECS实例,为什么选阿里云?因为我抢到了9.9三个月的优惠活动。其它什么华为云、百度云等等都可以,它们不时都会推出一些优惠活动,羊毛不薅白不薅。域名我选择的是百度域名,也是因为便宜,9.9抢了个一年域名

    2.2 远程操作工具xshell 和 文件上传工具 xftp  

    因为用了云服务器,就要涉及到远程控制和数据上传的问题,这里就要用到两个工具,xshell和xftp,这两个工具可以去官网申请个人免费版本,非常好用,对新手友好,强力推荐!

    2.3 高并发服务器Nginx 和 uwsgi

    Django自带的服务器仅限于开发调试用,它的并发能力很弱,不能用于生产环境,这里就要用一个专门的服务器工具Nginx。Nginx("engine x")是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。

    Nginx 处理静态网页很优秀,但是处理动态网页就需要另一个工具uwsgi了。Uwsgi本身也是个服务器,它处理动态网页比较高效。

    2.4 数据库

    就选熟悉的MySQL5.7,只要把本地的数据库迁移到网上就行,可以实现线下开发调试,线上发布运行 同步。

    2.5 大致流程

    所以整个网络部署的实际流程就是:

    1. 申请服务器和域名(可以在同一家也可以不同家)
    2. 用xshell连接服务器进行各项远程操作
    3. 安装Python、Django以及各种依赖环境
    4. 安装MySQL,迁移数据库数据
    5. 用xftp把相关文件上传到服务器
    6. 安装Nginx,收集静态文件,配置Nginx文件
    7. 安装uwsgi,和Nginx实现内部通讯
    8. 域名备案,域名解析,最终可以公网网址访问

    3、阿里云服务器选择和端口配置

    阿里云 云服务器ECS实例  1(vCPU) 2 GiB

    申请好以后会给一个公网IP,这个地址保存好,后面要用到

    端口配置:

    点击 配置安全组规则

    点进去,是一个列表,在这里配置端口

    一些默认的端口不要去动它,它们都是有常规功能的

    比如22是给ssh的,80是HTTP即网页访问的,443是给HTTPS的,3306是给MySQL的等等

    快速添加就是这些默认的端口,手动添加可以自定义任意端口

    我们可以自定义几个端口,后面会用到,比如我们设一个8005端口,用于给uwsgi和Nginx的内部通信。再自定义一个1905端口,用来做测试用。注意这里端口范围一定要写成8005/8005 格式,授权对象写 0.0.0.0/0,表示对所有地址开放。

    4、 xshell和xftp

    这两个是同一家公司的产品,官网https://www.xshell.com

    下载网页所有下载 - NetSarang Website

    申请一个个人免费版本,下载安装都没啥说的

    xshell 用于远程连接服务器,实现在自己的电脑上操作服务器的功能。当然服务器一般都是Linux系统,需要熟悉Linux命令。

    xftp 用于上传下载资源,包括上传项目文件、数据库、静态资源等等,是自己本地电脑和服务器实现数据传输的工具。

    4.1 Xshell的使用

    启动软件,新建一个会话

    在主机这里填入从阿里云那里获得的公网IP

    点击左边的用户身份验证

    填入阿里云实例的用户名和密码

    Tips:这里有个小坑,这里默认的用户名是root,我迷惑了很久,以为是实例名

    点击连接,看到的界面:

    现在就可以操作服务器了。当然,它用的是Linux系统,所以还要熟悉一些基本的Linux操作。

    详细的Linux命令可以参见这篇文章

    Linux命令详细总结(万字总结值得一看)_linux命令大全详解_程序员小王java的博客-CSDN博客

      这里记录几个最常用的:

    1. ls
    2. 查询
    3. netstat -ntlp
    4. 查询网络状况
    5. ps aux | grep uwsgi
    6. 查询所有uwsgi进程
    7. nginx -s reload
    8. 重启nginx服务
    9. uwsgi --ini uwsgi.ini
    10. 以uwsgi.ini配置文件启动uwsgi
    11. pkill -f uwsgi -9
    12. 杀死所有uwsgi进程,这个和上面的命令结合就是重启uwsgi

    4.2 xftp的使用

    一样启动软件后,新建连接

    这里端口号填22,一般是给ssh用的,主机填公网IP地址,用户名和密码跟上面xshell一样的

    连接上以后看到下面的界面

     这里左边是自己电脑上的文件夹,右边是服务器的文件目录,这里的上传操作就很简单了,把左边相应文件夹的文件直接拖到右边相应位置就行。(这个操作比Git之类的要简单多了,适合新手)

    tips:这个东西还有个妙用,就是可以直接对右边的文件进行操作,和打开编辑,基本跟Windows下一样,这大大方便了维护,比如右边某个py文件需要修改,我直接在右边这个框里找到该文件,打开修改,然后保存关闭即可。当然还要用xshell 把 nginx 和uwsgi 服务重启一下。

    5、Linux下安装 Python 、Django 及各种依赖

    这里是比较困难的部分,各个系统情况不一样,各个Python和Django的版本不一样,装起来确实挺费劲的,我这里记录一次我成功安装的过程

    5.1 安装Python

    强调一下Linux下不要用anaconda来安装Python,之前习惯了用anaconda来做Python的底座,但是Linux系统下anaconda有很多版本的坑,我装到最后都崩溃了,所以就老老实实手动安装Python吧

    参考文章:linux安装Python3     https://blog.csdn.net/SiShen654/article/details/109077772

    首先找官网也好找镜像也好,先下载一个安装包,我这里用xshell远程连接服务器,直接在服务器下用Linux命令下载:

    wget https://npm.taobao.org/mirrors/python/3.8.6/Python-3.8.6.tar.xz
    

    然后用tar命令进行解压

    1. mkdir -p /mine/python3
    2. -- 在根目录的创建mine文件夹,再到下面创建python3文件夹
    3. -- 你也可以安装到自己想要安装的包下面,但要记得后面的命令有些要改地址
    4. tar xvf Python-3.8.6.tar.xz -C /mine/python3
    5. -- 将文件解压到-C后面的地址(你可以自定义)

    然后进入刚刚解压后的目录执行编译

    1. cd Python-3.8.6
    2. ./configure --prefix=/mine/python3 // 执行配置文件
    3. make && make install // 进行编译安装

    安装完成后可以查看一下

    1. cd /mine/python3
    2. ls
    3. -- 安装成功的话可以看到bin文件夹
    4. cd bin
    5. ls
    6. -- 可以看到运行文件都在这里,接下来创建软连接

     创建软连接,类似与windows创建快捷方式

    1. -s后面接上刚刚查询的地址
    2. ===========创建===========
    3. ln -s /mine/python3/bin/python3.8 /usr/bin/python3
    4. ln -s /mine/python3/bin/pip3.8 /usr/bin/pip
    5. ===========查询===========
    6. ls -l /usr/bin/python*
    7. ls -l /usr/bin/pip*
    8. =====================================================
    9. 如果报错ln: failed to create symbolic link ‘/usr/bin/pip’: File exists
    10. 这里的python3的软连接如果被占用也一样删掉 rm -rf ./python3
    11. 使用下面的命令将python2的pip软连接删除:
    12. cd /usr/bin/
    13. rm -rf ./pip

     tips:在Linux下运行程序和Windows下的一个 不同,你要时刻关注用的是哪个路径下的程序,否则会有很多的坑。后面说uwsgi的时候会说到,不指定路径很容易出各种错

    5.2 安装Django

    有了Python,再安装Django就好办了,可以直接用pip 安装

    pip3 install Django

    当然这个过程也没那么顺利,它可能还要求安装各种环境等等,但是因为有了pip我们只要耐心一点,基本上都能装好,实在pip装不了的,可以yum install安装

    如果你的项目用到了bootstap4的,还要再安装一下

    pip3 install django-bootstrap4

    6、安装并配置Nginx

    参考文章 nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件,很全_java冯坚持的博客-CSDN博客

    6.1 什么是Nginx

    Nginx 是高性能的 HTTP 和反向代理的web服务器,处理高并发能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50,000 个并发连接数。

    其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

    Nginx 可以作为静态页面的 web 服务器,同时还支持 CGI 协议的动态语言,比如 perl、php 等。但是不支持 java。Java 程序只能通过与 tomcat 配合完成。Nginx 专为性能优化而开发, 性能是其最重要的考量,实现上非常注重效率 ,能经受高负载的考验,有报告表明能支持高 达 50,000 个并发连接数。


    6.2 安装Nginx

    6.2.1 到nginx官网下载软件
    http://nginx.org

    先安装其依赖软件,最后安装nginx。
    依赖工具:pcre-8.3.7.tar.gz, openssl-1.0.1t.tar.gz, zlib-1.2.8.tar.gz, nginx-1.11.1.tar.gz。 
    nginx的http模块使用pcre来解析正则表达式,需要在linux上安装pcre库
    nginx使用zlib对http包的内容进行gzip,需要在linux上安装安装zlib库
    安装openssl库,让 nginx 支持 https(即在ssl协议上传输http)

    6.2.2 安装过程

    安装都有两种方式,一种直接下载,第二种使用解压包方式。这里大多使用解压包方式。
    我的安装路径:/usr/feng/
    Mac系统安装请移步到这儿(和Linux安装并无多大区别):Mac os 安装 nginx 教程(success)
    安装pcre
    方式一、wget http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz 。
    方拾二、上传源码压缩包,解压、编译、安装 三部曲。
    1)、解压文件, 进入pcre目录,
    2)、./configure 完成后,
    3)、执行命令: make && make install
    安装 openssl
    下载OpenSSL的地址:
    http://distfiles.macports.org/openssl/
    1)、解压文件, 回到 openssl目录下,
    2)、./configure 完成后,
    3)、执行命令: make && make install
    安装 zlib
    1)、解压文件, 回到 zlib 目录下,
    2)、./configure 完成后,
    3)、执行命令: make && make install
    **安装 nginx **
    1)、解压文件, 回到 nginx 目录下,
    2)、./configure 完成后,
    3)、执行命令: make && make install

    6.2.3. 测试运行nginx

    安装完nginx后,会在 路径 /usr/local 下自动生成 nginx 文件夹。这是自动生成的。
    进入这个目录:
    cd /usr/local/nginx
    目录内容如下:

    在这里插入图片描述
    进入sbin文件夹,里面有两个文件:nginx 和 nginx.old。
    执行命令:./nginx 即可执行
    测试启动: ps -ef | grep nginx

    在这里插入图片描述

    已经启动。

    查看nginx默认端口(默认为80),使用网页的形式测试

    进入目录查看端口:cd /usr/local/nginx/conf 下的 nginx.conf文件。这个文件也是nginx的配置文件。vim 下:

    在这里插入图片描述

    输入IP:80,则显示:

    在这里插入图片描述

    6.3 配置Nginx

    a. 配置文件位置

    /usr/local/nginx/conf/nginx.conf

    在这里插入图片描述

    b. nginx 的组成部分

    配置文件中有很多#, 开头的表示注释内容,我们去掉所有以 # 开头的段落,精简之后的 内容如下:

    1. worker_processes 1;
    2. events {
    3. worker_connections 1024;
    4. }
    5. http {
    6. include mime.types;
    7. default_type application/octet-stream;
    8. sendfile on;
    9. keepalive_timeout 65;
    10. server {
    11. listen 80;
    12. server_name localhost;
    13. location / {
    14. root html;
    15. index index.html index.htm;
    16. }
    17. error_page 500 502 503 504 /50x.html;
    18. location = /50x.html {
    19. root html;
    20. }
    21. }
    22. }

     总结一下,nginx 配置文件有三部分组成
    第一部分:全局块
    从配置文件开始到 events 块之间的内容,主要会设置一些影响nginx 服务器整体运行的配置指令,主要包括配 置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以 及配置文件的引入等。
    比如上面第一行配置的:
     

      worker_processes  1;
    

    这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是 会受到硬件、软件等设备的制约。

    第二部分:events块

    比如上面的配置:

    1. events {
    2. worker_connections 1024;
    3. }

    events 块涉及的指令**主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否 允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。**
    上述例子就表示每个 work process 支持的最大连接数为 1024.
    这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。

    第三部分 http块:
     

    1. http {
    2. include mime.types;
    3. default_type application/octet-stream;
    4. sendfile on;
    5. keepalive_timeout 65;
    6. server {
    7. listen 80;
    8. server_name localhost;
    9. location / {
    10. root html;
    11. index index.html index.htm;
    12. }
    13. error_page 500 502 503 504 /50x.html;
    14. location = /50x.html {
    15. root html;
    16. }
    17. }
    18. }

    这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。

    需要注意的是:http 块也可以包括 http全局块、server 块。

    http全局块
    http全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
    server 块
    这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了 节省互联网服务器硬件成本。
    每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。
    而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。
    全局 server 块
    最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。
    location 块
    一个 server 块可以配置多个 location 块。
    这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称 (也可以是IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。 地址定向、数据缓 存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
     

    6.4 常用命令

    如果不记得自己的Nginx装在哪里了,可以用 find -name nginx 命令找一下

    1. [root@iZuf6ctterqg8fllx4kb9zZ local]# find / -name nginx
    2. /usr/share/doc/nginx
    3. /usr/share/nginx
    4. /usr/share/licenses/nginx
    5. /usr/lib64/nginx
    6. /usr/sbin/nginx #运行
    7. /var/log/nginx
    8. /var/lib/nginx
    9. /etc/nginx #配置
    10. /etc/logrotate.d/nginx

    查看网络服务命令

    1. [root@iZuf6ctterqg8fllx4kb9zZ ~]# netstat -ntlp
    2. Active Internet connections (only servers)
    3. Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
    4. tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1028/sshd
    5. tcp 0 0 0.0.0.0:56185 0.0.0.0:* LISTEN 1037/rpc.statd
    6. tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN -
    7. tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 1854/uwsgi
    8. tcp 0 0 0.0.0.0:43367 0.0.0.0:* LISTEN -
    9. tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN 483/systemd-resolve
    10. tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd
    11. tcp 0 0 0.0.0.0:20048 0.0.0.0:* LISTEN 1036/rpc.mountd
    12. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 736/nginx: master p
    13. tcp6 0 0 :::46743 :::* LISTEN 1037/rpc.statd
    14. tcp6 0 0 :::46111 :::* LISTEN -
    15. tcp6 0 0 :::2049 :::* LISTEN -
    16. tcp6 0 0 :::3306 :::* LISTEN 1219/mysqld
    17. tcp6 0 0 :::5355 :::* LISTEN 483/systemd-resolve
    18. tcp6 0 0 :::111 :::* LISTEN 1/systemd
    19. tcp6 0 0 :::20048 :::* LISTEN 1036/rpc.mountd
    20. tcp6 0 0 :::80 :::* LISTEN 736/nginx: master p

    nginx 常用操作命令,找到所在文件夹以后使用

    1. ./nginx #启动
    2. ./nginx -s start #启动
    3. ./nginx -s stop #停止
    4. ./nginx -s reload #重启

    7、安装并配置uwsgi

    7.1 什么是uwsgi

    WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。这东西是一个Gateway,也就是网关。网关的作用就是在协议之间进行转换。

    WSGI 是作为 Web 服务器与 Web 应用程序或应用框架之间的一种低级别的接口,以提升可移植 Web 应用开发的共同点。WSGI 是基于现存的 CGI 标准而设计的。

    uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

    uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。

    注意WSGI / uwsgi / uWSGI 这三个概念的区分。

    • WSGI是一种通信协议。
    • uwsgi同WSGI一样是一种通信协议。
    • 而uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。

    7.2 安装uwsgi

    有了pip,可以直接用pip命令安装:

    pip install uwsgi

    也可以下载源代码安装

    1. wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
    2. tar zxvf uwsgi-latest.tar.gz
    3. cd uwsgi-latest
    4. make

    7.3 测试uwsgi

    让我们新建一个test.py文件,内容如下:

    1. def application(env, start_response):
    2. start_response('200 OK', [('Content-Type','text/html')])
    3. return [b"Hello World"]

    uWSGI Python 加载器将会搜索的默认函数 application 。

    接下来我们启动 uWSGI 来运行一个 HTTP 服务器,将程序部署在HTTP端口 8005 上:

    uwsgi --http :8005 --wsgi-file test.py
    

    默认情况下,uWSGI 启动一个单一的进程和一个单一的线程。

    你可以用 --processes 选项添加更多的进程,或者使用 --threads 选项添加更多的线程 ,也可以两者同时使用。

    uwsgi --http :8005 --wsgi-file test.py --master --processes 4 --threads 2

    以上命令将会生成 4 个进程, 每个进程有 2 个线程。

    7.4 配置uwsgi

    一个uwsgi的基本配置项目如下:

    1. [uwsgi]
    2. uid=www-data # Ubuntu系统下默认用户名
    3. gid=www-data # Ubuntu系统下默认用户组
    4. project=mysite1 # 项目名
    5. base = /home/user1 # 项目根目录
    6. home = %(base)/Env/%(project) # 设置项目虚拟环境,Docker部署时不需要
    7. chdir=%(base)/%(project) # 设置工作目录
    8. module=%(project).wsgi:application # wsgi文件位置
    9. master=True # 主进程
    10. processes=2 # 同时进行的进程数,一般
    11. # 以下uwsgi与nginx通信手段3选一即可
    12. # 选项1, 使用unix socket与nginx通信,仅限于uwsgi和nginx在同一主机上情形
    13. # Nginx配置中uwsgi_pass应指向同一socket文件
    14. socket=/run/uwsgi/%(project).sock
    15. # 选项2,使用TCP socket与nginx通信
    16. # Nginx配置中uwsgi_pass应指向uWSGI服务器IP和端口
    17. # socket=0.0.0.0:8000 或则 socket=:8000
    18. # 选项3,使用http协议与nginx通信
    19. # Nginx配置中proxy_pass应指向uWSGI服务器一IP和端口
    20. # http=0.0.0.0:8000
    21. # socket权限设置
    22. chown-socket=%(uid):www-data
    23. chmod-socket=664
    24. # 进程文件
    25. pidfile=/tmp/%(project)-master.pid
    26. # 以后台守护进程运行,并将log日志存于temp文件夹。
    27. daemonize=/var/log/uwsgi/%(project).log
    28. # 服务停止时,自动移除unix socket和pid文件
    29. vacuum=True
    30. # 为每个工作进程设置请求数的上限。当处理的请求总数超过这个量,进程回收重启。
    31. max-requests=5000
    32. # 当一个请求花费的时间超过这个时间,那么这个请求都会被丢弃。
    33. harakiri=60
    34. #当一个请求被harakiri杀掉会输出一条日志
    35. harakiri-verbose=true
    36. # uWsgi默认的buffersize为4096,如果请求数据超过这个量会报错。这里设置为64k
    37. buffer-size=65536
    38. # 如果http请求体的大小超过指定的限制,打开http body缓冲,这里为64k
    39. post-buffering=65536
    40. #开启内存使用情况报告
    41. memory-report=true
    42. #设置平滑的重启(直到处理完接收到的请求)的长等待时间(秒)
    43. reload-mercy=10
    44. #设置工作进程使用虚拟内存超过多少MB就回收重启
    45. reload-on-as=1024

    注意:uWSGI和Nginx之间有3种通信方式, unix socket,TCP socket和http。Nginx的配置必须与uwsgi配置保持一致。

    7.5 uwsgi常用Linux命令

    配置uwsgi

    touch uwsgi.ini

    uwsgi守护运行

    uwsgi -d --ini uwsgi.ini

    杀死后台uwsgi进程

    pkill -f uwsgi -9

    查看后台uwsgi进程

    ps aux | grep uwsgi

    8、数据库MySQL的安装和迁移

    8.1 安装

    用xshell远程登录,在Linux下直接去官网下载源程序安装

    wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm

    中间有些小困难克服一下,安装完毕

    1. [root@iZuf6ctterqg8fllx4kb9zZ ~]# rpm -qa | grep mysql
    2. [root@iZuf6ctterqg8fllx4kb9zZ ~]# wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
    3. --2023-03-21 14:23:08-- http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
    4. Resolving dev.mysql.com (dev.mysql.com)... 23.76.83.234, 2600:1417:e800:185::2e31, 2600:1417:e800:189::2e31
    5. Connecting to dev.mysql.com (dev.mysql.com)|23.76.83.234|:80... connected.
    6. HTTP request sent, awaiting response... 301 Moved Permanently
    7. Location: https://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm [following]
    8. --2023-03-21 14:23:08-- https://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
    9. Connecting to dev.mysql.com (dev.mysql.com)|23.76.83.234|:443... connected.
    10. HTTP request sent, awaiting response... 302 Moved Temporarily
    11. Location: https://repo.mysql.com//mysql57-community-release-el7-10.noarch.rpm [following]
    12. --2023-03-21 14:23:09-- https://repo.mysql.com//mysql57-community-release-el7-10.noarch.rpm
    13. Resolving repo.mysql.com (repo.mysql.com)... 23.209.108.229
    14. Connecting to repo.mysql.com (repo.mysql.com)|23.209.108.229|:443... connected.
    15. HTTP request sent, awaiting response... 200 OK
    16. Length: 25548 (25K) [application/x-redhat-package-manager]
    17. Saving to: ‘mysql57-community-release-el7-10.noarch.rpm’
    18. mysql57-community-release-el7-10.noarch.rpm 100%[=========================================================================================>] 24.95K --.-KB/s in 0s
    19. 2023-03-21 14:23:09 (364 MB/s) - ‘mysql57-community-release-el7-10.noarch.rpm’ saved [25548/25548]
    20. [root@iZuf6ctterqg8fllx4kb9zZ ~]# yum -y install mysql57-community-release-el7-10.noarch.rpm
    21. Last metadata expiration check: 3:04:46 ago on Tue 21 Mar 2023 11:20:02 AM CST.
    22. Dependencies resolved.
    23. ==============================================================================================================================================================================
    24. Package Architecture Version Repository Size
    25. ==============================================================================================================================================================================
    26. Installing:
    27. mysql57-community-release noarch el7-10 @commandline 25 k
    28. Transaction Summary
    29. ==============================================================================================================================================================================
    30. Install 1 Package
    31. Total size: 25 k
    32. Installed size: 30 k
    33. Downloading Packages:
    34. Running transaction check
    35. Transaction check succeeded.
    36. Running transaction test
    37. Transaction test succeeded.
    38. Running transaction
    39. Preparing : 1/1
    40. Installing : mysql57-community-release-el7-10.noarch 1/1
    41. Verifying : mysql57-community-release-el7-10.noarch 1/1
    42. Installed:
    43. mysql57-community-release-el7-10.noarch
    44. Complete!
    45. [root@iZuf6ctterqg8fllx4kb9zZ ~]# yum -y install mysql-community-server
    46. Last metadata expiration check: 0:00:15 ago on Tue 21 Mar 2023 02:24:59 PM CST.
    47. Dependencies resolved.
    48. ==============================================================================================================================================================================
    49. Package Architecture Version Repository Size
    50. ==============================================================================================================================================================================
    51. Installing:
    52. mysql-community-server x86_64 5.7.41-1.el7 mysql57-community 178 M
    53. Installing dependencies:
    54. libaio x86_64 0.3.112-1.2.al8 alinux3-os 33 k
    55. mysql-community-client x86_64 5.7.41-1.el7 mysql57-community 28 M
    56. mysql-community-common x86_64 5.7.41-1.el7 mysql57-community 311 k
    57. mysql-community-libs x86_64 5.7.41-1.el7 mysql57-community 2.6 M
    58. Transaction Summary
    59. ==============================================================================================================================================================================
    60. Install 5 Packages
    61. Total download size: 209 M
    62. Installed size: 895 M
    63. Downloading Packages:
    64. (1/5): libaio-0.3.112-1.2.al8.x86_64.rpm 241 kB/s | 33 kB 00:00
    65. (2/5): mysql-community-common-5.7.41-1.el7.x86_64.rpm 182 kB/s | 311 kB 00:01
    66. (3/5): mysql-community-libs-5.7.41-1.el7.x86_64.rpm 239 kB/s | 2.6 MB 00:11
    67. (4/5): mysql-community-client-5.7.41-1.el7.x86_64.rpm 816 kB/s | 28 MB 00:35
    68. (5/5): mysql-community-server-5.7.41-1.el7.x86_64.rpm 87 kB/s | 178 MB 35:01
    69. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    70. Total 102 kB/s | 209 MB 35:02
    71. MySQL 5.7 Community Server 27 MB/s | 27 kB 00:00
    72. Importing GPG key 0x5072E1F5:
    73. Userid : "MySQL Release Engineering "
    74. Fingerprint: A4A9 4068 76FC BD3C 4567 70C8 8C71 8D3B 5072 E1F5
    75. From : /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    76. Key imported successfully
    77. Import of key(s) didn't help, wrong key(s)?
    78. Public key for mysql-community-client-5.7.41-1.el7.x86_64.rpm is not installed. Failing package is: mysql-community-client-5.7.41-1.el7.x86_64
    79. GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    80. Public key for mysql-community-common-5.7.41-1.el7.x86_64.rpm is not installed. Failing package is: mysql-community-common-5.7.41-1.el7.x86_64
    81. GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    82. Public key for mysql-community-libs-5.7.41-1.el7.x86_64.rpm is not installed. Failing package is: mysql-community-libs-5.7.41-1.el7.x86_64
    83. GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    84. Public key for mysql-community-server-5.7.41-1.el7.x86_64.rpm is not installed. Failing package is: mysql-community-server-5.7.41-1.el7.x86_64
    85. GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    86. The downloaded packages were saved in cache until the next successful transaction.
    87. You can remove cached packages by executing 'yum clean packages'.
    88. Error: GPG check FAILED
    89. [root@iZuf6ctterqg8fllx4kb9zZ ~]# yum -y install mysql-community-server
    90. Last metadata expiration check: 0:40:23 ago on Tue 21 Mar 2023 02:24:59 PM CST.
    91. Dependencies resolved.
    92. ==============================================================================================================================================================================
    93. Package Architecture Version Repository Size
    94. ==============================================================================================================================================================================
    95. Installing:
    96. mysql-community-server x86_64 5.7.41-1.el7 mysql57-community 178 M
    97. Installing dependencies:
    98. libaio x86_64 0.3.112-1.2.al8 alinux3-os 33 k
    99. mysql-community-client x86_64 5.7.41-1.el7 mysql57-community 28 M
    100. mysql-community-common x86_64 5.7.41-1.el7 mysql57-community 311 k
    101. mysql-community-libs x86_64 5.7.41-1.el7 mysql57-community 2.6 M
    102. Transaction Summary
    103. ==============================================================================================================================================================================
    104. Install 5 Packages
    105. Total size: 209 M
    106. Installed size: 895 M
    107. Downloading Packages:
    108. [SKIPPED] libaio-0.3.112-1.2.al8.x86_64.rpm: Already downloaded
    109. [SKIPPED] mysql-community-client-5.7.41-1.el7.x86_64.rpm: Already downloaded
    110. [SKIPPED] mysql-community-common-5.7.41-1.el7.x86_64.rpm: Already downloaded
    111. [SKIPPED] mysql-community-libs-5.7.41-1.el7.x86_64.rpm: Already downloaded
    112. [SKIPPED] mysql-community-server-5.7.41-1.el7.x86_64.rpm: Already downloaded
    113. MySQL 5.7 Community Server 27 MB/s | 27 kB 00:00
    114. GPG key at file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql (0x5072E1F5) is already installed
    115. The GPG keys listed for the "MySQL 5.7 Community Server" repository are already installed but they are not correct for this package.
    116. Check that the correct key URLs are configured for this repository.. Failing package is: mysql-community-client-5.7.41-1.el7.x86_64
    117. GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    118. Public key for mysql-community-common-5.7.41-1.el7.x86_64.rpm is not installed. Failing package is: mysql-community-common-5.7.41-1.el7.x86_64
    119. GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    120. Public key for mysql-community-libs-5.7.41-1.el7.x86_64.rpm is not installed. Failing package is: mysql-community-libs-5.7.41-1.el7.x86_64
    121. GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    122. Public key for mysql-community-server-5.7.41-1.el7.x86_64.rpm is not installed. Failing package is: mysql-community-server-5.7.41-1.el7.x86_64
    123. GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    124. The downloaded packages were saved in cache until the next successful transaction.
    125. You can remove cached packages by executing 'yum clean packages'.
    126. Error: GPG check FAILED
    127. [root@iZuf6ctterqg8fllx4kb9zZ ~]# rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
    128. [root@iZuf6ctterqg8fllx4kb9zZ ~]# yum -y install mysql-community-server
    129. Last metadata expiration check: 0:41:35 ago on Tue 21 Mar 2023 02:24:59 PM CST.
    130. Dependencies resolved.
    131. ==============================================================================================================================================================================
    132. Package Architecture Version Repository Size
    133. ==============================================================================================================================================================================
    134. Installing:
    135. mysql-community-server x86_64 5.7.41-1.el7 mysql57-community 178 M
    136. Installing dependencies:
    137. libaio x86_64 0.3.112-1.2.al8 alinux3-os 33 k
    138. mysql-community-client x86_64 5.7.41-1.el7 mysql57-community 28 M
    139. mysql-community-common x86_64 5.7.41-1.el7 mysql57-community 311 k
    140. mysql-community-libs x86_64 5.7.41-1.el7 mysql57-community 2.6 M
    141. Transaction Summary
    142. ==============================================================================================================================================================================
    143. Install 5 Packages
    144. Total size: 209 M
    145. Installed size: 895 M
    146. Downloading Packages:
    147. [SKIPPED] libaio-0.3.112-1.2.al8.x86_64.rpm: Already downloaded
    148. [SKIPPED] mysql-community-client-5.7.41-1.el7.x86_64.rpm: Already downloaded
    149. [SKIPPED] mysql-community-common-5.7.41-1.el7.x86_64.rpm: Already downloaded
    150. [SKIPPED] mysql-community-libs-5.7.41-1.el7.x86_64.rpm: Already downloaded
    151. [SKIPPED] mysql-community-server-5.7.41-1.el7.x86_64.rpm: Already downloaded
    152. Running transaction check
    153. Transaction check succeeded.
    154. Running transaction test
    155. Transaction test succeeded.
    156. Running transaction
    157. Preparing : 1/1
    158. Installing : mysql-community-common-5.7.41-1.el7.x86_64 1/5
    159. Installing : mysql-community-libs-5.7.41-1.el7.x86_64 2/5
    160. Running scriptlet: mysql-community-libs-5.7.41-1.el7.x86_64 2/5
    161. Installing : mysql-community-client-5.7.41-1.el7.x86_64 3/5
    162. Installing : libaio-0.3.112-1.2.al8.x86_64 4/5
    163. Running scriptlet: mysql-community-server-5.7.41-1.el7.x86_64 5/5
    164. Installing : mysql-community-server-5.7.41-1.el7.x86_64 5/5
    165. Running scriptlet: mysql-community-server-5.7.41-1.el7.x86_64 5/5
    166. [/usr/lib/tmpfiles.d/mysql.conf:23] Line references path below legacy directory /var/run/, updating /var/run/mysqld → /run/mysqld; please update the tmpfiles.d/ drop-in file accordingly.
    167. Verifying : libaio-0.3.112-1.2.al8.x86_64 1/5
    168. Verifying : mysql-community-client-5.7.41-1.el7.x86_64 2/5
    169. Verifying : mysql-community-common-5.7.41-1.el7.x86_64 3/5
    170. Verifying : mysql-community-libs-5.7.41-1.el7.x86_64 4/5
    171. Verifying : mysql-community-server-5.7.41-1.el7.x86_64 5/5
    172. Installed:
    173. libaio-0.3.112-1.2.al8.x86_64 mysql-community-client-5.7.41-1.el7.x86_64 mysql-community-common-5.7.41-1.el7.x86_64 mysql-community-libs-5.7.41-1.el7.x86_64
    174. mysql-community-server-5.7.41-1.el7.x86_64
    175. Complete!

    然后启动MySQL服务器并查看服务器状态

    1. [root@iZuf6ctterqg8fllx4kb9zZ ~]# systemctl status mysqld.service
    2. ● mysqld.service - MySQL Server
    3. Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: enabled)
    4. Active: inactive (dead)
    5. Docs: man:mysqld(8)
    6. http://dev.mysql.com/doc/refman/en/using-systemd.html
    7. [root@iZuf6ctterqg8fllx4kb9zZ ~]# systemctl start mysqld.service
    8. [root@iZuf6ctterqg8fllx4kb9zZ ~]# netstat -ntlp | grep mysql
    9. tcp6 0 0 :::3306 :::* LISTEN 23116/mysqld

    从mysqld.log文件查看随机生成的初始密码,用root账户登录并修改密码:

    1. [root@iZuf6ctterqg8fllx4kb9zZ ~]# grep "password" /var/log/mysqld.log
    2. 2023-03-21T07:08:02.255989Z 1 [Note] A temporary password is generated for root@localhost: .TyFH/#8aot0
    3. [root@iZuf6ctterqg8fllx4kb9zZ ~]# mysqladmin -u root -h 127.0.0.1 -p password
    4. Enter password:
    5. New password:
    6. Confirm new password:
    7. Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
    8. mysqladmin: unable to change password; error: 'Your password does not satisfy the current policy requirements'

    发现输入密码太简单,系统不接受,查了一下,要求8位以上字母有大小写,于是重新输入:

    1. [root@iZuf6ctterqg8fllx4kb9zZ ~]# mysqladmin -u root -h 127.0.0.1 -p password
    2. Enter password:
    3. New password:
    4. Confirm new password:
    5. Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
    6. mysqladmin: [Warning] Using a password on the command line interface can be insecure.
    7. Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
    8. [root@iZuf6ctterqg8fllx4kb9zZ ~]# mysql -u root -p
    9. Enter password:
    10. Welcome to the MySQL monitor. Commands end with ; or \g.
    11. Your MySQL connection id is 8
    12. Server version: 5.7.41 MySQL Community Server (GPL)
    13. Copyright (c) 2000, 2023, Oracle and/or its affiliates.
    14. Oracle is a registered trademark of Oracle Corporation and/or its
    15. affiliates. Other names may be trademarks of their respective
    16. owners.
    17. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    18. mysql> show databases;
    19. +--------------------+
    20. | Database |
    21. +--------------------+
    22. | information_schema |
    23. | mysql |
    24. | performance_schema |
    25. | sys |
    26. +--------------------+
    27. 4 rows in set (0.00 sec)
    28. mysql>

    8.2 数据迁移

    如果我们想把本地已经跑的数据放到服务器上,或者本地版本做了修改以后让服务器上数据同步,那就要用到数据迁移,步骤如下:

    A)使用mysqldump指令将数据库表/数据保存成xx.sql文件存到本地,

    1. #导出数据到/root/目录下
    2. # 导出所有数据库的表结构和数据
    3. mysqldump -uroot -p123456 --all-databases > /root/alldata.sql
    4. # 导出指定数据库(user)的所有表结构和数据
    5. mysqldump -uroot -p123456 user > /root/user.sql
    6. # 导出指定数据库(user)的所有表结构(不包含数据)
    7. mysqldump -uroot -p123456 -d user > /root/user.sql
    8. # 导出指定数据库(user)某一张表(socre)的结构
    9. mysqldump -uroot -p123456 -d user score > /root/userscore.sql
    10. # 导出指定数据库(user)某一张表(score)的结构和数据
    11. mysqldump -uroot -p123456 user score > /root/userscoredata.sql

    B)上传导出的.sql文件到服务器

     这里,我们可以通xftp直接拉过去,比那些上传的方法方便多了

    C)  在服务器执行.sql文件完成数据迁移

    1. # 登录mysql
    2. mysql -uroot -p 
    3. 输入密码
    4. # 新建迁移保存的数据库,要和准备迁移的数据库同名
    5. mysql > create database user;
    6. mysql > use user;
    7. # 执行.sql文件
    8. mysql > source /root/user.sql;

    9、配置uwsgi+Nginx+Django

    好了,到现在为止,我们才算是做好了所有准备工作,开始真正地来部署上线了。

    9.1  更改Django中的配置

    修改setting.py

    打开你的项目文件夹中项目同名文件夹中的setting.py文件,修改其中设置:     

    1. DEBUG = False #防止攻击者根据DEBUG信息攻击你的项目
    2. ALLOWED_HOSTS = ['*'] #允许所有端口访问项目

    在文件末尾添加

    STATIC_ROOT= '/home/mylog/static/'  #你的静态文件存放的文件夹

    9.2 安装虚拟环境

    线上程序最好是跑在一个虚拟环境中,这样可以隔离不同的项目

    用xshell远程登录,在Linux下用以下命令安装虚拟环境

    1. #如果以root用户登录的话可以不用加 sudo
    2. sudo pip install virtualenv
    3. sudo pip install virtualenvwrapper

    如果提示找不到mkvirtualenv命令,则还要配置环境变量

    1. #1.创建目录用来存放虚拟环境
    2. mkdir $HOME/.virtualenvs
    3. #2.打开~/.bashrc文件,添加两行代码
    4. export WORKON_HOME=$HOME/.virtualenvs
    5. source /usr/local/bin/virtualenvwrapper.sh
    6. #如果还是提示找不到mkvirtualenv命令,可能是virtualenvwrapper.sh文件路径不对,用which找出路径
    7. #which virtualenvwrapper.sh
    8. #用找出的路径替换source /usr/local/bin/virtualenvwrapper.sh中的路径
    9. #3.运行
    10. source ~/.bashrc

    创建虚拟环境

    1. mkvirtualenv 虚拟环境名称
    2. #例:mkvirtualenv myweb

    查看虚拟环境

    workon

    使用虚拟环境

    1. workon 虚拟环境名称
    2. #例:workon myweb

    退出虚拟环境

    deactivate
    

    删除虚拟环境

    1. rmvirtualenv 虚拟环境名称
    2. #例:rmvirtualenv myweb
    3. #删除正在运行的虚拟环境,需要先退出,再删除
    4. #即,先deactivate,再rmvirtualenv myweb

    用conda方法的操作

    1. #创建一个python版本是3.6的虚拟环境
    2. conda create -n 虚拟环境名称 python=3.6
    3. #激活虚拟环境
    4. conda activate 虚拟环境名称
    5. #查看已安装的虚拟环境
    6. conda info --envs
    7. #退出虚拟环境
    8. deactivate 虚拟环境名称

    9.3 部署

    a) 用xshell连接到服务器,在/home/virtualenv 文件夹下创建一个虚拟环境,比如我的项目名称叫basketball,

    mkvirtualenv basketball

    然后切换到虚拟环境的目录

    workon basketball

    b) 用xftp把项目文件上传到 /home/virtualenv/basketball 目录下

    c) 修改Nginx配置

    Nginx的配置文件在  /etc/nginx  文件夹下,这里主要修改server这里涉及uwsgi的一些配置

    1. server {
    2. listen 80; #这里默认是80,最好别改,80端口是给http用的,不用这个端口网址解析不了,只能公网访问
    3. listen [::]:80;
    4. server_name 47.100.184.223; #这里是从阿里云申请的公网IP
    5. error_log /home/virtualenvs/basketball/logs/nginx_error.log; #报错日志,可以随便改
    6. # Load configuration files for the default server block.
    7. include /etc/nginx/default.d/*.conf;
    8. location / {
    9. include /etc/nginx/uwsgi_params;
    10. uwsgi_pass 127.0.0.1:8005; #这里是和uwsgi通信的内部地址,要和uwsgi.ini的配置里面一致,否则无法实现通信
    11. uwsgi_param UWSGI_SCRIPT BasketballManager.wsgi;
    12. uwsgi_param UWSGI_CHDIR /home/virtualenvs/basketball/BasketballManager;
    13. index index.html index.htm;
    14. client_max_body_size 4096m;
    15. }
    16. location /static {
    17. alias /home/virtualenvs/basketball/BasketballManager/static;
    18. }
    19. error_page 404 /404.html;
    20. location = /40x.html {
    21. }
    22. error_page 500 502 503 504 /50x.html;
    23. location = /50x.html {
    24. }
    25. }

    d) 修改uwsgi配置

    uwsgi.ini文件一般放在虚拟目录下,你也可以指定位置和文件名,但是启动调用的时候也要指定路径,我这里是在指定目录下新建了一个uwsgi_basket.ini配置文件

    /home/virtualenvs/basketball/BasketballManager/uwsgi_basket.ini

    这里最主要修改的就是网络配置,上面说过,uwsgi 和 nginx 有三种方式可以通信,因为我的uwsgi和nginx都装在同一个服务器上,所以用socket比较快,所以这里选择用socket配置

    1. [uwsgi]
    2. socket = 127.0.0.1:8005 //这里的端口号要跟nginx配置文件里面的一致
    3. master = true //主进程
    4. vhost = true //多站模式
    5. no-site = true //多站模式时不设置入口模块和文件
    6. workers = 4 //子进程数
    7. reload-mercy = 10
    8. vacuum = true //退出、重启时清理文件
    9. max-requests = 1000 //最大连接数
    10. limit-as = 1024
    11. http-timeout=600
    12. buffer-size = 10240000 //这里根据电脑配置可以调大一点
    13. pidfile = /home/virtualenvs/basketball/BasketballManager/uwsgi6666.pid
    14. daemonize = /home/virtualenvs/basketball/BasketballManager/uwsgi6666.log //指定log文件位置
    15. pythonpath=/usr/local/lib/python3.6/site-packages
    16. pythonpath=/home/virtualenvs/basketball/lib/python3.6/site-packages

    tips:这里有个坑,可以看到我这里配置文件里面的注释都用//来分割,而不是Python常用的#,有些网上的配置文件用#注释,最后就会连接不上,我郁闷了好久,后来发现它读取这个配置文件的时候可能不是当作Python文件来读的,// 这个是C语言或者Java之类的注释,这样就能理解了。

    e) 在阿里云开放刚刚设定的端口

    f) 启动

    这里要注意的是,如果你的机器(服务器)上有多个版本的Python,或者说虚拟环境重装了Python的话,一定要搞清楚启动的是哪个Python,还有uwsgi也是一样,所以我用的笨办法就是指定路径,我的启动命令如下:

    1. #启动nginx
    2. /usr/sbin/nginx start
    3. #启动uwsgi 这里指定启动哪个uwsgi,调用哪个uwsgi的ini文件
    4. /home/virtualenvs/basketball/bin/uwsgi --ini /home/virtualenvs/basketball/BasketballManager/uwsgi_basket.ini

    如果一切顺利,这时候打开浏览器输入公网地址,就可以看到网站的页面了

     g) 网址解析

    找到申请域名的服务商,我的是百度,找到百度的域名管理

    点击解析

     把自己的公网地址填进去,在服务器重启服务,这样就可以直接通过网址访问你的网站了。

    总结:

            整个上线部署是一个复杂的过程,这里只是介绍了最基本的流程,其他还要结合自己的业务考虑很多,比如访问量、安全漏洞、数据安全、网络配置、支付系统、管理权限等等很多问题,这里不展开叙述了,真实上线部署的时候要慎之又慎。

            到这里,我们就基本掌握了用Django开发一个网站的技术,结合前端技术,就可以开发出一个完整的网站了,动手尝试一下吧!

  • 相关阅读:
    数据分析-Pandas如何画自相关图
    python超细致带你批量获取美女内容~ 快来观赏叭
    2、《创建您自己的NFT集合并发布一个Web3应用程序来展示它们》启动并运行您的本地环境
    Golang 协程 与 Java 线程池的联系
    手写一个民用Tomcat (05)
    JS开发3D建模软件
    Spring中Bean循环依赖详解
    十七、文件(1)
    论文解读( N2N)《Node Representation Learning in Graph via Node-to-Neighbourhood Mutual Information Maximization》
    C语言每日一题——打印输出句子中各种单词长度的单词数目
  • 原文地址:https://blog.csdn.net/qq_41597915/article/details/130723477