本文分享自天翼雲開發者社區《nginx證書緩存功能》.作者:雲海
背景:
ssl證書之前是不支持公用的,不同的域名,如果引用同一本證書,是無法公用的,每個域名都要加載同一個證書,浪費內存
新版本:
在1.27.2版本中,nginx官方更新了ssl證書相關的實現,支持了ssl證書緩存共享。
實現原理:
在配置初始化時,初始了ssl證書緩存的紅黑樹:
ngx_openssl_cache_create_conf -> ngx_rbtree_init
在要獲取ssl證書時,通過如下接口獲取對應ssl證書:
ngx_ssl_cache_fetch
該接口的index參數可以傳遞不同的標記位,因為不同功能ssl證書有不同的創建釋放和引用增加處理
不同功能ssl證書有如下定義:
typedef struct {
ngx_ssl_cache_create_pt create;
ngx_ssl_cache_free_pt free;
ngx_ssl_cache_ref_pt ref;
} ngx_ssl_cache_type_t;
核心函數分析:
void *
ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
ngx_str_t *path, void *data)
{
uint32_t hash; // 用於存儲計算出的哈希值
ngx_ssl_cache_t *cache; // 指向 SSL 緩存的指針
ngx_ssl_cache_key_t id; // 緩存鍵,用於標識特定緩存項
ngx_ssl_cache_type_t *type; // 緩存類型對象指針
ngx_ssl_cache_node_t *cn; // 指向緩存節點的指針
// 初始化緩存鍵(如失敗則返回 NULL)
if (ngx_ssl_cache_init_key(cf->pool, index, path, &id) != NGX_OK) {
return NULL;
}
// 獲取全局的 SSL 緩存對象
cache = (ngx_ssl_cache_t *) ngx_get_conf(cf->cycle->conf_ctx,
ngx_openssl_cache_module);
// 根據索引獲取對應的緩存類型
type = &ngx_ssl_cache_types[index];
// 計算緩存鍵的哈希值
hash = ngx_murmur_hash2(id.data, id.len);
// 在緩存中查找節點
cn = ngx_ssl_cache_lookup(cache, type, &id, hash);
if (cn != NULL) {
// 如果找到節點,則調用類型的 ref 函數返回緩存值
return type->ref(err, cn->value);
}
// 如果未找到,則分配一個新的緩存節點內存
cn = ngx_palloc(cf->pool, sizeof(ngx_ssl_cache_node_t) + id.len + 1);
if (cn == NULL) {
return NULL; // 分配失敗,返回 NULL
}
// 初始化緩存節點的屬性
cn->node.key = hash; // 設置節點的哈希鍵
cn->id.data = (u_char *)(cn + 1); // 將 ID 數據存儲在分配內存之後
cn->id.len = id.len; // 設置 ID 長度
cn->id.type = id.type; // 設置 ID 類型
cn->type = type; // 設置節點的類型指針
// 複製緩存鍵數據
ngx_cpystrn(cn->id.data, id.data, id.len + 1);
// 調用類型的 create 函數創建緩存值
cn->value = type->create(&id, err, data);
if (cn->value == NULL) {
return NULL; // 創建失敗,返回 NULL
}
// 將新節點插入到緩存的紅黑樹中
ngx_rbtree_insert(&cache->rbtree, &cn->node);
// 返回節點值的引用
return type->ref(err, cn->value);
}
nginx官方此功能並沒有開關控制,是默認開啓的