Django 架设 Restful API(八)项目部署:定制django管理后台、日志设置

1. 定制django管理后台

管理后台详细定制参见我的另一篇博客:https://blog.csdn.net/anbuqi/article/details/103077268。

2.日志配置

2.1 django 运行日志

django运行日志配置参考

https://docs.djangoproject.com/zh-hans/3.1/topics/logging/

安全提示

django运行日志可能会包含堆栈信息,因此千万不能泄露,以免被攻击者根据日志窥探出系统漏洞。

django运行日志通常用来捕捉python代码运行过程中的异常,以及引起异常的堆栈信息,如果发现服务器出现500错误,首先要检查的就是django运行日志,看看是否出现python代码执行错误。在settings.py同级目录下新建日志设置文件:

Django 架设 Restful API(八)项目部署:定制django管理后台、日志设置_第1张图片

然后编写日志配置文件:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

LOG_FILE_PATH = os.path.join(BASE_DIR, 'kaopu_log/run.log')
DEFAULT_LOG_FILE_PATH = os.path.join(BASE_DIR, 'kaopu_log/all.log')
CONSOLE_LOG_FILE_PATH = os.path.join(BASE_DIR, 'kaopu_log/console.log')
LOGGING = {
    # 日志版本
    'version': 1,
    'disable_existing_loggers': False,  # 表示是否禁用所有的已经存在的日志配置
    'formatters': {  # 日志输出格式器
        'verbose': {  # 详细
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'standard': {  # 标准
            'format': '[%(asctime)s] [%(levelname)s] %(message)s'
        },
    },
    # handlers:用来定义具体处理日志的方式,可以定义多种,"default"就是默认方式,"console"就是打印到控制台方式。file是写入到文件的方式,注意使用的class不同
    'handlers': {  # 处理器,在这里定义了两个个处理器
        'console': {
            'level': 'ERROR',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',
            'formatter': 'standard',  # 制定输出的格式,注意 在上面的formatters配置里面选择一个,否则会报错
        },
        'file': {
            'level': 'ERROR',
            'class': 'logging.FileHandler',
            'filename': LOG_FILE_PATH,  # 这是将普通日志写入到日志文件中的方法,
            'formatter': 'verbose'
        },
        'default': {
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': DEFAULT_LOG_FILE_PATH,  # 日志输出文件
            'maxBytes': 1024 * 1024 * 5,  # 文件大小
            'backupCount': 3,  # 备份份数
            'formatter': 'verbose',  # 使用哪种formatters日志格式
        },

    },
    'loggers': {  # log记录器,配置之后就会对应的输出日志
        'django': {
            'handlers': ['console', 'file'],
            # 这里直接输出到控制台只是请求的路由等系统console,当使用重定向之后会把所有内容输出到log日志
            'level': 'ERROR',
            'propagate': True,
        },
        'django.request ': {
            'handlers': ['console', 'file'],
            'level': 'ERROR',  # 配合上面的将警告log写入到另外一个文件
            'propagate': True,
        },
        'django.db.backends': {
            'handlers': ['file'],  # 指定file handler处理器,表示只写入到文件
            'level': 'ERROR',
            'propagate': True,
        },
    },

}

settings.py中设置LOGGING字段:

from .server_log_settings.server_log_settings import get_kaopu_django_sever_logger
# django日志设置
LOGGING = get_kaopu_django_sever_logger(BASE_DIR)

然后新建日志目录和文件:

Django 架设 Restful API(八)项目部署:定制django管理后台、日志设置_第2张图片

最后在.gitignore文件中排除这个文件夹:

Django 架设 Restful API(八)项目部署:定制django管理后台、日志设置_第3张图片

按照上述配置的django运行日志不用进入容器也可快速查看,例如查看名为my_django容器的运行日志:

docker logs my_django

实际上只要容器内的日志被输出到控制台:stdout或者stderr,都可以直接使用docker logs查看。

2.2  gunicorn日志

 gunicorn运行日志分为两部分,一个是access_log,也就是连接日志,记录了客户端访问的url路径客户端ip请求状态码等信息;error_log则记录了 gunicorn运行时产生的错误。 gunicorn日志设置在配置文件 gunicorn.conf.py中指定(参见docker 容器构建一节)

# 错误日志
errorlog = "./my_log/gunicorn_error.log"
# 连接日志
accesslog = "./my_log/gunicorn_access.log"

gunicorn日志对于服务器的安全防护有重要意义,通过监控客户端连接记录,例如是否短时间内出现大量耗时连接,可以识别出恶意用户,分辨服务器是否受到攻击。

注意

如果使用了nginx作为代理服务器,那么在生产环境中设置access_log将无多大价值,因为此时记录到的访问记录都是来自nginx容器,本次项目中使用了nginx作为代理服务器,故得到的连接日志如下:

192.168.64.4:54668 - "POST /auth/user_auth/ HTTP/1.0" 200

 客户端ip都是相同的,即nginx容器在docker设定的内网中的ip。代理由在nginx配置文件中upstreamlocation / 字段中proxy_pass字段组合设定。因此这种情况下,建议只在调试的时候开启gunicorn连接日志。

2.3 mysql日志

mysql binlog日志详解参见

https://blog.csdn.net/wwwdc1012/article/details/88373440

MySQL中一般有以下几种日志:

Django 架设 Restful API(八)项目部署:定制django管理后台、日志设置_第4张图片

其中比较重要的是前三种日志,而二进制日志( binlog )是 MySQL 最重要的日志,它记录了所有的 DDL DML 语句(除了数据查询语句select、show等),并以事件形式记录,还包含语句执行所消耗的时间。binlog可以用来恢复和复制数据,因此非常重要

(1)查看日志配置

在mysql命令行中执行如下命令可以查看日志配置。


# 查看详细的日志配置信息
show global variables like '%log%';

# mysql数据存储目录
show variables like '%dir%';

(1)错误日志log_error

个人认为错误日志主要用来追溯mysql服务遇到的问题,可以用来进行故障排查辅助数据库优化。查看错误日志详细设置可以在mysql命令行中运行:

show global variables like '%log_error%';

默认情况下会看到以下输出:

Django 架设 Restful API(八)项目部署:定制django管理后台、日志设置_第5张图片

可以看到,mysql错误日志被重定向为标准错误输出stderr,这是因为docker为了我们能方便的查看容器运行日志,默认将mysql错误日志重定向到控制台,这样可以通过运行以下命令来查看名为my_mysql的容器中mysql服务的错误日志:

docker logs my_mysql

得到以下输出:

Django 架设 Restful API(八)项目部署:定制django管理后台、日志设置_第6张图片

因此为了方便查看mysql错误日志,不需要再在mysql配置文件中配置log_error字段。

(3)查询日志general_log

详细操作参见

https://www.cnblogs.com/ray-mr-huang/p/10466692.html

个人认为查询日志主要的用途是对数据库进行安全检查,监控连接数据库的用户和执行的语句是否合法,在受到攻击时确定受影响的数据范围。查看查询日志是否开启:

show variables like '%general_log%';

通常情况下不开启该日志,因此会得到以下输出:

Django 架设 Restful API(八)项目部署:定制django管理后台、日志设置_第7张图片

开启查询日志:

set global general_log = on;

查看日志的输出方式:

show variables like 'log_output';

默认为输出到文件,也可以设置成输出到数据表:

set global log_output='table';

然后这样查看查询日志:

select * from mysql.general_log;

 (4)二进制日志binlog

binlog对于数据备份和恢复,提升数据安全有重要意义,因此要妥善设置和保存。默认情况下binlog是开启的,通常保存在/var/lib/mysql中,且以binlog开头的文件中。常用操作如下:

# 查看binlog的目录
show global variables like "%log_bin%";

# 查看当前服务器使用的biglog文件及大小
show binary logs;

# 查看主服务器使用的biglog文件及大小

# 查看最新一个binlog日志文件名称和Position
show master status;
# 查看具体一个binlog文件的内容 (in 后面为binlog的文件名)
show binlog events in 'master.000003';

# 设置binlog文件保存事件,过期删除,单位天
set global expire_log_days=3; 

# 删除当前的binlog文件
reset master; 

# 删除指定日期前的日志索引中binlog日志文件
purge master logs before '2019-03-09 14:00:00';

对于binlog,尤其要注意的是写binlog的时机,这事关数据安全和一致性。对支持事务的引擎如InnoDB而言,必须要提交了事务才会记录binlogbinlog 什么时候刷新到磁盘跟参数 sync_binlog 相关。

  • 如果设置为0,则表示MySQL不控制binlog的刷新,由文件系统去控制它缓存的刷新;
  • 如果设置为不为0的值,则表示每 sync_binlog 次事务,MySQL调用文件系统的刷新操作刷新binlog到磁盘中。
  • 设为1是最安全的,在系统故障时最多丢失一个事务的更新,但是会对性能有所影响。
  • 如果 sync_binlog=0 sync_binlog大于1,当发生电源故障或操作系统崩溃时,可能有一部分已提交但其binlog未被同步到磁盘的事务会被丢失,恢复程序将无法恢复这部分事务。

MySQL 5.7.7之前,默认值 sync_binlog 是0,MySQL 5.7.7和更高版本使用默认值1,这是最安全的选择。一般情况下会设置为100或者0,牺牲一定的一致性来获取更好的性能docker容器中的sync_binlog默认值通常为1。

2.4 nginx日志

Nginx日志主要分为两种:access_log(访问日志)和error_log(错误日志)。通过访问日志我们可以得到用户的IP地址、浏览器的信息,请求的处理时间等信息。错误日志记录了访问出错的信息,可以帮助我们定位错误的原因。

nginx日志详解参见

https://blog.51cto.com/longlei/2132170

(1)访问日志access_log

访问日志对于服务器安全防护尤为重要,因为nginx的访问日志中记录了访问服务器客户端ip、类型(UA)和连接时长等信息,当受到网络攻击时,可以根据访问日志确定攻击者ip,从而做出防护。访问日志主要关注以下几个字段:

  • $remote_addr:客户端ip地址,可以用来确定攻击者信息。
  • $remote_user:客户端用户名称,针对启用了用户认证的请求。
  • $http_referer:请求的referer地址。
  • $status连接响应状态码,可以用来查看响应是否成功。
  • $http_user_agent:客户端设备类型,这个字段可以用来过滤爬虫。
  • $time_local:连接建立时间。
  • $request:完整的原始请求行,如 "GET / HTTP/1.1"。
  • $request_uri:完整的请求地址,如 "https://daojia.com/"。

默认情况下,运行docker日志查看命令:

docker logs my_nginx

dockernginx会输出的访问日志格式如下(瞎编的IP):

192.168.32.199 - - [08/Apr/2021:18:34:59 +0000] "POST /auth/user_auth/ HTTP/1.1" 200 1035 "-" "python-requests/2.25.1" "-"

对应的日志格式:

'$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"'

 其中"-"表示这个字段值为空。通常默认日志格式的信息已经足够了,如果需要进一步优化nginx性能,可以查看手册开启更多字段,但是开启的字段越多日志文件占用的空间就越多。

(2)错误日志error_log

错误日志主要记录客户端访问Nginx出错时的日志,格式不支持自定义。通过错误日志,你可以得到系统某个服务或server的性能瓶颈等信息。错误日志由指令error_log来指定,具体格式如下:

error_log path(存放路径) level(日志等级)

例如:

error_log  logs/error.log  info;

 放在nginx配置文件的http字段内。

日志输出等级分为:[ debug | info | notice | warn | error | crit ],从左至右,日志详细程度逐级递减,debug最详细,crit输出信息最少。

2.5 redis日志

默认配置下redis不会生成日志文件,而是将日志输出到标准输出。通常情况下,为了方便使用:

docker logs my_redis

查看容器内的redis日志,保持日志输出到标准输出即可,推荐使用这种方式。如果想生成日志文件,配置redis.conf中的日志文件路径:

# Specify the log file name. Also the empty string can be used to force
# Redis to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile "你的日志文件路径"

默认日志级别是notice,官方推荐在生产环境下用这个,修改loglevel更换日志级别:

# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice

3.总结

3.1 日志目的

日志不能胡乱的开启,只有在需要的时候才能开启,而且日志是一种敏感信息,不能随意乱放,以免日志暴露系统缺陷而受到网络攻击。个人认为日志在以下的场景中才需要开启:

(1)系统监控

系统监控日志主要是捕捉系统运行时出现的错误,记录系统崩溃时的状态,从而能根据日志复现错误,达到修补系统缺陷的目的。在这种情况下,日志级别一般设置为错误级别,如本项目中的django运行日志。另一个目的是记录系统的行为,以此判断系统是否有异常操作,从而分析系统是否受到入侵和破坏,如本项目中的nginx连接日志。

(2)数据恢复

生产环境下误删数据屡见不鲜,由于突发状况(断电,网络攻击)造成数据损坏的情况也很难避免,因此对于关键数据,一定要做备份并记录对数据的操作,这样在出现意外状况时可以复原数据。本项目中使用MYSQLbinlog来完成该项功能。

(3)性能优化

记录系统运行过程中关键指标(如IO,内存,磁盘和CPU使用)变化情况对于分析系统性能有重要意义。对于web服务器,通常需要监控服务器的负载、内存使用率以及请求响应时长等。可以使用日志采集每个请求的响应时间,从而找出响应慢的请求,用于分析是否是服务代码不合理,导致响应速度低下。

3.2 日志维护

日志不能开启之后不管,不然只会在白白浪费资源。随着系统升级,系统规模不断扩大,产生的日志文件也越来越多,日志也要随着优化。为了节省资源和分析的精力,日志中应当不断剔除不需要的信息;不断优化日志系统,尽力达到用最少的资源和性能损耗捕捉到最多有效信息的目的。日志维护可能需要从以下几个方面着手:

(1)日志采集

由于日志通常是现场采集,即在服务运行同时采集日志,因此日志可能会造成系统性能损耗,比如过多的采集异常信息(try catch)造成请求响应速度变慢。因此要仔细分析日志采集的指标,尽量做到精准采集,减少性能损耗。

(2)日志存储

日志通常存储在文件或数据库中,要选择规范的格式存储日志,方便进行日志分析,同时要考虑使用一定的压缩方法,减少日志占用的空间。

(3)日志清理

选择合适的时机清理过时日志,要保证清除的日志被用到的概率极低。

3.3 日志分析

日志分析的目的是从日志中挖掘出有用的信息,为系统安全防护和性能优化提供数据支持,指明系统优化和改进方向。

3.4 日志安全

(1)日志脱敏

日志脱敏是指日志中禁止记录可能带来安全性问题的数据,例如用户登录使用的账号密码,系统源码等。

(2)日志权限

要对日志输出层级设限,防止无关人员开启详细日志功能获取系统的详细日志,从而窥探出系统设置和关键数据。要对日志文件设置权限,只允许特定的运维人员查看日志,减少系统缺陷被恶意利用的几率。

你可能感兴趣的:(django,restful,日志)