[CP][Bugfix][OBKV]fix session pool hold too much memory when login frequently
This commit is contained in:
@ -33,7 +33,7 @@ int ObTableApiSessPoolMgr::mtl_init(ObTableApiSessPoolMgr *&mgr)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
start tableapi retired session task
|
start tableapi retired session task
|
||||||
- 60 second interval
|
- 5 second interval
|
||||||
- repeated
|
- repeated
|
||||||
*/
|
*/
|
||||||
int ObTableApiSessPoolMgr::start()
|
int ObTableApiSessPoolMgr::start()
|
||||||
@ -45,7 +45,7 @@ int ObTableApiSessPoolMgr::start()
|
|||||||
LOG_WARN("table api session pool mgr isn't inited", K(ret));
|
LOG_WARN("table api session pool mgr isn't inited", K(ret));
|
||||||
} else if (OB_FAIL(TG_SCHEDULE(MTL(omt::ObSharedTimer*)->get_tg_id(),
|
} else if (OB_FAIL(TG_SCHEDULE(MTL(omt::ObSharedTimer*)->get_tg_id(),
|
||||||
elimination_task_,
|
elimination_task_,
|
||||||
ELIMINATE_SESSION_DELAY/* 60s */,
|
ELIMINATE_SESSION_DELAY/* 5s */,
|
||||||
true/* repeat */))) {
|
true/* repeat */))) {
|
||||||
LOG_WARN("failed to schedule tableapi retired session task", K(ret));
|
LOG_WARN("failed to schedule tableapi retired session task", K(ret));
|
||||||
} else {
|
} else {
|
||||||
@ -377,7 +377,7 @@ int ObTableApiSessPool::move_node_to_retired_list(ObTableApiSessNode *node)
|
|||||||
1. remove session val in free_list.
|
1. remove session val in free_list.
|
||||||
2. remove session node from retired_nodes_ when node is empty.
|
2. remove session node from retired_nodes_ when node is empty.
|
||||||
3. free node memory.
|
3. free node memory.
|
||||||
4. delete 1000 session nodes per times
|
4. delete 2000 session nodes per times
|
||||||
*/
|
*/
|
||||||
int ObTableApiSessPool::evict_retired_sess()
|
int ObTableApiSessPool::evict_retired_sess()
|
||||||
{
|
{
|
||||||
@ -387,7 +387,7 @@ int ObTableApiSessPool::evict_retired_sess()
|
|||||||
ObLockGuard<ObSpinLock> guard(retired_nodes_lock_); // lock retired_nodes_
|
ObLockGuard<ObSpinLock> guard(retired_nodes_lock_); // lock retired_nodes_
|
||||||
|
|
||||||
DLIST_FOREACH_REMOVESAFE_X(node, retired_nodes_, delete_count < BACKCROUND_TASK_DELETE_SESS_NUM) {
|
DLIST_FOREACH_REMOVESAFE_X(node, retired_nodes_, delete_count < BACKCROUND_TASK_DELETE_SESS_NUM) {
|
||||||
if (cur_time - node->get_last_active_ts() < SESS_RETIRE_TIME) {
|
if (cur_time - node->get_last_active_ts() < SESS_UPDATE_TIME_INTERVAL) {
|
||||||
// do nothing, this node maybe is from ObTableApiSessNodeReplaceOp, some threads maybe is using it.
|
// do nothing, this node maybe is from ObTableApiSessNodeReplaceOp, some threads maybe is using it.
|
||||||
// we remove it next retire task.
|
// we remove it next retire task.
|
||||||
} else if (OB_FAIL(node->remove_unused_sess())) {
|
} else if (OB_FAIL(node->remove_unused_sess())) {
|
||||||
@ -545,23 +545,31 @@ int ObTableApiSessPool::create_and_add_node_safe(ObTableApiCredential &credentia
|
|||||||
/*
|
/*
|
||||||
1. only call in login
|
1. only call in login
|
||||||
2. move old to retired list when node exist, create new node otherwise.
|
2. move old to retired list when node exist, create new node otherwise.
|
||||||
|
3. if the update interval is less than 5 seconds, ignore this update.
|
||||||
*/
|
*/
|
||||||
int ObTableApiSessPool::update_sess(ObTableApiCredential &credential)
|
int ObTableApiSessPool::update_sess(ObTableApiCredential &credential)
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
|
|
||||||
ObTableApiSessNode *node = nullptr;
|
ObTableApiSessNode *node = nullptr;
|
||||||
const uint64_t key = credential.hash_val_;
|
const uint64_t key = credential.hash_val_;
|
||||||
|
int64_t cur_time = ObTimeUtility::current_time();
|
||||||
|
|
||||||
if (OB_FAIL(get_sess_node(key, node))) {
|
if (OB_FAIL(get_sess_node(key, node))) {
|
||||||
if (OB_HASH_NOT_EXIST == ret) { // not exist, create
|
if (OB_HASH_NOT_EXIST == ret) { // not exist, create
|
||||||
if (OB_FAIL(create_and_add_node_safe(credential))) {
|
if (OB_FAIL(create_and_add_node_safe(credential))) {
|
||||||
LOG_WARN("fail to create and add node", K(ret), K(credential));
|
LOG_WARN("fail to create and add node", K(ret), K(credential));
|
||||||
|
} else {
|
||||||
|
ATOMIC_STORE(&last_update_ts_, cur_time);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_WARN("fail to get session node", K(ret), K(key));
|
LOG_WARN("fail to get session node", K(ret), K(key));
|
||||||
}
|
}
|
||||||
|
} else if (cur_time - last_update_ts_ < SESS_UPDATE_TIME_INTERVAL) {
|
||||||
|
// if the update interval is less than 5 seconds, ignore this update.
|
||||||
} else if (OB_FAIL(replace_sess_node_safe(credential))) { // exist, create and replace old node
|
} else if (OB_FAIL(replace_sess_node_safe(credential))) { // exist, create and replace old node
|
||||||
LOG_WARN("fail to replace session node", K(ret), K(credential));
|
LOG_WARN("fail to replace session node", K(ret), K(credential));
|
||||||
|
} else {
|
||||||
|
ATOMIC_STORE(&last_update_ts_, cur_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@ -70,7 +70,7 @@ private:
|
|||||||
int create_session_pool_safe();
|
int create_session_pool_safe();
|
||||||
int create_session_pool_unsafe();
|
int create_session_pool_unsafe();
|
||||||
private:
|
private:
|
||||||
static const int64_t ELIMINATE_SESSION_DELAY = 60 * 1000 * 1000; // 60s
|
static const int64_t ELIMINATE_SESSION_DELAY = 5 * 1000 * 1000; // 5s
|
||||||
bool is_inited_;
|
bool is_inited_;
|
||||||
common::ObArenaAllocator allocator_;
|
common::ObArenaAllocator allocator_;
|
||||||
ObTableApiSessPool *pool_;
|
ObTableApiSessPool *pool_;
|
||||||
@ -87,13 +87,15 @@ class ObTableApiSessPool final
|
|||||||
public:
|
public:
|
||||||
// key is ObTableApiCredential.hash_val_
|
// key is ObTableApiCredential.hash_val_
|
||||||
typedef common::hash::ObHashMap<uint64_t, ObTableApiSessNode*> CacheKeyNodeMap;
|
typedef common::hash::ObHashMap<uint64_t, ObTableApiSessNode*> CacheKeyNodeMap;
|
||||||
static const int64_t SESS_POOL_DEFAULT_BUCKET_NUM = 10; // 取决于客户端登录的用户数量
|
static const int64_t SESS_POOL_DEFAULT_BUCKET_NUM = 10; // default user number
|
||||||
static const int64_t SESS_RETIRE_TIME = 300 * 1000000; // 超过300s未被访问的session会被标记淘汰
|
static const int64_t SESS_RETIRE_TIME = 300 * 1000 * 1000; // marked as retired more than 300 seconds are not accessed
|
||||||
static const int64_t BACKCROUND_TASK_DELETE_SESS_NUM = 1000; // 后台任务每次删除淘汰的session node数量
|
static const int64_t BACKCROUND_TASK_DELETE_SESS_NUM = 2000; // number of eliminated session nodes in background task per time
|
||||||
|
static const int64_t SESS_UPDATE_TIME_INTERVAL = 5 * 1000 * 1000; // the update interval cannot exceed 5 seconds
|
||||||
public:
|
public:
|
||||||
explicit ObTableApiSessPool()
|
explicit ObTableApiSessPool()
|
||||||
: allocator_("TbSessPool", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()),
|
: allocator_("TbSessPool", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()),
|
||||||
is_inited_(false)
|
is_inited_(false),
|
||||||
|
last_update_ts_(0)
|
||||||
{}
|
{}
|
||||||
~ObTableApiSessPool() { destroy(); };
|
~ObTableApiSessPool() { destroy(); };
|
||||||
TO_STRING_KV(K_(is_inited),
|
TO_STRING_KV(K_(is_inited),
|
||||||
@ -120,6 +122,7 @@ private:
|
|||||||
// 前台login时、后台淘汰时都会操作retired_nodes_,因此需要加锁
|
// 前台login时、后台淘汰时都会操作retired_nodes_,因此需要加锁
|
||||||
common::ObDList<ObTableApiSessNode> retired_nodes_;
|
common::ObDList<ObTableApiSessNode> retired_nodes_;
|
||||||
ObSpinLock retired_nodes_lock_; // for lock retired_nodes_
|
ObSpinLock retired_nodes_lock_; // for lock retired_nodes_
|
||||||
|
int64_t last_update_ts_;
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(ObTableApiSessPool);
|
DISALLOW_COPY_AND_ASSIGN(ObTableApiSessPool);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -170,8 +170,7 @@ TEST_F(TestTableSessPool, mgr_update_session)
|
|||||||
ASSERT_NE(nullptr, mgr->pool_);
|
ASSERT_NE(nullptr, mgr->pool_);
|
||||||
ASSERT_TRUE(mgr->pool_->is_inited_);
|
ASSERT_TRUE(mgr->pool_->is_inited_);
|
||||||
ASSERT_EQ(1, mgr->pool_->key_node_map_.size());
|
ASSERT_EQ(1, mgr->pool_->key_node_map_.size());
|
||||||
ASSERT_EQ(1, mgr->pool_->retired_nodes_.size_);
|
ASSERT_EQ(0, mgr->pool_->retired_nodes_.size_);
|
||||||
ASSERT_EQ(node, mgr->pool_->retired_nodes_.get_last());
|
|
||||||
ASSERT_EQ(OB_SUCCESS, mgr->pool_->get_sess_node(new_cred->hash_val_, node));
|
ASSERT_EQ(OB_SUCCESS, mgr->pool_->get_sess_node(new_cred->hash_val_, node));
|
||||||
ASSERT_NE(nullptr, node);
|
ASSERT_NE(nullptr, node);
|
||||||
ASSERT_TRUE(node->sess_lists_.free_list_.is_empty());
|
ASSERT_TRUE(node->sess_lists_.free_list_.is_empty());
|
||||||
@ -184,7 +183,7 @@ TEST_F(TestTableSessPool, mgr_update_session)
|
|||||||
ASSERT_NE(nullptr, mgr->pool_);
|
ASSERT_NE(nullptr, mgr->pool_);
|
||||||
ASSERT_TRUE(mgr->pool_->is_inited_);
|
ASSERT_TRUE(mgr->pool_->is_inited_);
|
||||||
ASSERT_EQ(2, mgr->pool_->key_node_map_.size());
|
ASSERT_EQ(2, mgr->pool_->key_node_map_.size());
|
||||||
ASSERT_EQ(1, mgr->pool_->retired_nodes_.size_);
|
ASSERT_EQ(0, mgr->pool_->retired_nodes_.size_);
|
||||||
ASSERT_EQ(OB_SUCCESS, mgr->pool_->get_sess_node(new_cred->hash_val_, node));
|
ASSERT_EQ(OB_SUCCESS, mgr->pool_->get_sess_node(new_cred->hash_val_, node));
|
||||||
ASSERT_NE(nullptr, node);
|
ASSERT_NE(nullptr, node);
|
||||||
ASSERT_TRUE(node->sess_lists_.free_list_.is_empty());
|
ASSERT_TRUE(node->sess_lists_.free_list_.is_empty());
|
||||||
|
|||||||
Reference in New Issue
Block a user