Skip to content
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

Merged
merged 24 commits into from
Mar 27, 2017
Merged

Sticky sessions implementation #713

merged 24 commits into from
Mar 27, 2017

Conversation

vankoven
Copy link
Contributor

Change log:

comment #76 (comment) not implemented in the patch, instead i work on it in separate branch since some discussion may be needed.

@@ -78,12 +79,12 @@ typedef struct {
spinlock_t lock;
} SessHashBucket;

static TfwCfgSticky tfw_cfg_sticky;
static TfwCfgSticky tfw_cfg_sticky;
Copy link
Contributor

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?

.name = "sess_lifetime",
.deflt = "0",
.handler = tfw_cfg_set_int,
.handler = tfw_http_sticky_sess_lifetime_cfg,
.dest = &tfw_cfg_sticky.sess_lifetime,
Copy link
Contributor

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.

Copy link
Contributor Author

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.

.dest = &tfw_cfg_sticky.sess_lifetime,
.spec_ext = &(TfwCfgSpecInt) {
.range = { 0, INT_MAX },
},
.allow_none = true,
Copy link
Contributor

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.

int r = tfw_cfg_set_int(cs, ce);

/* @sess_lifetime value of 0 means unlimited. */
if (!r && !tfw_cfg_sticky.sess_lifetime)
Copy link
Contributor

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?

Copy link
Contributor Author

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;

Copy link
Contributor

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).

* 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.
Copy link
Contributor

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.

TfwSrvConn *srv_conn;
TfwSrvGroup *main_sg;
TfwSrvGroup *backup_sg;
rwlock_t conn_lock;
Copy link
Contributor

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.

Copy link
Contributor

@krizhanovsky krizhanovsky left a 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.

static SessHashBucket sess_hash[SESS_HASH_SZ] = {
// [0 ... (SESS_HASH_SZ - 1)] = {
// HLIST_HEAD_INIT,
// }
Copy link
Contributor

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.

Copy link
Contributor Author

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.

@@ -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))) {
Copy link
Contributor

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;
};

Copy link
Contributor

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?

Copy link
Contributor Author

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.

* scheduling work flow.
*/
static inline TfwSrvConn *
__get_sticky_srv_conn(TfwMsg *msg, TfwHttpSess *sess)
Copy link
Contributor

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.

TfwStickyConn *st_conn = &sess->st_conn;
TfwSrvConn *srv_conn;

read_lock(&st_conn->lock);
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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);
Copy link
Contributor

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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vankoven vankoven merged commit dfa12c9 into master Mar 27, 2017
@vankoven vankoven deleted the ik-sticky-sessions-ng branch March 27, 2017 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Sticky sessions scheduler
3 participants