높은 동시 서버 설계 - 연결 풀 설계
풀(pool)의 디자인은 주로 일부 자원의 빈번한 신청과 방출을 고려한다. 특히 높은 병발 서버에서 수만, 심지어 수십만 개의 병발 초마다 디자이너들은 이런 것들을 고려해야 한다.
예를 들어 데이터베이스 연결 탱크(sqlpool)는 TCP를 통해 통신하는 것으로 IO류에 속하며 일정한 지연이 있어 높은 병발 시스템에서 빈번한 창설은 시스템 성능에 심각한 영향을 줄 수 있다.
메모리(mem)의 분배는 자물쇠(mutex)와 관련된 것이기 때문에 자물쇠가 있으면 시간이 지연되기 때문에 큰 메모리를 신청하고 그 다음에 분배와 방출을 해서 자물쇠 비용을 절약할 수 있다.
서버의 연결 처리는 메모리뿐만 아니라 일부 속성의 값도 관련된다. 이것은 CPU 시간을 차지하는 것이다. 만약에 처음부터 대량의 연결을 만들면 나중에 다시 사용하기 편리하다.
다음은 데이터베이스 연결 풀을 예로 들어 연결의 구조를 정의합니다.
typedef struct tst_sql_s tst_sql_t;
struct tst_sql_s{
MYSQL *sql;
tst_sql_t *next;
tst_sql_t *prev;
};
현실 개발에서 나는 (free-busi) 모델로 연못을 설계하는 것을 좋아한다는 것을 발견했다.
struct tst_sql_pool_s
{
tst_sql_t *free_sql;
tst_sql_t *busi_sql;
…
};
풀의 연결을 두 부분으로 나누면 일부는 빈 (free), 일부는 사용 중인 (busi), 함수:
tst_sql_t* tst_sql_pool_get( tst_sql_pool_t* pool )
{
tst_sql_t *sql;
if( !pool ){
return 0;
}
sql = pool->free_sql;
if( !sql ){
return 0;
}
pool->free_sql = sql->next;
sql->next = pool->busi_sql;
sql->prev = 0;
if( pool->busi_sql ){
pool->busi_sql->prev = sql;
}
pool->busi_sql = sql;
return sql;
}
int tst_sql_pool_put( tst_sql_pool_t* pool, tst_sql_t* sql )
{
if( !pool || !sql ){
return 0;
}
if( sql->prev ){
sql->prev->next = sql->next;
}
else{
pool->busi_sql = sql->next;
}
if( sql->next ){
sql->next->prev = sql->prev;
}
sql->next = pool->free_sql;
pool->free_sql = sql;
return 0;
}
기본적으로 연못의 관리를 마쳤지만, 우리도 이 판단이 사실 매우 번거롭다는 것을 알 수 있다. 이렇게 번거롭게 하지 않아도 되는지 모르겠다.
위의 함수에서도 알 수 있듯이 번거로움은 주로 busi못에 있다. free못의 처리는 사실 매우 간단하기 때문에 다음과 같은 디자인이 있다.
연결 탱크는 빈 연결만 저장하고 연결 상태를 저장하지 않으며 상태의 구분을 관리 함수에 맡겨야 한다.
다음은 연결 탱크로 예를 들겠습니다.
나는 연결 탱크의 구조를 다시 설계했다.
typedef struct tst_conn_s tst_conn_t;
typedef struct tst_conn_pool_s tst_conn_pool_t;
struct tst_conn_s
{
int fd;
……..
……..
tst_conn_t* next;
};
struct tst_conn_pool_s
{
………
……….
tst_conn_t* conns;
};
풀 관리 함수:
tst_conn_t* tst_conn_pool_get( tst_conn_pool_t* pool )
{
tst_conn_t* conn;
if( !pool ){
return 0;
}
conn = pool->conns;
if( !conn ){
return 0;
}
pool->conns = conn->next;
return conn;
}
#define TST_CONN_POOL_ERROR -1
#define TST_CONN_POOL_OK 0
int tst_conn_pool_put( tst_conn_pool_t* pool, tst_conn_t* conn )
{
if( !pool || !conn ){
return TST_CONN_POOL_ERROR;
}
conn->next = pool->conns;
pool->conns = conn;
return TST_CONN_POOL_OK;
}
이렇게 하면 연결 탱크의 분배와 회수 기능을 한다.
일반적으로 디자인에 있어서 모듈의 투명성을 높이고 결합을 낮춘다. 나는 탱크의 관리를 모듈 내부에 놓고 대외적으로 일치성 인터페이스만 제공한다.
#define TST_CONN_POOL_ERROR -1
#define TST_CONN_POOL_OK 0
tst_conn_t* tst_conn_get();
int tst_conn_free( tst_conn_t* conn );
모듈 내부는 하나의 전역적인 탱크로 모듈 내에서 통일된 관리를 한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
APP 는 위 챗 결 제 를 9582 ℃ (~) 에서 9581 ℃ (JAVA 서버 개발) 로 조정 합 니 다.최근 앱 을 통 해 위 챗 결 제 를 하고 있 습 니 다. 2. 지불 대기 주문 서 를 생 성 합 니 다. 위 챗 결제 방식 은 자줏빛 입 니 다. 선생님 은 지불 대기 주문 서 를 작성 한 다음 에 지불 대기 주문...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.