-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sticky sessions implementation #713
Conversation
Default servers keep-alive configuration affect functional tests, set unlimited keep-alive requests count for functional tests.
tempesta_fw/http_sess.c
Outdated
@@ -78,12 +79,12 @@ typedef struct { | |||
spinlock_t lock; | |||
} SessHashBucket; | |||
|
|||
static TfwCfgSticky tfw_cfg_sticky; | |||
static TfwCfgSticky tfw_cfg_sticky; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a structure where members should be aligned. Why TABs are used here?
tempesta_fw/http_sess.c
Outdated
.name = "sess_lifetime", | ||
.deflt = "0", | ||
.handler = tfw_cfg_set_int, | ||
.handler = tfw_http_sticky_sess_lifetime_cfg, | ||
.dest = &tfw_cfg_sticky.sess_lifetime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way it is now, there's no need for .dest
. You'll have to know anyway which variable you need to use in the .handler
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In tfw_http_sticky_sess_lifetime_cfg
i use tfw_cfg_set_int
for parsing int value and check it for min-max borders. To use that i need to set .dest
either here or in tfw_http_sticky_sess_lifetime_cfg
.
tempesta_fw/http_sess.c
Outdated
.dest = &tfw_cfg_sticky.sess_lifetime, | ||
.spec_ext = &(TfwCfgSpecInt) { | ||
.range = { 0, INT_MAX }, | ||
}, | ||
.allow_none = true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps, this is not needed right now. The use crypto_free_shash()
dictates that there's a certain clean up procedure for it. That clean up is currently done in exit()
. That means that start()
/stop()
, and a possible reconfigure()
are not supported (without exiting the kernel module). Perhaps, it's a good idea to introduce a .cleanup()
here and unify that with exit
.
How to unify? Currently crypto_shash_setkey()
is called twice. Once in init()
, and the other time in tfw_http_sticky_secret_cfg()
. That presents a small bug already as there's no paired crypto_free_shash()
before another crypto_shash_setkey()
is called. Now, there should be just one place for that, and that place is in tfw_http_sticky_secret_cfg()
. The function should, perhaps, process a default zero length string that can be set as a .deflt = ""
value in the configuration specs for the directive.
tempesta_fw/http_sess.c
Outdated
int r = tfw_cfg_set_int(cs, ce); | ||
|
||
/* @sess_lifetime value of 0 means unlimited. */ | ||
if (!r && !tfw_cfg_sticky.sess_lifetime) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why a check for tfw_cfg_sticky.sess_lifetime
? Is there a meaning for multiple sess_lifetime
directives in the configuration file? I believe that you need to set .allow_repeat = false
in the specs for the directive.
Can other directives in this file be repeated for any meaningful need?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0
in terms of sess_lifetime
means unlimited
, but setting actually zero to the parameter makes session to be removed right after it was created. As discussed before, UINT_MAX
value should represent unlimited
value for the code, but for the user it should remain as 0
.
I can rewrite condition as follows if you find that more meaningful:
if (!r && !*(cs->dest))
*(cs->dest) = UINT_MAX;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that would make this function to NOT depend on the specific variable.
That would also make it generic for getting a number value for a directive, and setting is to max value if the number is zero (also a default value).
tempesta_fw/server.h
Outdated
* However, not all the schedulers are able to designate target server group. | ||
* If a scheduler determines server group, then it should register @sched_grp | ||
* callback. The callback determines the target server group which references | ||
* a scheduler responsible to distribute messages in the group. | ||
* For the avoidance of unnecessary calls, any @sched_grp callback must call | ||
* @sched_srv callback of the target scheduler. | ||
* @sched_sg_conn callback or @sched_srv_conn of the target scheduler. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unclear when each of the new callbacks is called and for what purpose. Please write a better description.
tempesta_fw/http_sess.h
Outdated
TfwSrvConn *srv_conn; | ||
TfwSrvGroup *main_sg; | ||
TfwSrvGroup *backup_sg; | ||
rwlock_t conn_lock; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, conn_lock
is confusing as the name suggests that is a lock for a connection. But it's not.
Usually, when a lock protects the whole structure its called just 'lock'. When the lock is used, the preceding part of a statement tells what exactly is protected by the lock, i.e. st_conn->lock
. If a lock protects only part of a structure, or a specific member of a structure, then a prefix is useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be merged after cleanups pointed out by the review comments. However, comments #713 (comment) and #713 (comment) are serious, but they can be addressed in further PR implementing #76 requirements.
tempesta_fw/http_sess.c
Outdated
static SessHashBucket sess_hash[SESS_HASH_SZ] = { | ||
// [0 ... (SESS_HASH_SZ - 1)] = { | ||
// HLIST_HEAD_INIT, | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use C++ style comments. Don't leave dead (just commented out) code. Why did you remove the initialization? I know that it's just zeroying, but using the initialization is still a good practice. At least use the list initializer in tfw_http_sess_init()
near to spinlock initialization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't want C++ comments to appear here. I use IDE with integrated clang code analysis and clang gets stuck on this initialization and the whole IDE hangs every time i make changes to this file. I will be twice more careful on sending patches next time.
tempesta_fw/http_sess.c
Outdated
@@ -565,7 +566,7 @@ tfw_http_sess_obtain(TfwHttpReq *req) | |||
goto found; | |||
} | |||
|
|||
if (!(sess = kmem_cache_alloc(sess_cache, GFP_ATOMIC))) { | |||
if (!(sess = kmem_cache_zalloc(sess_cache, GFP_ATOMIC))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use __GFP_ZERO w/o need, that's relatively expensive thing to make the kernel write zeroes to free pages. Instead, you can just write 3 NULLs to the new pointer fields.
unsigned long expires; | ||
TfwStickyConn st_conn; | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra empty line. Why do you define TfwHttpSess ouside of the file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In last PR i was advised by @keshonok to move all the session related definitions from http.h
to separate header. But TfwHttpSess
is required for TfwHttpReq
in http.h
and most functions in this header require definitions from http.h
, so circular dependency take place here.
As for me, advice was very valuable: http.h is too big and placing there more and more definitions only breaks it to loosely connected parts.
tempesta_fw/sched.c
Outdated
* scheduling work flow. | ||
*/ | ||
static inline TfwSrvConn * | ||
__get_sticky_srv_conn(TfwMsg *msg, TfwHttpSess *sess) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically, sched.c
isn't an appropriate place for Sticky cookie scheduling. sched.c
is the generic scheduling logic. __get_sticky_srv_conn()
, __try_conn()
and maybe some other functions are good candidates for http_sess.c or a new file sched/tfw_sched_sticky.c
. Also keep in mind #685 which is going to extend the logic even more.
tempesta_fw/sched.c
Outdated
TfwStickyConn *st_conn = &sess->st_conn; | ||
TfwSrvConn *srv_conn; | ||
|
||
read_lock(&st_conn->lock); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you use read lock for __try_conn()
which basically calls lock-free routines only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If session is under failovering, connection stored in sessions private data is no more valid. Even if original server is suddenly back online.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it better to use reference counting to make the session private data valid even under failovering?
|
||
return srv_conn; | ||
} | ||
EXPORT_SYMBOL(tfw_sched_get_sg_srv_conn); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please define the function before the first usage of it, i.e. before __get_sticky_srv_conn()
.
TfwServer *srv; | ||
TfwSrvConn *conn[TFW_SRV_MAX_CONN]; | ||
unsigned long hash[TFW_SRV_MAX_CONN]; | ||
} TfwHashSrv; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment https://github.com/tempesta-tech/tempesta/pull/666/files#r94275356 is still not addressed. I saw your PR https://github.com/tempesta-tech/tempesta/pull/714/files, but it's somehow already closed.
Change log:
comment #76 (comment) not implemented in the patch, instead i work on it in separate branch since some discussion may be needed.