]> err.no Git - varnish/commitdiff
Added a health parameter for the backend. This is readable in vcl with backend.health.
authorcecilihf <cecilihf@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 27 Jul 2007 14:16:39 +0000 (14:16 +0000)
committercecilihf <cecilihf@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 27 Jul 2007 14:16:39 +0000 (14:16 +0000)
Made it possible to pass a vcl variable to error (error 200 backend.health).
Implemented a first attempt at an algorithm for checking the health of a backend.
Negative values means the backend has problems, positive values means it is ok. 0 is neutral,
and could mean that it has been a while since the backend was asked for anything.
See the code for details.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1778 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_center.c
varnish-cache/bin/varnishd/cache_vrt.c
varnish-cache/include/vrt.h
varnish-cache/include/vrt_obj.h
varnish-cache/lib/libvcl/vcc_action.c
varnish-cache/lib/libvcl/vcc_fixed_token.c
varnish-cache/lib/libvcl/vcc_gen_obj.tcl
varnish-cache/lib/libvcl/vcc_obj.c
varnish-cache/lib/libvcl/vcc_string.c

index e2da5bf2bf5551c6443dd384dc85523ac34cf22d..951d2a04b28292aabd0a7bb54e442ff074f453cd 100644 (file)
@@ -332,6 +332,11 @@ struct backend {
 
        double                  dnsttl;
        double                  dnstime;
+
+       int                     health;
+       double                  last_check;
+       int                     minute_limit;
+       
 #if 0
        double                  responsetime;
        double                  timeout;
index 1bc6b44600e3fa40d95c849120d788862a0cc688..46b4cefee61cf7a273390b6ea101216c6bc000b4 100644 (file)
@@ -288,10 +288,35 @@ cnt_fetch(struct sess *sp)
 
        AN(sp->bereq);
        i = Fetch(sp);
+       
+       /* Experimental. Set time for last check of backend health.
+        * If the backend replied with 200, it is obviously up and running,
+        * increase health parameter. If we got a 504 back, it would imply
+        * that the backend is not reachable. Decrease health parameter.
+        */
+       sp->backend->last_check = TIM_mono();
+       sp->backend->minute_limit = 1;
+       if (!i){
+               if (http_GetStatus(sp->bereq->http) == 200) {
+                       if (sp->backend->health < 10000)
+                               sp->backend->health++;
+               } else if(http_GetStatus(sp->bereq->http) == 504) {
+                       if (sp->backend->health > -10000)
+                               sp->backend->health--;
+               }
+       }
+       
+               
        vbe_free_bereq(sp->bereq);
        sp->bereq = NULL;
 
        if (i) {
+               /* Experimental. If the fetch failed, it would also seem
+                * to be a backend problem, so decrease the health parameter.
+                */
+               if (sp->backend->health > -10000)
+                       sp->backend->health--;
+               
                SYN_ErrorPage(sp, 503, "Error talking to backend", 30);
        } else {
                RFC2616_cache_policy(sp, &sp->obj->http);       /* XXX -> VCL */
@@ -372,8 +397,19 @@ DOT hit -> deliver [label="deliver",style=bold,color=green,weight=4]
 static int
 cnt_hit(struct sess *sp)
 {
+       double time_diff;
+       double minutes;
 
        assert(!sp->obj->pass);
+       
+       /* Experimental. Reduce health parameter of backend towards zero
+        * if it has been more than a minute since it was checked. */
+       time_diff = TIM_mono() - sp->backend->last_check;
+       minutes = time_diff / 60;
+       if (minutes > sp->backend->minute_limit) {
+               sp->backend->minute_limit++;
+               sp->backend->health = (int)((double)sp->backend->health / 2);
+       }
 
        VCL_hit_method(sp);
 
index 04b92f02b26a412160127ac67797c82401030f58..d393c7cf2ea6b763e53d09a7840063aff7656c6f 100644 (file)
@@ -289,6 +289,9 @@ VRT_alloc_backends(struct VCL_conf *cp)
                cp->backend[i]->magic = BACKEND_MAGIC;
                cp->backend[i]->dnsttl = 30;
                TAILQ_INIT(&cp->backend[i]->connlist);
+               cp->backend[i]->health = 0;
+               cp->backend[i]->last_check = TIM_mono();
+               cp->backend[i]->minute_limit = 1;
        }
 }
 
@@ -320,6 +323,7 @@ VBACKEND(const char *,      host,   hostname)
 VBACKEND(const char *, port,   portname)
 VBACKEND(double,       dnsttl, dnsttl)
 
+
 /*--------------------------------------------------------------------
  * XXX: Working relative to t_req is maybe not the right thing, we could
  * XXX: have spent a long time talking to the backend since then.
@@ -487,6 +491,15 @@ VRT_r_obj_lastuse(struct sess *sp)
        return (TIM_mono() - sp->obj->lru_stamp);
 }
 
+int
+VRT_r_backend_health(struct sess *sp)
+{
+       
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
+       return sp->backend->health;
+}
+
 /*--------------------------------------------------------------------*/
 
 char *
@@ -514,6 +527,18 @@ VRT_IP_string(struct sess *sp, struct sockaddr *sa)
        return (q);
 }
 
+char *
+VRT_int_string(struct sess *sp, int num)
+{
+       char *p;
+       int size = 10;
+       
+       p = WS_Alloc(sp->http->ws, size);
+       AN(p);
+       snprintf(p, size, "%d", num);
+       return (p);
+}
+
 /*--------------------------------------------------------------------*/
 
 void
index 2cf5f7efcf39fab805eaac532dda380915215623..7edf14f42a17486501c45fe76bb6ac4d2aea5bf7 100644 (file)
@@ -89,6 +89,7 @@ void VRT_free_backends(struct VCL_conf *cp);
 void VRT_fini_backend(struct backend *be);
 
 char *VRT_IP_string(struct sess *sp, struct sockaddr *sa);
+char *VRT_int_string(struct sess *sp, int);
 
 #define VRT_done(sp, hand)                     \
        do {                                    \
index 2d65ca2f248098f35e72402c33ceefcc98949c78..9560ce7aa416a9cb684b2d0749ac973738f6458d 100644 (file)
@@ -46,3 +46,4 @@ void VRT_l_resp_status(struct sess *, int);
 const char * VRT_r_resp_response(struct sess *);
 void VRT_l_resp_response(struct sess *, const char *, ...);
 double VRT_r_now(struct sess *);
+int VRT_r_backend_health(struct sess *);
index 181abe23cfaf8fd9b45431a2e77a897b85f1d31f..9b007e0a32ad85b65ef520fd78cfdcf7955f8da8 100644 (file)
@@ -84,6 +84,9 @@ parse_error(struct tokenlist *tl)
        if (tl->t->tok == CSTR) {
                Fb(tl, 0, ", %.*s", PF(tl->t));
                vcc_NextToken(tl);
+       } else if (tl->t->tok == VAR) {
+               Fb(tl, 0, ", ");
+               vcc_StringVal(tl);
        } else {
                Fb(tl, 0, ", (const char *)0");
        }
index 07e30c5687292c5ac600142c8f4e9d75726d6cd5..4cb1f77bf79747e1cf2a1ddb43f5239debf01fd4 100644 (file)
@@ -445,6 +445,7 @@ vcl_output_lang_h(struct vsb *sb)
        vsb_cat(sb, "void VRT_fini_backend(struct backend *be);\n");
        vsb_cat(sb, "\n");
        vsb_cat(sb, "char *VRT_IP_string(struct sess *sp, struct sockaddr *sa);\n");
+       vsb_cat(sb, "char *VRT_int_string(struct sess *sp, int);\n");
        vsb_cat(sb, "\n");
        vsb_cat(sb, "#define VRT_done(sp, hand)                 \\\n");
        vsb_cat(sb, "   do {                                    \\\n");
@@ -499,4 +500,5 @@ vcl_output_lang_h(struct vsb *sb)
        vsb_cat(sb, "const char * VRT_r_resp_response(struct sess *);\n");
        vsb_cat(sb, "void VRT_l_resp_response(struct sess *, const char *, ...);\n");
        vsb_cat(sb, "double VRT_r_now(struct sess *);\n");
+       vsb_cat(sb, "int VRT_r_backend_health(struct sess *);\n");
 }
index 8d691ffeea1bf14df1ccf0b284ccd0353bf1b0ab..315ab05e2f1028d3dda8abe2f61f95f3d556381c 100755 (executable)
@@ -164,6 +164,10 @@ set spobj {
                RO TIME
                {recv pipe pass hash miss hit fetch deliver discard timeout}
        }
+       { backend.health        RO INT
+               {recv pipe pass hash miss hit fetch deliver discard timeout}
+       }
+
 }
 
 set tt(IP)     "struct sockaddr *"
index b0930662e88ff7d325f0ee06cd3ee1b70ff27c52..e016aad62e23b80b5b1425ccf77980b8ed5ba8c4 100644 (file)
@@ -210,5 +210,12 @@ struct var vcc_vars[] = {
            0,
            VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER | VCL_MET_DISCARD | VCL_MET_TIMEOUT
        },
+       { "backend.health", INT, 14,
+           "VRT_r_backend_health(sp)",
+           NULL,
+           V_RO,
+           0,
+           VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER | VCL_MET_DISCARD | VCL_MET_TIMEOUT
+       },
        { NULL }
 };
index b50a736164d5762d10cb93290321dfa1ee607a19..80eb0972ba364d0eb78f07ead72d23c1c1a4c638 100644 (file)
@@ -140,6 +140,9 @@ vcc_StringVal(struct tokenlist *tl)
                case IP:
                        Fb(tl, 0, "VRT_IP_string(sp, %s)", vp->rname);
                        break;
+               case INT:
+                       Fb(tl, 0, "VRT_int_string(sp, %s)", vp->rname);
+                       break;
                default:
                        vsb_printf(tl->sb,
                            "String representation of '%s' not implemented yet.\n",