source: bin/varnishd/cache_session.c @ 8a27e66

Revision 8a27e66, 6.8 KB checked in by Poul-Henning Kamp <phk@…>, 5 years ago (diff)

Remove the client source address accounting, it is unused and a performance
bottleneck.

The original idea was anti-DoS measures along the lines of

sub vcl_recv {

if (client.bandwith > 1 mbit/s) {

delay (100 ms);

}

}

But there are does not seem to be a pressing need, wherefore it has
never been completed, and even if it was, it would not solve the
problem across a server farm.

git-svn-id:  http://www.varnish-cache.org/svn/trunk/varnish-cache@3884 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2008 Linpro AS
4 * All rights reserved.
5 *
6 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id$
30 *
31 * Session and Client management.
32 *
33 * XXX: The two-list session management is actually not a good idea
34 * XXX: come to think of it, because we want the sessions reused in
35 * XXX: Most Recently Used order.
36 * XXX: Another and maybe more interesting option would be to cache
37 * XXX: free sessions in the worker threads and postpone session
38 * XXX: allocation until then.  This does not quite implment MRU order
39 * XXX: but it does save some locking, although not that much because
40 * XXX: we still have to do the source-addr lookup.
41 */
42
43#include "config.h"
44
45#include <stdlib.h>
46#include <string.h>
47#include <math.h>
48#include <sys/uio.h>
49#include <sys/socket.h>
50
51#include "shmlog.h"
52#include "cache.h"
53#include "cache_backend.h"
54
55/*--------------------------------------------------------------------*/
56
57struct sessmem {
58        unsigned                magic;
59#define SESSMEM_MAGIC           0x555859c5
60
61        struct sess             sess;
62        struct http             http[2];
63        unsigned                workspace;
64        VTAILQ_ENTRY(sessmem)   list;
65        struct sockaddr_storage sockaddr[2];
66};
67
68static VTAILQ_HEAD(,sessmem)    ses_free_mem[2] = {
69    VTAILQ_HEAD_INITIALIZER(ses_free_mem[0]),
70    VTAILQ_HEAD_INITIALIZER(ses_free_mem[1]),
71};
72
73static unsigned ses_qp;
74static struct lock              ses_mem_mtx;
75
76/*--------------------------------------------------------------------*/
77
78static struct lock              stat_mtx;
79
80/*--------------------------------------------------------------------*/
81
82static void
83ses_sum_acct(struct acct *sum, const struct acct *inc)
84{
85
86#define ACCT(foo)       sum->foo += inc->foo;
87#include "acct_fields.h"
88#undef ACCT
89}
90
91void
92SES_Charge(struct sess *sp)
93{
94        struct acct *a = &sp->acct_req;
95
96        ses_sum_acct(&sp->acct, a);
97        Lck_Lock(&stat_mtx);
98#define ACCT(foo)       VSL_stats->s_##foo += a->foo;
99#include "acct_fields.h"
100#undef ACCT
101        Lck_Unlock(&stat_mtx);
102        memset(a, 0, sizeof *a);
103}
104
105/*--------------------------------------------------------------------*/
106
107struct sess *
108SES_New(const struct sockaddr *addr, unsigned len)
109{
110        struct sessmem *sm;
111        struct sess *sp;
112        volatile unsigned u;
113
114        /*
115         * One of the two queues is unlocked because only one
116         * thread ever gets here to empty it.
117         */
118        assert(ses_qp <= 1);
119        sm = VTAILQ_FIRST(&ses_free_mem[ses_qp]);
120        if (sm == NULL) {
121                /*
122                 * If that queue is empty, flip queues holding the lock
123                 * and try the new unlocked queue.
124                 */
125                Lck_Lock(&ses_mem_mtx);
126                ses_qp = 1 - ses_qp;
127                Lck_Unlock(&ses_mem_mtx);
128                sm = VTAILQ_FIRST(&ses_free_mem[ses_qp]);
129        }
130        if (sm != NULL) {
131                VTAILQ_REMOVE(&ses_free_mem[ses_qp], sm, list);
132        } else {
133                /*
134                 * If that fails, alloc new one.
135                 *
136                 * It is not necessary to lock mem_workspace, but we
137                 * need to cache it locally, to make sure we get a
138                 * consistent view of it.
139                 */
140                u = params->sess_workspace;
141                sm = malloc(sizeof *sm + u);
142                if (sm == NULL)
143                        return (NULL);
144                sm->magic = SESSMEM_MAGIC;
145                sm->workspace = u;
146                VSL_stats->n_sess_mem++;
147        }
148        CHECK_OBJ_NOTNULL(sm, SESSMEM_MAGIC);
149        VSL_stats->n_sess++;
150        sp = &sm->sess;
151        memset(sp, 0, sizeof *sp);
152        sp->magic = SESS_MAGIC;
153        sp->mem = sm;
154        sp->sockaddr = (void*)(&sm->sockaddr[0]);
155        sp->sockaddrlen = sizeof(sm->sockaddr[0]);
156        sp->mysockaddr = (void*)(&sm->sockaddr[1]);
157        sp->mysockaddrlen = sizeof(sm->sockaddr[1]);
158        sp->sockaddr->sa_family = sp->mysockaddr->sa_family = PF_UNSPEC;
159        sp->t_open = NAN;
160        sp->t_req = NAN;
161        sp->t_resp = NAN;
162        sp->t_end = NAN;
163        sp->grace = NAN;
164
165        assert(len <= sp->sockaddrlen);
166        if (addr != NULL) {
167                memcpy(sp->sockaddr, addr, len);
168                sp->sockaddrlen = len;
169        }
170
171        WS_Init(sp->ws, "sess", (void *)(sm + 1), sm->workspace);
172        sp->http = &sm->http[0];
173        sp->http0 = &sm->http[1];
174
175        SES_ResetBackendTimeouts(sp);
176
177        return (sp);
178}
179
180void
181SES_Delete(struct sess *sp)
182{
183        struct acct *b = &sp->acct;
184        struct sessmem *sm;
185
186        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
187        sm = sp->mem;
188        CHECK_OBJ_NOTNULL(sm, SESSMEM_MAGIC);
189
190        AZ(sp->obj);
191        AZ(sp->vcl);
192        VSL_stats->n_sess--;
193        assert(!isnan(b->first));
194        assert(!isnan(sp->t_end));
195        VSL(SLT_StatSess, sp->id, "%s %s %.0f %ju %ju %ju %ju %ju %ju %ju",
196            sp->addr, sp->port, sp->t_end - b->first,
197            b->sess, b->req, b->pipe, b->pass,
198            b->fetch, b->hdrbytes, b->bodybytes);
199        if (sm->workspace != params->sess_workspace) {
200                VSL_stats->n_sess_mem--;
201                free(sm);
202        } else {
203                Lck_Lock(&ses_mem_mtx);
204                VTAILQ_INSERT_HEAD(&ses_free_mem[1 - ses_qp], sm, list);
205                Lck_Unlock(&ses_mem_mtx);
206        }
207}
208
209/*--------------------------------------------------------------------*/
210
211void
212SES_Init()
213{
214
215        Lck_New(&stat_mtx);
216        Lck_New(&ses_mem_mtx);
217}
218
219void
220SES_ResetBackendTimeouts(struct sess *sp)
221{
222        sp->connect_timeout = params->connect_timeout;
223        sp->first_byte_timeout = params->first_byte_timeout;
224        sp->between_bytes_timeout = params->between_bytes_timeout;
225}
226
227void
228SES_InheritBackendTimeouts(struct sess *sp)
229{
230        struct backend *be;
231
232        AN(sp);
233        AN(sp->vbe);
234        AN(sp->vbe->backend);
235
236        be = sp->vbe->backend;
237        /*
238         * We only inherit the backend's timeout if the session timeout
239         * has not already been set in the VCL, as the order of precedence
240         * is parameter < backend definition < VCL.
241         */
242        if (be->connect_timeout > 1e-3 && 
243            sp->connect_timeout == params->connect_timeout)
244                sp->connect_timeout = be->connect_timeout;
245        if (be->first_byte_timeout > 1e-3 && 
246            sp->first_byte_timeout == params->first_byte_timeout)
247                sp->first_byte_timeout = be->first_byte_timeout;
248        if (be->between_bytes_timeout > 1e-3 &&
249            sp->between_bytes_timeout == params->between_bytes_timeout)
250                sp->between_bytes_timeout = be->between_bytes_timeout;
251}
Note: See TracBrowser for help on using the repository browser.