Fork me on GitHub

应用案例——高并发 WEB 服务器队列的应用

在高并发 HTTP 反向代理服务器 Nginx 中,存在着一个跟性能息息相关的模块 - 文件缓存。

                              

 

 

 经常访问到的文件会被 nginx 从磁盘缓存到内存,这样可以极大的提高 Nginx 的并发能力,不过因为内存的限制,当缓存的文件数达到一定程度的时候就会采取淘汰机制,优先淘汰进入时间比较久或是最近访问很少(LRU)的队列文件。

 

具体实现方案:

1. 使用双向循环队列保存缓存的文件节点,这样可以实现多种淘汰策略:

比如:如果采用淘汰进入时间比较久的策略,就可以使用队列的特性,先进先出

如果要采用按照 LRU,就遍历链表,找到节点删除。

 

源码实现:

nginx_queue.h

 1 #ifndef _NGX_QUEUE_H_INCLUDED_ 
 2 #define _NGX_QUEUE_H_INCLUDED_ 
 3 typedef struct ngx_queue_s ngx_queue_t;
 4 
 5 struct ngx_queue_s 
 6 {
 7     ngx_queue_t* prev; 
 8     ngx_queue_t* next;
 9 };
10 
11 #define ngx_queue_init(q)       \
12     (q)->prev = q;              \
13 (q)->next = q
14 #define ngx_queue_empty(h)      \
15 (h == (h)->prev)
16 #define ngx_queue_insert_head(h, x)\
17     (x)->next = (h)->next;     \
18     (x)->next->prev = x;      \
19     (x)->prev = h;          \
20 (h)->next = x
21 #define ngx_queue_insert_after    ngx_queue_insert_head
22 #define ngx_queue_insert_tail(h, x)\
23     (x)->prev = (h)->prev;      \
24     (x)->prev->next = x;       \
25     (x)->next = h;          \
26 (h)->prev = x
27 #define ngx_queue_head(h)            \
28 (h)->next
29 #define ngx_queue_last(h)            \
30 (h)->prev
31 #define ngx_queue_sentinel(h)        \
32 (h)
33 #define ngx_queue_next(q)            \
34 (q)->next
35 #define ngx_queue_prev(q)            \
36 (q)->prev
37 #define ngx_queue_remove(x)          \
38 (x)->next->prev = (x)->prev;         \
39 (x)->prev->next = (x)->next
40 #define ngx_queue_data(q, type, link)
41 (type*)((char*)q - offsetof(type, link))
42 #endif

 

 

Nginx_双向循环队列.cpp

 1 #include <Windows.h>
 2 #include <stdlib.h>
 3 #include <iostream>
 4 #include "nginx_queue.h" 
 5 #include <time.h> 
 6 
 7 using namespace std;
 8 
 9 typedef struct ngx_cached_open_file_s 
10 {
11     //其它属性省略...
12     int fd;
13     ngx_queue_t    queue;
14 }ngx_cached_file_t;
15 
16 typedef struct 
17 {
18     //其它属性省略... 
19     ngx_queue_t    expire_queue; 
20     //其它属性省略...
21 } ngx_open_file_cache_t;
22 
23 int main(void) 
24 {
25     ngx_open_file_cache_t* cache = new ngx_open_file_cache_t;
26     ngx_queue_t* q;
27     ngx_queue_init(&cache->expire_queue);
28 
29     //1. 模拟文件模块,增加打开的文件到缓存中
30     for (int i = 0; i < 10; i++) 
31     {
32         ngx_cached_file_t* e = new ngx_cached_file_t; 
33         e->fd = i;
34         ngx_queue_insert_head(&cache->expire_queue, &e->queue);
35     }
36 
37     //遍历队列
38     for (q = cache->expire_queue.next;q != ngx_queue_sentinel(&cache->expire_queue); q = q->next) 
39     {
40         printf("队列中的元素:%d\n", (ngx_queue_data(q, ngx_cached_file_t, queue))->fd);
41     }
42 
43     //模拟缓存的文件到期,执行出列操作
44     while (!ngx_queue_empty(&cache->expire_queue)) 
45     {
46         q = ngx_queue_last(&cache->expire_queue); 
47         ngx_cached_file_t* cached_file = ngx_queue_data(q, ngx_cached_file_t, queue); 
48         printf("出队列中的元素:%d\n", cached_file->fd); 
49         ngx_queue_remove(q); 
50         delete(cached_file);
51     }
52     system("pause"); 
53     return 0;
54 }

 

 

 

 

 


==================================================================================================================

posted @ 2020-09-02 16:57  索智源  阅读(277)  评论(0编辑  收藏  举报