Flask服務(wù)器部署:使用Docker+Gunicorn+gevent+Nginx部署Flask應(yīng)用

摘要:Flask抖棘,gunicornnginx净捅,docker疑枯,geventWSGI

整理一下Flask的部署相關(guān)代碼蛔六,以及各個(gè)組件的使用和一些原理


Flask部署.png

為什么需要Gunicorn

在開發(fā)時(shí)flask的run命令可以直接啟動(dòng)提供web服務(wù)荆永,實(shí)際上是由Werkzeug提供的WSGI服務(wù)器,相當(dāng)于Flask內(nèi)置了一個(gè)WSGI服務(wù)器国章,只適合在開發(fā)調(diào)試的時(shí)候使用具钥;在生產(chǎn)環(huán)境中需要一個(gè)更強(qiáng)健,性能更高的WSGI服務(wù)器液兽,WSGI服務(wù)器也被稱為獨(dú)立的WSGI容器骂删,主流的WSGI容器有GunicornuWSGI


什么是WSGI服務(wù)器

Web Server Gateway Interface 的縮寫,即 Web 服務(wù)器網(wǎng)關(guān)接口四啰。Python web開發(fā)中宁玫,服務(wù)端程序分為兩個(gè)部分

  • 服務(wù)器程序:用來接收整理客戶端發(fā)送的請求柑晒,比如Nginx
  • 應(yīng)用程序處理服務(wù)器程序傳遞過來的請求欧瘪,比如Flask,Django匙赞,Tornado

服務(wù)器程序和應(yīng)用程序互相配合才能給用戶提供服務(wù)佛掖,而不同應(yīng)用程序(不同框架)會(huì)有不同的函數(shù)、功能罚屋。 此時(shí)就需要一個(gè)標(biāo)準(zhǔn)苦囱,讓服務(wù)器程序和應(yīng)用程序都支持這個(gè)標(biāo)準(zhǔn),這樣二者就能很好的配合了脾猛,這個(gè)標(biāo)準(zhǔn)就是WSGI撕彤,是python web開發(fā)的標(biāo)準(zhǔn),類似于協(xié)議,是web服務(wù)器程序與應(yīng)用程序解耦的規(guī)范羹铅,這樣服務(wù)器程序和應(yīng)用程序就可以隨意組合實(shí)現(xiàn)自己的web應(yīng)用蚀狰。它是服務(wù)器程序和應(yīng)用程序的一個(gè)約定,規(guī)定了各自使用的接口和功能职员,以便二和互相配合麻蹋。


為什么需要Nginx

Nginx是Web服務(wù)器,流行的Web服務(wù)器還有Apache焊切,Tengine等扮授,Web服務(wù)器主要負(fù)責(zé)和客戶端交換數(shù)據(jù)處理請求和響應(yīng),像Gunicorn這類WSGI服務(wù)器內(nèi)置了Web服務(wù)器专肪,但是內(nèi)置的Web服務(wù)器不夠強(qiáng)健刹勃,更流行的部署方式是采用一個(gè)常規(guī)的Web服務(wù)器運(yùn)行在前端,為WSGI服務(wù)器提供反向代理嚎尤。在Gunicorn之后再加一層Nginx有以下好處:

  • 負(fù)載均衡: 當(dāng)有多個(gè)應(yīng)用多臺(tái)機(jī)器時(shí)需要做負(fù)載均衡
  • 靜態(tài)文件處理:經(jīng)過配置之后荔仁,Nginx可以直接處理靜態(tài)文件請求而不用經(jīng)過Python服務(wù)器,Gunicorn或者Flask等對靜態(tài)資源的處理效率不如Nginx芽死,并且Nginx可以對靜態(tài)文件設(shè)置緩存
  • 安全問題:Gunicorn暴露在公網(wǎng)公網(wǎng)十分危險(xiǎn)乏梁,在Nginx擋在前面會(huì)安全不少
  • 抗并發(fā)壓力:前端多一層Nginx,可以吸收一些瞬時(shí)的并發(fā)請求作為請求緩沖关贵,讓Nginx先保持住連接遇骑,然后后端慢慢消化
  • 支持的http協(xié)議更廣:gunicorn的http解析可能有bug,Nginx處理更好
  • 提供其他額外功能:比如IP過濾等

使用Gunicorn作為容器啟動(dòng)Flask

安裝gunicorn坪哄,使用pip下載安裝

pip install gunicorn

如果以gevent模式運(yùn)行g(shù)unicorn质蕉,需要安裝gevent,版本20.9.0以上

pip install gevent==20.9.0

編寫gunicorn配置文件

root@ubuntu:~/myproject/pira_score_web_application# cat gun.conf.py 
# gun.conf
bind = '0.0.0.0:5000'
workers = 5 
backlog = 2048
worker_class = "gevent"
debug = False
proc_name = 'gunicorn.proc'
pidfile = './gunicorn.pid'
#accesslog = '/var/log/gunicorn/pira_score_web/detail.log'
#access_log_format = '%(h)s %(l)s %(u)s %(t)s'
#loglevel = 'info'

Gunicorn配置詳解

  • -c, --config:啟動(dòng)時(shí)引入Gunicorn的配置文件路徑
  • -b, --bind:Gunicorn與指定socket進(jìn)行綁定.
  • --backlog:未決連接的最大數(shù)量翩肌,即等待服務(wù)的客戶的數(shù)量模暗。必須是正整數(shù),一般設(shè)定在64~2048的范圍內(nèi)念祭,一般設(shè)置為2048兑宇,超過這個(gè)數(shù)字將導(dǎo)致客戶端在嘗試連接時(shí)錯(cuò)誤
  • -w, --workers:用于處理工作進(jìn)程的數(shù)量,為正整數(shù)粱坤,默認(rèn)為1隶糕。worker推薦的數(shù)量為當(dāng)前的CPU個(gè)數(shù)*2 + 1
  • -k, --worker-class:要使用的工作模式,默認(rèn)為sync站玄,可以使用其他模式比如gevent枚驻,tornado,但是需要額外pip安裝
  • --threads:處理請求的工作線程數(shù)株旷,使用指定數(shù)量的線程運(yùn)行每個(gè)worker再登。為正整數(shù)尔邓,默認(rèn)為1
  • --reload:代碼更新時(shí)將重啟工作锉矢,默認(rèn)為False梯嗽。
  • -D,--daemon:守護(hù)Gunicorn進(jìn)程后臺(tái)運(yùn)行,默認(rèn)False沽损。
  • -p, --pid, pidfile:設(shè)置pid文件的文件名灯节,如果不設(shè)置將不會(huì)創(chuàng)建pid文件。
  • proc_name:設(shè)置進(jìn)程名绵估。

編寫gunicorn啟動(dòng)腳本

root@ubuntu:~/myproject/pira_score_web_application# cat run.sh 
#! /bin/bash
cd /home/gp/myproject/pira_score_web_application
gunicorn -c gun.conf.py -D app:app

查看后臺(tái)gunicorn進(jìn)程pid

root@ubuntu:~/myproject/pira_score_web_application# cat gunicorn.pid 
30322
root@ubuntu~/myproject/pira_score_web_application# ps -ef|grep `cat gunicorn.pid`
root     30322  1104  0 10:47 ?        00:00:00 /opt/anaconda3/bin/python /opt/anaconda3/bin/gunicorn -c gun.conf.py -D app:app
root     30325 30322  0 10:47 ?        00:00:00 /opt/anaconda3/bin/python /opt/anaconda3/bin/gunicorn -c gun.conf.py -D app:app
root     30326 30322  0 10:47 ?        00:00:00 /opt/anaconda3/bin/python /opt/anaconda3/bin/gunicorn -c gun.conf.py -D app:app
root     30327 30322  0 10:47 ?        00:00:00 /opt/anaconda3/bin/python /opt/anaconda3/bin/gunicorn -c gun.conf.py -D app:app
root     30328 30322  0 10:47 ?        00:00:00 /opt/anaconda3/bin/python /opt/anaconda3/bin/gunicorn -c gun.conf.py -D app:app
root     30329 30322  0 10:47 ?        00:00:00 /opt/anaconda3/bin/python /opt/anaconda3/bin/gunicorn -c gun.conf.py -D app:app
root     31611 21931  0 11:01 pts/3    00:00:00 grep --color=auto 30322

可見后臺(tái)一共有一個(gè)父進(jìn)程和5個(gè)子進(jìn)程炎疆,和5個(gè)workers對應(yīng),可以使用父進(jìn)程pid直接關(guān)閉gunicorn的所有進(jìn)程

root@ubuntu:~/myproject/pira_score_web_application# kill -9 `cat gunicorn.pid`

gevent和協(xié)程

gevent:是一個(gè)基于協(xié)程的python網(wǎng)絡(luò)庫壹士,在遇到IO阻塞時(shí)磷雇,程序會(huì)自動(dòng)進(jìn)行切換,可以讓開發(fā)者用同步的方式寫異步IO代碼躏救。
協(xié)程:是單線程下的并發(fā),又稱微線程螟蒸,是一種并發(fā)編程模式盒使,協(xié)程并發(fā)的本質(zhì)是切換+保存狀態(tài)

測試使用gevent運(yùn)行兩個(gè)阻塞IO任務(wù)七嫌,分別阻塞3秒少办,4秒;gevent使用spawn定義一個(gè)協(xié)程任務(wù)诵原,接受任務(wù)名入?yún)?/code>英妓,是一個(gè)異步任務(wù),使用join等待協(xié)程執(zhí)行完畢退出绍赛,也可以調(diào)用joinall方法傳入一個(gè)任務(wù)列表蔓纠。

from gevent import monkey
import gevent
import time

monkey.patch_all()  # 合并成一行,專門用于打標(biāo)記


def eat(name):
    print("%s is eating 1" % name)
    # gevent.sleep(3)  # gevent.sleep()和 time.sleep()效果一樣
    time.sleep(3)
    print("%s is eating 2" % name)


def play(name):
    print("%s play 1" % name)
    # gevent.sleep(4)
    time.sleep(4)
    print("%s play 2" % name)


start = time.time()

g1 = gevent.spawn(eat, "aaa")  # 提交任務(wù)  #  spawn()第一個(gè)參數(shù)寫任務(wù)名吗蚌,后面直接參數(shù)就行(位置參數(shù)或關(guān)鍵字參數(shù)都可以)
g2 = gevent.spawn(play, "bbb")  # gevent.spawn()是異步提交任務(wù)

g1.join()
g2.join()  # 保證上面提交的兩個(gè)任務(wù)都執(zhí)行完畢了  # 協(xié)程是單線程的腿倚,需要再線程結(jié)束前等待g1和g2,要不然g1和g2還沒起來蚯妇,“主線程”就結(jié)束了,此時(shí)g1和g2也就不會(huì)再執(zhí)行了
# g1.join()和g2.join()可以合并成:
# gevent.joinall([g1,g2])

stop = time.time()
print(stop - start)  # 4.002309322357178

執(zhí)行結(jié)果為最大阻塞時(shí)間4秒,如果是串行執(zhí)行為7秒紊馏。
gevent執(zhí)行過程分析
(1)先啟任務(wù)1:g1先起來富雅,執(zhí)行了第一個(gè)print,然后遇到了IO阻塞(gevent.sleep(3)),然后立馬就切到了 g2 提交的 play任務(wù)
(2)任務(wù)1阻塞切換任務(wù)2:執(zhí)行 play中的第一個(gè)print陨收,接著又遇到了IO阻塞(gevent.sleep(4))饭豹,然后就又切到了 g1的eat任務(wù)
(3)來回切換:此時(shí)g1的eat還是處于阻塞狀態(tài),接著就在兩個(gè)任務(wù)之間來回切
(4)分別等待協(xié)程執(zhí)行就緒:直到 g1的eat 又處于就緒狀態(tài),打印 eat的第2個(gè)print墨状;執(zhí)行完 eat之后卫漫,g2的play還處于阻塞狀態(tài),然后等其阻塞結(jié)束后執(zhí)行 play的第2個(gè)print肾砂;
gevent監(jiān)測了多個(gè)任務(wù)之間的IO阻塞列赎,遇到IO阻塞就切走


Gunicorn前后壓測對比

使用壓測工具siege模擬并發(fā),先修改根目錄下.siege目錄下的配置文件siege.conf設(shè)置最大并發(fā)量為1000镐确,先對比400并發(fā)下包吝,循環(huán)測試2次,請求之間無間隔的統(tǒng)計(jì)結(jié)果
flask自帶的WSGI服務(wù)器

root@ubuntu:~/.siege# siege -c 400 -r 2 -b "http://192.168.67.72:5000/北京優(yōu)勝輝煌教育科技有限公司.html"
** SIEGE 4.0.4
** Preparing 400 concurrent users for battle.
The server is now under siege...
Transactions:               4800 hits
Availability:             100.00 %
Elapsed time:              30.62 secs
Data transferred:         744.21 MB
Response time:              1.77 secs
Transaction rate:         156.76 trans/sec
Throughput:            24.30 MB/sec
Concurrency:              276.91
Successful transactions:        4800
Failed transactions:               0
Longest transaction:           29.01
Shortest transaction:           0.04

Gunicorn作為WSGI服務(wù)器
Gunicorn開啟5個(gè)進(jìn)程啟動(dòng)Flask源葫,工作模式使用gevent

root@ubuntu:~/.siege# siege -c 400 -r 2 -b "http://192.168.61.100:5000/北京優(yōu)勝輝煌教育科技有限公司.html"
** SIEGE 4.0.4
** Preparing 400 concurrent users for battle.
The server is now under siege...
Transactions:               4800 hits
Availability:             100.00 %
Elapsed time:              13.72 secs
Data transferred:         744.21 MB
Response time:              0.83 secs
Transaction rate:         349.85 trans/sec
Throughput:            54.24 MB/sec
Concurrency:              291.27
Successful transactions:        4800
Failed transactions:               0
Longest transaction:           12.04
Shortest transaction:           0.00
  • Transactions:總計(jì)傳輸?shù)氖聞?wù)數(shù)诗越,請求這個(gè)url加上其他靜態(tài)文件一共發(fā)出6個(gè)請求,循環(huán)兩次息堂,一共400 × 12 = 4800
  • Elapsed time:總耗時(shí)嚷狞, Flask總耗時(shí) 30.62秒,Gunicorn耗時(shí)13.72秒
  • Response time:平均響應(yīng)時(shí)間荣堰,F(xiàn)lask 1.77秒床未, Gunicorn 0.83秒
  • Transaction rate:TPS每秒傳輸事務(wù)數(shù),F(xiàn)lask 156振坚,Gunicorn 350

測試結(jié)果Gunicorn的處理速度和性能是Flask的2倍多薇搁,并且在模擬并發(fā)達(dá)到500及以上時(shí),請求Flask服務(wù)報(bào)錯(cuò)渡八,而Gunicorn運(yùn)行良好


Docker容器化部署服務(wù)器

在項(xiàng)目目錄下創(chuàng)建requirements.txt啃洋,指定項(xiàng)目需要的Python包和版本

# requirements.txt
flask==1.1.1
Flask-SQLAlchemy==2.4.4
gevent==20.9.0
gunicorn==20.0.4
numpy==1.19.5
pymysql==1.0.0
SQLAlchemy==1.3.13
python-dotenv==0.15.0
Flask-Caching==1.9.0

在項(xiàng)目根目錄向創(chuàng)建Dockerfile,指定鏡像源屎鳍,在基礎(chǔ)鏡像中安裝requirements.txt包

FROM python:3.7
ENV PIPURL "https://pypi.tuna.tsinghua.edu.cn/simple"

ADD ./requirements.txt /home/
WORKDIR /home
RUN pip install --no-cache-dir -i ${PIPURL} -r requirements.txt
#CMD gunicorn -c gun.conf.py app:app

構(gòu)建鏡像

root@ubuntu:~/myproject/pira_score_web_application# docker build . -t=pira_score_web:latest

掛載flask項(xiàng)目根目錄下的所有文件到容器內(nèi)部啟動(dòng)

root@ubuntu:~/myproject/pira_score_web_application# docker run --rm -d -v `pwd`:/home -p 5001:5000 pira_score_web:latest

Nginx配置反向代理

ubuntu下安裝nginx

sudo apt-get install nginx

查看nginx運(yùn)行狀態(tài)

root@ubuntu:~# service nginx status
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2021-01-18 10:13:15 CST; 2s ago
     Docs: man:nginx(8)
  Process: 1141 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid (code=exited, status=0/SUCCESS)
  Process: 1231 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 1218 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 1232 (nginx)
    Tasks: 5 (limit: 4915)
   CGroup: /system.slice/nginx.service
           ├─1232 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           ├─1237 nginx: worker process
           ├─1238 nginx: worker process
           ├─1239 nginx: worker process
           └─1240 nginx: worker process

開啟宏娄,停止,重啟nginx服務(wù)

root@ubuntu:~# service nginx start
root@ubuntu:~# service nginx stop
root@ubuntu:~# service nginx restart
image.png

給Flask應(yīng)用構(gòu)建Nginx配置文件哥艇,通常在/etc/nginx/sites-enabled或者/etc/nginx/conf.d目錄下創(chuàng)建單獨(dú)的配置文件绝编,而不直接在全局配置文件/etv/nginx/nginx.conf直接創(chuàng)建,在nginx.conf中已經(jīng)引入這兩個(gè)路徑貌踏,這兩個(gè)路徑下的配置會(huì)被插入到全局配置文件中十饥。

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
Nginx配置文件的基本結(jié)構(gòu)

Nginx配置文件為nginx.conf,結(jié)構(gòu)如下

...              #全局塊


events {         #events塊
   ...
}

http      #http塊
{
    ...   #http全局塊
    server        #server塊
    { 
        ...       #server全局塊
        location [PATTERN]   #location塊
        {
            ...
        }
        location [PATTERN] 
        {
            ...
        }
    }
    server
    {
      ...
    }
    ...     #http全局塊
}
  • 全局塊:配置影響nginx全局的指令祖乳。一般有運(yùn)行nginx服務(wù)器的用戶組逗堵,nginx進(jìn)程pid存放路徑,日志存放路徑眷昆,配置文件引入蜒秤,允許生成worker process數(shù)等汁咏,默認(rèn)如下

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

  • events塊:配置影響nginx服務(wù)器或與用戶的網(wǎng)絡(luò)連接。有每個(gè)進(jìn)程的最大連接數(shù)作媚,選取哪種事件驅(qū)動(dòng)模型處理連接請求攘滩,是否允許同時(shí)接受多個(gè)網(wǎng)路連接,開啟多個(gè)網(wǎng)絡(luò)連接序列化等纸泡,默認(rèn)如下漂问。

events {
worker_connections 768;
# multi_accept on;
}

  • http塊:可以嵌套多個(gè)server,配置代理女揭,緩存蚤假,日志定義等絕大多數(shù)功能和第三方模塊的配置。如文件引入吧兔,mime-type定義磷仰,日志自定義,是否使用sendfile傳輸文件境蔼,連接超時(shí)時(shí)間灶平,單連接請求數(shù)等,在這個(gè)塊底部使用include引入其他文件的server箍土。

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

  • server塊:配置虛擬主機(jī)的相關(guān)參數(shù)民逼,一個(gè)http中可以有多個(gè)server,可以在sites-enabled和conf.d下定義文件涮帘。
  • location塊:配置請求的路由,以及各種頁面的處理情況笑诅。
  • [PATTERN]:設(shè)置location 的路徑匹配規(guī)則调缨,根據(jù)不同的路徑分配給請求不同的處理方式,主要分為前綴匹配正則匹配

前綴匹配
精確前綴匹配: location = uri {...}
優(yōu)先前綴匹配: location ^~ uri {...}
普通前綴匹配: location uri {...}
正則匹配
大小寫敏感: location ~ uri {...}
大小寫不敏感: location ~* uri {...}

location的匹配順序以及優(yōu)先級(jí)

1.首先匹配=
2.其次匹配^~
3.再其次按照配置文件的順序進(jìn)行正則匹配
4.最后是交給/進(jìn)行通用匹配吆你,通用匹配記錄下最長的匹配作為命中的規(guī)則

server配置
server {
    listen 80;
    server_name 127.0.0.1;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_redirect    off;

        proxy_set_header    Host                $host;
        proxy_set_header    X-Real_IP           $remote_addr;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for ;
        proxy_set_header    X-Forwarded-Proto   $scheme;
        #deny 127.0.0.1;  #拒絕的ip
    }

    location /PiraScore/static {
        alias /home/gp/myproject/pira_score_web_application/static/;
        expires 30d;
        add_header wall  "use nginx cache";
    }
}

server參數(shù)配置詳解

  • listen:監(jiān)聽端口
  • server_name:監(jiān)聽地址
  • access_log:訪問日志地址
  • error_log:錯(cuò)誤日志
  • proxy_pass:請求轉(zhuǎn)向的目標(biāo)位置
  • proxy_redirect:禁止所有的proxy_redirect指令
  • proxy_set_header:用來設(shè)定被代理服務(wù)器接收到的header信息

語法:proxy_set_header field value;
field :為要更改的項(xiàng)目弦叶,也可以理解為變量的名字,比如host
value :為變量的值

  • Host妇多,$host:設(shè)置header信息中的Host伤哺,如果不設(shè)置則默認(rèn)host的值為proxy_pass后面跟的那個(gè)域名或者IP
  • X-Real_IP$remote_addr:用來設(shè)置被代理端接收到的遠(yuǎn)程客戶端IP者祖,如果不設(shè)置立莉,則header信息中并不會(huì)透傳遠(yuǎn)程真實(shí)客戶端的IP地址
  • X-Forwarded-For$proxy_add_x_forwarded_for:用來設(shè)置被代理端接收到的遠(yuǎn)程客戶端IP七问,如果不設(shè)置蜓耻,則header信息中并不會(huì)透傳遠(yuǎn)程真實(shí)客戶端的IP地址
  • X-Forwarded-Proto:用于識(shí)別識(shí)別實(shí)際用戶發(fā)出的協(xié)議是 http 還是 https
    其中proxy_set_header的幾行設(shè)置是反向代理的標(biāo)準(zhǔn)配置
proxy_set_header    Host                $host;
proxy_set_header    X-Real_IP           $remote_addr;
proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for ;  
proxy_set_header    X-Forwarded-Proto   $scheme;
  • deny:設(shè)置拒絕的ip,設(shè)置了之后就403 forbidden了
  • location:第一個(gè)規(guī)則是/械巡,代表通用匹配刹淌,所有url如果沒用命中第二個(gè)location都會(huì)走這個(gè)規(guī)則處理
  • /PiraScore/static:第二個(gè)規(guī)則是/PiraScore/static饶氏,代表通用匹配,靜態(tài)文件的地址
  • alias:設(shè)置url對應(yīng)文件系統(tǒng)的位置有勾,設(shè)置后會(huì)到定義的目錄中尋找資源疹启,alias后面必須要用 / 結(jié)束,否則會(huì)找不到文件
  • expires:30d設(shè)置緩存時(shí)間為30天
  • add_header:用于設(shè)置header中的自定義信息蔼卡,變量名可以隨意指定喊崖,比如wall
nginx啟動(dòng)

使用命令檢查Nginx配置是否有語法錯(cuò)誤

root@ubuntu:/etc/nginx/sites-enabled# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重啟Nginx

root@ubuntu:/etc/nginx/sites-enabled# service nginx restart

訪問url http:127.0.0.1:80/PiraScore成功,訪問靜態(tài)文件的url查看是否被對應(yīng)location處理成緩存菲宴,在響應(yīng)頭中查看是否有自定義內(nèi)容贷祈,存在!

靜態(tài)文件訪問地址的響應(yīng)頭.png

也可以在日志中查看喝峦,日志中不應(yīng)該存在請求靜態(tài)文件的url势誊,因?yàn)殪o態(tài)文件走了Nginx緩存

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市谣蠢,隨后出現(xiàn)的幾起案子粟耻,更是在濱河造成了極大的恐慌,老刑警劉巖眉踱,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挤忙,死亡現(xiàn)場離奇詭異,居然都是意外死亡谈喳,警方通過查閱死者的電腦和手機(jī)册烈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婿禽,“玉大人赏僧,你說我怎么就攤上這事∨で悖” “怎么了淀零?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長膛壹。 經(jīng)常有香客問我驾中,道長,這世上最難降的妖魔是什么模聋? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任肩民,我火速辦了婚禮,結(jié)果婚禮上撬槽,老公的妹妹穿的比我還像新娘此改。我一直安慰自己,他們只是感情好侄柔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布共啃。 她就那樣靜靜地躺著占调,像睡著了一般。 火紅的嫁衣襯著肌膚如雪移剪。 梳的紋絲不亂的頭發(fā)上究珊,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音纵苛,去河邊找鬼剿涮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛攻人,可吹牛的內(nèi)容都是我干的取试。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怀吻,長吁一口氣:“原來是場噩夢啊……” “哼瞬浓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蓬坡,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤猿棉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后屑咳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體萨赁,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年兆龙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了杖爽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡紫皇,死狀恐怖掂林,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坝橡,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布精置,位于F島的核電站计寇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏脂倦。R本人自食惡果不足惜番宁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赖阻。 院中可真熱鬧蝶押,春花似錦、人聲如沸火欧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赶盔,卻和暖如春企锌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背于未。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工撕攒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烘浦。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓抖坪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親闷叉。 傳聞我的和親對象是個(gè)殘疾皇子擦俐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容