double dnsttl;
double dnstime;
+
+ int health;
+ double last_check;
+ int minute_limit;
+
#if 0
double responsetime;
double timeout;
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 */
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);
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;
}
}
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.
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 *
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
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 { \
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 *);
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");
}
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");
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");
}
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 *"
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 }
};
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",