Nginx狀態碼499

来源:http://www.cnblogs.com/chenpingzhao/archive/2016/08/27/5807823.html
-Advertisement-
Play Games

1、問題描述 2、問題分析 google 499 / ClientClosed Request An Nginx HTTP server extension. This codeis introduced to log the case when the connection is closed b ...


1、問題描述

140.207.202.187 - - [18/May/2016:10:30:58 +0800] "POST/v3/violations HTTP/1.1" 499 0 "-" "-"
42.236.10.71 - - [18/May/2016:10:30:59 +0800] "POST /v3/violationsHTTP/1.1" 499 0 "-" "-"

2、問題分析

google

499 / ClientClosed Request

    An Nginx HTTP server extension. This codeis introduced to log the case when the connection is closed by client whileHTTP server is processing its request, making server unable to send the HTTP header back

維基百科

499Client Closed Request (Nginx)

Used in Nginx logs to indicate when the connection has been closed by client while the server is still processing itsrequest, making server unable to send a status code back

nginx源碼

./src/http/ngx_http_core_module.c:        if (status == NGX_ERROR || status == 499) {
./src/http/ngx_http_request.h:#define NGX_HTTP_CLIENT_CLOSED_REQUEST     499
./src/http/ngx_http_special_response.c:    ngx_null_string,                     /* 499, client has closed connection */

這是nginx定義的一個狀態碼,用於表示這樣的錯誤:伺服器返回http頭之前,客戶端就提前關閉了http連接,這很有可能是因為伺服器端處理的時間過長,客戶端“不耐煩”了。

進一步查找

查找“NGX_HTTP_CLIENT_CLOSED_REQUEST”

./src/http/ngx_http_upstream.c:                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_upstream.c:                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_upstream.c:                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_upstream.c:                                           NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_upstream.c:                                           NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_upstream.c:                                           NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_request.c:        || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
./src/http/ngx_http_spdy.c:                                              NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_spdy.c:        ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_spdy.c:        ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_spdy.c:    ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/modules/tfs/ngx_http_tfs_server_handler.c:                     return NGX_HTTP_CLIENT_CLOSED_REQUEST;
./src/http/modules/tfs/ngx_http_tfs.c:    if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
./src/http/modules/tfs/ngx_http_tfs.c:                                          NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/modules/lua/ngx_http_lua_socket_tcp.c:                        if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST) {
./src/http/modules/lua/ngx_http_lua_control.c:        && rc != NGX_HTTP_CLIENT_CLOSED_REQUEST)
./src/http/modules/lua/ngx_http_lua_control.c:        && rc != NGX_HTTP_CLIENT_CLOSED_REQUEST
./src/http/modules/lua/ngx_http_lua_subrequest.c:            && rc != NGX_HTTP_CLIENT_CLOSED_REQUEST))
./src/http/modules/lua/ngx_http_lua_util.c:        return NGX_HTTP_CLIENT_CLOSED_REQUEST;
./src/http/modules/lua/ngx_http_lua_util.c:        return NGX_HTTP_CLIENT_CLOSED_REQUEST;
./src/http/modules/lua/ngx_http_lua_util.c:    return NGX_HTTP_CLIENT_CLOSED_REQUEST;
./src/http/ngx_http_spdy_v3.c:                                              NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_spdy_v3.c:        ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_spdy_v3.c:        ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_spdy_v3.c:    ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST);
./src/http/ngx_http_request.h:#define NGX_HTTP_CLIENT_CLOSED_REQUEST     499

第一處顯示

#if (NGX_HAVE_KQUEUE)

    if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {

        if (!ev->pending_eof) {
            return;
        }    

        ev->eof = 1; 
        c->error = 1; 

        if (ev->kq_errno) {
            ev->error = 1; 
        }    

        if (!u->cacheable && u->peer.connection) {
            ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
                          "kevent() reported that client prematurely closed "
                          "connection, so upstream connection is closed too");
            ngx_http_upstream_finalize_request(r, u,
                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
            return;
        }    

        ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
                      "kevent() reported that client prematurely closed "
                      "connection");

        if (u->peer.connection == NULL) {
            ngx_http_upstream_finalize_request(r, u,
                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
        }    

        return;
    }    

KQUEUE 這個是在unix下使用的網路模型,這裡可以略過

第二處顯示

static void
ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
    ngx_event_t *ev)
{
    int                  n;
    char                 buf[1];
    ngx_err_t            err;
    ngx_int_t            event;
    ngx_connection_t     *c;
    ngx_http_upstream_t  *u;

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
                   "http upstream check client, write event:%d, \"%V\"",
                   ev->write, &r->uri);

    c = r->connection;
    u = r->upstream;

    if (c->error) {
        if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {

            event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;

            if (ngx_del_event(ev, event, 0) != NGX_OK) {
                ngx_http_upstream_finalize_request(r, u,
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
                return;
            }
        }

        if (!u->cacheable) {
            ngx_http_upstream_finalize_request(r, u,
                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
        }

        return;
    }

第三處顯示

void
ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
{
    ngx_connection_t          *c;
    ngx_http_request_t        *pr;
    ngx_http_core_loc_conf_t  *clcf;

    c = r->connection;

    ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   "http finalize request: %d, \"%V?%V\" a:%d, c:%d",
                   rc, &r->uri, &r->args, r == c->data, r->main->count);

    if (rc == NGX_DONE) {
        ngx_http_finalize_connection(r);
        return;
    }

    if (rc == NGX_OK && r->filter_finalize) {
        c->error = 1;
    }

    if (rc == NGX_DECLINED) {
        r->content_handler = NULL;
        r->write_event_handler = ngx_http_core_run_phases;
        ngx_http_core_run_phases(r);
        return;
    }

    if (r != r->main && r->post_subrequest) {
        rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
    }

    if (rc == NGX_ERROR
        || rc == NGX_HTTP_REQUEST_TIME_OUT
        || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
        || c->error)
    {
        if (ngx_http_post_action(r) == NGX_OK) {
            return;
        }

        if (r->main->blocked) {
            r->write_event_handler = ngx_http_request_finalizer;
        }

        ngx_http_terminate_request(r, rc);
        return;
    }

在收到讀寫事件處理之前時連接不可用

1、在一個upstream出錯,執行next_upstream時也會判斷連接是否可用,不可用則返回499

2、server處理請求未結束,而client提前關閉了連接

 

3、故障排除

nginx配置中加上

proxy_ignore_client_abort  on;  #表示代理服務端不要主要主動關閉客戶端連接。 

預設 proxy_ignore_client_abort 是關閉的,

關閉時:如果客戶端端主動關閉請求或者客戶端網路斷掉, Nginx 會記錄 499,同時 request_time 是「後端已經處理」的時間,而upstream_response_time 為“-“ (已驗證)。

開啟時:如果客戶端端主動關閉請求或者客戶端網路斷掉,Nginx 會等待後端處理完(或者超時),然後記錄「後端的返回信息」到日誌。所以,如果後端返回 200,就記錄 200 ;如果後端放回 5XX ,那麼就記錄 5XX 。

如果超時(預設60s,可以用 proxy_read_timeout 設置),Nginx 會主動斷開連接,記錄 504

註:只在做反向代理的時候加入,作為其他伺服器的時候,關閉為好,預設設置是關閉的!

  

參考文章

http://blog.hexu.org/archives/1085.shtml

http://stackoverflow.com/questions/12973304/nginx-499-error-codes

https://httpstatuses.com/499

http://wmcxy.iteye.com/blog/2026835

http://ju.outofmemory.cn/entry/228858

http://www.90arther.net/jekyll/update/2015/11/19/repeat-request.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 標題:sed命令的使用 作用:sed是以行為單位處理文本數據,可以對數據按行進行選取(顯示)、替換、刪除和新增等功能。 一、用法 sed [-nefr] [動作] 參數: -n:使用安靜模式,取消自動列印模式空間。在一般來自STDIN的數據一般都會被列出到屏幕上,但如果加上-n參數後,則只有經過se ...
  • 1、在mac上安裝好了mysql-5.7.14 ,會自動生成一個初始密碼,這個初始密碼一定要記住: 在終端中輸入:mysql -u root -p,提示:mysql: command not found。這是因為沒有配置環境變數; 2、配置環境變數,即配置.bash_profile文件,~/.zsh ...
  • 今日頭條創立於2012年3月,到目前僅4年時間。從十幾個工程師開始研發,到上百人,再到200餘人。產品線由內涵段子,到今日頭條,今日特賣,今日電影等產品線。 一、產品背景 今日頭條是為用戶提供個性化資訊客戶端。下麵就和大家分享一下當前今日頭條的數據(據內部與公開數據綜合): 5億註冊用戶 2014年 ...
  • 本文介紹RHEL7下which、whereis、locate、find命令的使用,重點介紹find命令的使用 which 命令:which 作用:查找命令的執行文件路徑 語法:which [選項] [ ] 名稱... 說明:which命令比較簡單,他的選項都是不常用的 whereis 命令:wher ...
  • 本文介紹RHEL7.2文件的歸檔和壓縮 文件歸檔 歸檔的好處:方便使用、查詢、閱讀,易於管理 (批量刪除文件) 常用操作 命令:tar 作用:將許多文件一起保存至一個單獨的磁帶或磁碟歸檔,並能從歸檔中單獨還原所需文件 用法: tar [選項...] [FILE]... | 選項 | 說明 | | : ...
  • 進程概念 | 名稱 | 說明 | | : | : | | 程式 | 一組指令的集合 | | 進程 |程式的執行就是進程也可以把進程看成一個獨立的程式在記憶體中有其對應的代碼空間和數據空間,一個進程所擁有的數據和代碼只屬於自己進程是資源分配的基本單位,也是調度運行的基本單位 | | 線程 | 線程被人們 ...
  • 一、問題起源 在Linux系統中,通過rm刪除文件將會從文件系統的目錄結構上解除鏈接(unlink),如果文件是被打開的(有一個進程正在使用),那麼進程將仍然可以讀取該文件磁碟空間也一直被占用 這樣就會導致我們明明刪除了文件,但是磁碟空間卻未被釋放 二、問題分析 1、首先獲得一個已經被刪除但是仍然被 ...
  • 》進程式控制制塊 在linux中進程信息存放在叫做進程式控制制塊的數據結構中,每個進程在內核中都有⼀個進程式控制制塊(PCB)來維護進程相關的信息,Linux內核的 進程式控制制塊是task_struct結構體。在Linux中,這個結構叫做task_struct。 task_struct是Linux內核的一種數據結 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...