varnish - 在 Varnish 中获取随机 "http first read error: EOF"错误

标签 varnish varnish-4

我不时在日志中看到 Varnish 中的以下 503 错误:

*   << BeReq    >> 213585014 
-   Begin          bereq 213585013 fetch
-   Timestamp      Start: 1452675822.032332 0.000000 0.000000
-   BereqMethod    GET
-   BereqURL       /client/hedge-funds-asset-managers/
-   BereqProtocol  HTTP/1.1
-   BereqHeader    X-Real-IP: 123.125.71.28
-   BereqHeader    Host: XXXXXXXXXXXXXXXXXXX
-   BereqHeader    X-Forwarded-Proto: http
-   BereqHeader    User-Agent: Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)
-   BereqHeader    Accept-Encoding: gzip
-   BereqHeader    Accept-Language: zh-cn,zh-tw
-   BereqHeader    Accept: */*
-   BereqHeader    X-Forwarded-For: 172.18.210.22
-   BereqHeader    X-Varnish: 213585014
-   VCL_call       BACKEND_FETCH
-   VCL_return     fetch
-   BackendOpen    232 reload_2016-01-12T07:28:50.cp_12 162.251.80.23 80 172.18.210.71 40019
-   Timestamp      Bereq: 1452675822.047840 0.015508 0.015508
-   FetchError     http first read error: EOF
-   BackendClose   232 reload_2016-01-12T07:28:50.cp_12
-   Timestamp      Beresp: 1452675876.038544 54.006212 53.990704
-   Timestamp      Error: 1452675876.038555 54.006223 0.000010
-   BerespProtocol HTTP/1.1
-   BerespStatus   503
-   BerespReason   Service Unavailable
-   BerespReason   Backend fetch failed
-   BerespHeader   Date: Wed, 13 Jan 2016 09:04:36 GMT
-   BerespHeader   Server: Varnish
-   VCL_call       BACKEND_ERROR
-   BerespHeader   Content-Type: text/html; charset=utf-8
-   BerespHeader   Retry-After: 5
-   VCL_return     deliver
-   Storage        malloc Transient
-   ObjProtocol    HTTP/1.1
-   ObjStatus      503
-   ObjReason      Backend fetch failed
-   ObjHeader      Date: Wed, 13 Jan 2016 09:04:36 GMT
-   ObjHeader      Server: Varnish
-   ObjHeader      Content-Type: text/html; charset=utf-8
-   ObjHeader      Retry-After: 5
-   Length         286
-   BereqAcct      350 0 350 0 0 0
-   End

问题不在于后端连接,因为从 varnish 服务器到相同 URL 的 curl 工作正常。 varnish 的版本是 4.1.0。我不确定“http first read error: EOF”是什么意思,感谢您对这个问题的任何了解。由于这个问题的随机性,我也没有办法重现它。

最佳答案

当您尝试在调用 vcl_fetch 之前从后端读取 header 时,Varnish 中会发生“首次读取错误” ,而 Varnish 未能得到回应。 TL;DR:您的后端要么在传递响应之前关闭连接,要么传递响应超时。您可以使用 wireshark 之类的工具来确定发生了这两种情况中的哪一种。

要了解发生了什么,让我们进行一些源代码潜水:

static int __match_proto__(vdi_gethdrs_f)
vbe_dir_gethdrs(const struct director *d, struct worker *wrk,
    struct busyobj *bo)
{
    int i, extrachance = 1;
    struct backend *bp;
    struct vbc *vbc;

    ...

    do {
            vbc = vbe_dir_getfd(wrk, bp, bo);

不要过多关注董事,vbe_dir_gethdrs Varnish 打开一个新连接,或决定重用一个连接后调用。

            if (vbc->state != VBC_STATE_STOLEN)
                    extrachance = 0;

如果我们重用一个连接,vbc->state设置为 VBC_STATE_STOLEN ( Varnish-Cache/bin/varnishd/cache/cache_backend_tcp.c364 )。当我们打开一个新连接时,这个值没有被设置。到目前为止,还不错。

            i = V1F_SendReq(wrk, bo, &bo->acct.bereq_hdrbytes, 0);
            if (vbc->state != VBC_STATE_USED)
                    VBT_Wait(wrk, vbc);

            assert(vbc->state == VBC_STATE_USED);

            if (i == 0)
                    i = V1F_FetchRespHdr(bo);

这样做是将请求发送到后端。如果一切顺利,我们将调用 V1F_FetchRespHdr ,它等待源发送其协议(protocol)响应和 header 。如果我们按照代码进入V1F_FetchRespHdr :

    VTCP_set_read_timeout(htc->fd, htc->first_byte_timeout);
    ...
    do {
        ...
        i = read(htc->fd, htc->rxbuf_e, i);
        if (i <= 0) {
            bo->acct.beresp_hdrbytes +=
                htc->rxbuf_e - htc->rxbuf_b;
            WS_ReleaseP(htc->ws, htc->rxbuf_b);
            VSLb(bo->vsl, SLT_FetchError, "http %sread error: EOF",
                first ? "first " : "");
            htc->doclose = SC_RX_TIMEOUT;
            return (first ? 1 : -1);
        }

在这里,我们看到我们在执行 read 之前在套接字上设置了超时。系统调用。如果此读取返回错误(< 0 情况)或 EOF(== 0 情况),并且这是我们第一次调用读取,我们最终会记录 http first read error: EOF正如您在 varnishlog 中看到的那样输出。

因此,如果您打开到后端的新连接,并且后端在发送请求后超时或关闭连接,则会出现此错误。

就个人而言,我会怀疑您的来源是否正在关闭连接;我认为超时通常更有可能。但是,如果您的后端认为它有太多打开的连接,或者它可能通过连接收到太多请求,或者类似的情况,连接可能会被关闭。

希望对您有所帮助!

关于varnish - 在 Varnish 中获取随机 "http first read error: EOF"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34762779/

相关文章:

Varnish http_req_hdr_len 参数不适用于请求 header 大小 > 8KB

varnish - 在Varnish 4中 'synthetic'设置了哪个变量?

amazon-web-services - ELB 保活超时 : Varnish Configuration Assistance

node.js - 在 EC2/Nodejs 后端 Redis/Varnish 中存储元数据和缓存 api 响应数据?

caching - 有和没有 Varnish 的情况下没有加载时间差

caching - Varnish 缓存-缓存403响应

varnish - 如何将第二个缓存更改为特定IP

caching - Drupal 7 & Varnish 4 - 我总是得到 X-Drupal-Cache : MISS but X-Cache: HIT

Varnish host_header不会发送到后端

c - Varnish 4 + Pounds - 绕过特定 IP 地址的缓存