最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從零實(shí)現(xiàn)Nginx風(fēng)格內(nèi)存池完整代碼

 更新時(shí)間:2026年05月27日 09:28:08   作者:UrSpecial  
本文將從為什么需要內(nèi)存池講起,重點(diǎn)探討內(nèi)存池的設(shè)計(jì)哲學(xué),并詳細(xì)拆解其實(shí)現(xiàn)方案,從而搭建起讀者對內(nèi)存池從理論到實(shí)踐的完整認(rèn)知模型,感興趣的朋友跟隨小編一起看看吧

1.引言

本文將從為什么需要內(nèi)存池講起,重點(diǎn)探討內(nèi)存池的設(shè)計(jì)哲學(xué),并詳細(xì)拆解其實(shí)現(xiàn)方案,從而搭建起讀者對內(nèi)存池從理論到實(shí)踐的完整認(rèn)知模型。

2.為什么需要內(nèi)存池

為什么需要內(nèi)存池?這個(gè)問題可以換一種問法:為什么不直接malloc/freenew/delete?
我們一層一層的回答這個(gè)問題。

1.malloc/free有較高的性能開銷。 內(nèi)存的申請不光是給我們一塊地址這么簡單,malloc底層還要做很多事情,比如分割內(nèi)存塊,合并碎片等。在多線程場景下,malloc內(nèi)部還會(huì)涉及到鎖競爭,避免給不同線程返回相同的內(nèi)存塊。這些操作,都需要性能開銷。

2.減少系統(tǒng)調(diào)用。 申請內(nèi)存屬于系統(tǒng)級操作,所以會(huì)涉及到用戶態(tài)和內(nèi)核態(tài)的切換,也就不可避免的進(jìn)行CPU的上下文切換。而且,用戶態(tài)有用戶態(tài)的棧,內(nèi)核態(tài)有內(nèi)核態(tài)的棧,不能共用,所以也需要切換。這種用戶態(tài)到內(nèi)核態(tài)的切換,相對于在同一個(gè)態(tài)里直接調(diào)用函數(shù)來說,開銷更高一些。內(nèi)存池通過一次申請大塊內(nèi)存,后面再申請內(nèi)存時(shí)直接從這一大塊中切出來,減少了系統(tǒng)調(diào)用。因此,高性能系統(tǒng)總在想辦法減少系統(tǒng)調(diào)用次數(shù)。

3.減少內(nèi)存碎片。 普通的malloc/free會(huì)產(chǎn)生內(nèi)存碎片。雖然內(nèi)存的總?cè)萘繅颍蔷褪欠峙洳怀鰜頋M足需求的連續(xù)內(nèi)存。內(nèi)存池通過將生命周期一致的對象放一起,比如將一個(gè)請求的所有對象放一起,請求結(jié)束時(shí)將整個(gè)池一起釋放,不需要單獨(dú)的free,這就減少了內(nèi)存碎片。

4.減少鎖競爭。 前面也有提到,多個(gè)線程同時(shí)調(diào)用malloc時(shí),底層是會(huì)有鎖競爭的,但是內(nèi)存池通常是線程私有的,互不影響,幾乎無鎖。

3.內(nèi)存對齊

因?yàn)樵趦?nèi)存池的實(shí)現(xiàn)過程中,涉及到內(nèi)存對齊,所以這里先介紹一下。

內(nèi)存對齊本質(zhì)上是編譯器對變量地址存放位置的一個(gè)強(qiáng)制約束。

為什么需要內(nèi)存對齊?

CPU在讀取數(shù)據(jù)的時(shí)候,是按地址總線的寬度來讀取的。如果數(shù)據(jù)按一定的對齊值進(jìn)行了對齊,那么就可以減少CPU額外的讀取次數(shù),從而提高CPU訪問數(shù)據(jù)的效率。

如何進(jìn)行內(nèi)存對齊?

主要有以下3條規(guī)則:

  • 按各自的對齊值對齊。
  • 整體按最大對齊值對齊。
  • 結(jié)構(gòu)體的大小是最大對齊值的整數(shù)倍。

進(jìn)行內(nèi)存對齊,就一定會(huì)有部分內(nèi)存浪費(fèi)。所以,內(nèi)存對齊本質(zhì)上是一種 空間換時(shí)間 的權(quán)衡之策。

4.內(nèi)存池設(shè)計(jì)的核心思想

因?yàn)榇髮ο笕绻苍趦?nèi)存池中分配的話,很快就會(huì)把內(nèi)存池給沾滿。所以,在設(shè)計(jì)內(nèi)存池時(shí),對小對象和大對象做了區(qū)分。

小對象:從內(nèi)存池中分配內(nèi)存。
大對象:直接malloc分配內(nèi)存。

5.代碼設(shè)計(jì)

小對象的節(jié)點(diǎn)設(shè)計(jì)

struct mp_node_s {
    unsigned char *last;
    unsigned char* end;
    struct mp_node_s *next;
    size_t failed;
};

last: 下一個(gè)分配的起始地址。下一次有小對象申請內(nèi)存時(shí),從last位置開始向后切出來分配內(nèi)存。
end: 當(dāng)前節(jié)點(diǎn)內(nèi)存的末尾。
next: 指向下一個(gè)節(jié)點(diǎn)的指針。
failed: 記錄當(dāng)前節(jié)點(diǎn)內(nèi)存申請失敗次數(shù)。這個(gè)字段主要是用來做優(yōu)化的,如果該節(jié)點(diǎn)的內(nèi)存申請失敗次數(shù)達(dá)到一定值,我們直接就跳過該節(jié)點(diǎn),不在該節(jié)點(diǎn)中申請內(nèi)存。

大對象的節(jié)點(diǎn)設(shè)計(jì)

struct mp_large_s {
    struct mp_large_s *next;
    void *alloc;
};

next: 指向下一個(gè)節(jié)點(diǎn)的指針。
alloc: 存放的是malloc函數(shù)的返回值,也就是指向的內(nèi)存塊起始地址。

線程池的總體設(shè)計(jì)

struct mp_pool_s {
    size_t max;
    struct mp_node_s *current;
    struct mp_large_s *large;
    struct mp_node_s head[];
};

max: 小對象和大對象的分界點(diǎn),申請的內(nèi)存大于max的,視為大對象,走的是malloc;申請的內(nèi)存小于max的,視為小對象,走的是內(nèi)存池切塊。
current: 指向小對象鏈表中某個(gè)節(jié)點(diǎn)的指針。current指向哪個(gè)節(jié)點(diǎn),下次分配內(nèi)存時(shí),就首先從該節(jié)點(diǎn)嘗試分配。
large: 指向下一個(gè)大對象節(jié)點(diǎn)的指針。
head: 柔性數(shù)組,整個(gè)小塊鏈表的頭節(jié)點(diǎn)。

這個(gè)結(jié)構(gòu)體,作為整個(gè)內(nèi)存池的入口和管理者。

內(nèi)存池的創(chuàng)建

struct mp_pool_s *mp_create_pool(size_t size) {
    struct mp_pool_s *p;
    int ret = posix_memalign((void **)&p, MP_ALIGNMENT, 
        size + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s));
    if (ret != 0) {
        printf("[%s:%d]mp_create_pool failed!\n", __func__, __LINE__);
        return NULL;
    }
    p->max = (size < MP_MAX_ALLOC_FROM_POOL) ? size : MP_MAX_ALLOC_FROM_POOL;
    p->current = p->head;
    p->large = NULL;
    // 當(dāng)前可分配的起點(diǎn)
    p->head->last = (unsigned char *)p + 
        sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
    p->head->end = p->head->last + size;
    p->head->failed = 0;
    ret

int posix_memalign(void **memptr, size_t alignment, size_t size)
分配一塊地址對齊的內(nèi)存,相對于malloc來說,多了內(nèi)存對齊的功能。

我們除了要分配用戶申請的內(nèi)存大小外,還要給元數(shù)據(jù)申請內(nèi)存。而且,每一個(gè)mp_node_s節(jié)點(diǎn)的大小是一樣的,last指針會(huì)隨著節(jié)點(diǎn)中內(nèi)存的分配情況而移動(dòng)。

小對象節(jié)點(diǎn)的創(chuàng)建

static void *mp_alloc_block(struct mp_pool_s *pool, size_t size) {
    unsigned char* m;
    struct mp_node_s *h = pool->head;
    //所有擴(kuò)容block大小和初始block保持一致
    size_t psize = (size_t)(h->end - (unsigned char *)h);
    int ret = posix_memalign((void **)&m, MP_ALIGNMENT, psize);
    if (ret != 0) {
        printf("[%s:%d]mp_alloc_block failed!\n", __func__, __LINE__);
        return NULL;
    }
    struct mp_node_s *p, *new_node, *current;
    new_node = (struct mp_node_s *)m;
    new_node->end = m + psize;
    new_node->next = NULL;
    new_node->failed = 0;
    m += sizeof(struct mp_node_s);// 跳過node的元數(shù)據(jù)
    m = mp_align_ptr(m, MP_ALIGNMENT);//因?yàn)樵獢?shù)據(jù)可能會(huì)破壞內(nèi)存對齊,所以這里需要做一次內(nèi)存對齊
    new_node->last = m + size;
    current = pool->current;
    // 找鏈表的尾部,同時(shí)更新current字段和failed字段,用于表示失敗的次數(shù),以便用作優(yōu)化
    for (p = current; p->next; p = p->next) {
        if (p->failed > 4) {
            current = p->next;
            p->failed++;
        }
    }
    p->next = new_node;
    pool->current = current ? current : new_node;
    return m;
}

創(chuàng)建新節(jié)點(diǎn),意味著從current指向的節(jié)點(diǎn)往后的所有節(jié)點(diǎn)的剩余可用空間都小于當(dāng)前用戶申請的內(nèi)存大小。
創(chuàng)建出來的新節(jié)點(diǎn),和前面的節(jié)點(diǎn)大小是一樣的。

大對象的節(jié)點(diǎn)創(chuàng)建

static void *mp_alloc_large(struct mp_pool_s *pool, size_t size) {
    void *p = malloc(size);
    if (p == NULL) {
        printf("[%s:%d]mp_alloc_large failed!\n", __func__, __LINE__);
        return NULL;
    }
    size_t n = 0;
    struct mp_large_s *large;
    for (large = pool->large; large; large = large->next) {
        if (large->alloc == NULL) {
            large->alloc = p;
            return p;
        }
        if (n++ >= MP_MAX_LARGE_SCAN) break;
    }
    // large本身不是malloc出來的,而是在內(nèi)存池中分配的
    large = mp_alloc(pool, sizeof(struct mp_large_s));
    if (large == NULL) {
        free(p);
        printf("[%s:%d]mp_alloc failed!\n", __func__, __LINE__);
        return NULL;
    }
    // 頭插
    large->alloc = p;
    large->next = pool->large;
    pool->large = large;
    return p;
}

對于大對象,直接malloc分配內(nèi)存。同時(shí),還需要申請節(jié)點(diǎn)本身的空間,這里large節(jié)點(diǎn)的內(nèi)存,不是直接malloc來的,而是走小對象內(nèi)存分配的路,從內(nèi)存池中切割出來的。對于直接malloc出來的大塊內(nèi)存,用完直接free,不用統(tǒng)一釋放。
再強(qiáng)調(diào)一遍,mp_large_s結(jié)構(gòu)體,它內(nèi)部的指針指向malloc出來的大內(nèi)存,但是這個(gè)結(jié)構(gòu)體本身,不是我們直接malloc出來的,而是從內(nèi)存池中申請得到的。因?yàn)?code>mp_alloc函數(shù)內(nèi)部,對于小于一定大小的空間,走的是內(nèi)存池分配,不是malloc。

空間分配函數(shù)

void *mp_alloc(struct mp_pool_s *pool, size_t size) {
    unsigned char *m;
    struct mp_node_s *p;
    if (size <= pool->max) {
        p = pool->current;
        do {
            m = mp_align_ptr(p->last, MP_ALIGNMENT);
            if ((size_t)(p->end - m) >= size) {
                p->last = m + size;
                return m;
            }
            p->failed++;
            p = p->next;
        }while (p);
        return mp_alloc_block(pool, size);
    }
    return mp_alloc_large(pool, size);
}
void *mp_nalloc(struct mp_pool_s *pool, size_t size) {
    unsigned char *m;
    struct mp_node_s *p;
    if (size <= pool->max) {
        p = pool->current;
        do {
            m = p->last;
            if ((size_t)(p->end - m) >= size) {
                p->last = m + size;
                return m;
            }
            p = p->next;
        }while(p);
        return mp_alloc_block(pool, size);
    }
    return mp_alloc_large(pool, size);
}

外部申請內(nèi)存的時(shí)候,調(diào)用的就是這兩個(gè)函數(shù)??傮w的邏輯就是:小對象走內(nèi)存池分配,大對象直接malloc。
這兩個(gè)函數(shù)的區(qū)別在哪?有沒有內(nèi)存對齊。

mp_alloc是有內(nèi)存對齊的,而mp_nalloc沒有。

CPU會(huì)按固定寬度類型來訪問數(shù)據(jù)的,通常需要內(nèi)存對齊。按字節(jié)流或文本訪問數(shù)據(jù)的,通??梢圆粚R。
我們常見的int、long等這些基本類型,通常就需要內(nèi)存對齊。而字符串就沒必要進(jìn)行內(nèi)存對齊。

內(nèi)存池的銷毀

void mp_destroy_pool(struct mp_pool_s *pool) {
    struct mp_node_s *head = pool->head->next;
    struct mp_node_s *next = NULL;
    struct mp_large_s *cur = pool->large;
    while (cur) {
        if (cur->alloc) free(cur->alloc);
        cur = cur->next;
    }
    while (head) {
        next = head->next;
        free(head);
        head = next;
    }
    free(pool);
}

如果有大對象的內(nèi)存沒有釋放,那么這里會(huì)一并釋放,最后在釋放這個(gè)內(nèi)存池。

6.內(nèi)存池完整代碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#define MP_ALIGNMENT 32
#define MP_PAGE_SIZE 4096
#define MP_MAX_LARGE_SCAN   4
#define MP_MAX_ALLOC_FROM_POOL	(MP_PAGE_SIZE-1)
#define mp_align_ptr(p, alignment) \
    (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))
struct mp_large_s {
    struct mp_large_s *next;
    void *alloc;
};
struct mp_node_s {
    unsigned char *last;
    unsigned char* end;
    struct mp_node_s *next;
    size_t failed;
};
struct mp_pool_s {
    size_t max;//內(nèi)存池允許的小塊分配上限
    struct mp_node_s *current;
    struct mp_large_s *large;
    struct mp_node_s head[];
};
void *mp_alloc(struct mp_pool_s *pool, size_t size);
struct mp_pool_s *mp_create_pool(size_t size) {
    struct mp_pool_s *p;
    int ret = posix_memalign((void **)&p, MP_ALIGNMENT, 
        size + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s));
    if (ret != 0) {
        printf("[%s:%d]mp_create_pool failed!\n", __func__, __LINE__);
        return NULL;
    }
    p->max = (size < MP_MAX_ALLOC_FROM_POOL) ? size : MP_MAX_ALLOC_FROM_POOL;
    p->current = p->head;
    p->large = NULL;
    // 當(dāng)前可分配的起點(diǎn)
    p->head->last = (unsigned char *)p + 
        sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
    p->head->end = p->head->last + size;
    p->head->failed = 0;
    return p;
}
void mp_destroy_pool(struct mp_pool_s *pool) {
    struct mp_node_s *head = pool->head->next;
    struct mp_node_s *next = NULL;
    struct mp_large_s *cur = pool->large;
    while (cur) {
        if (cur->alloc) free(cur->alloc);
        cur = cur->next;
    }
    while (head) {
        next = head->next;
        free(head);
        head = next;
    }
    free(pool);
}
void mp_reset_pool(struct mp_pool_s *pool) {
    struct mp_large_s *cur = pool->large;
    struct mp_node_s *head = pool->head;
    while (cur) {
        free(cur->alloc);
        cur = cur->next;
    }
    pool->large = NULL;
    while (head) {
        head->last = mp_align_ptr((unsigned char *)
            head + sizeof(struct mp_node_s), MP_ALIGNMENT);
        head->failed = 0;
        head = head->next;
    }
    pool->current = pool->head;
}
static void *mp_alloc_block(struct mp_pool_s *pool, size_t size) {
    unsigned char* m;
    struct mp_node_s *h = pool->head;
    //所有擴(kuò)容block大小和初始block保持一致
    size_t psize = (size_t)(h->end - (unsigned char *)h);
    int ret = posix_memalign((void **)&m, MP_ALIGNMENT, psize);
    if (ret != 0) {
        printf("[%s:%d]mp_alloc_block failed!\n", __func__, __LINE__);
        return NULL;
    }
    struct mp_node_s *p, *new_node, *current;
    new_node = (struct mp_node_s *)m;
    new_node->end = m + psize;
    new_node->next = NULL;
    new_node->failed = 0;
    m += sizeof(struct mp_node_s);// 跳過node的元數(shù)據(jù)
    m = mp_align_ptr(m, MP_ALIGNMENT);//因?yàn)樵獢?shù)據(jù)可能會(huì)破壞內(nèi)存對齊,所以這里需要做一次內(nèi)存對齊
    new_node->last = m + size;
    current = pool->current;
    // 找鏈表的尾部,同時(shí)更新current字段和failed字段,用于表示失敗的次數(shù),以便用作優(yōu)化
    for (p = current; p->next; p = p->next) {
        if (p->failed > 4) {
            current = p->next;
            p->failed++;
        }
    }
    p->next = new_node;
    pool->current = current ? current : new_node;
    return m;
}
static void *mp_alloc_large(struct mp_pool_s *pool, size_t size) {
    void *p = malloc(size);
    if (p == NULL) {
        printf("[%s:%d]mp_alloc_large failed!\n", __func__, __LINE__);
        return NULL;
    }
    size_t n = 0;
    struct mp_large_s *large;
    for (large = pool->large; large; large = large->next) {
        if (large->alloc == NULL) {
            large->alloc = p;
            return p;
        }
        if (n++ >= MP_MAX_LARGE_SCAN) break;
    }
    // large節(jié)點(diǎn)不是malloc出來的,而是在small pool分配的
    large = mp_alloc(pool, sizeof(struct mp_large_s));
    if (large == NULL) {
        free(p);
        printf("[%s:%d]mp_alloc failed!\n", __func__, __LINE__);
        return NULL;
    }
    // 頭插
    large->alloc = p;
    large->next = pool->large;
    pool->large = large;
    return p;
}
void *mp_memalign(struct mp_pool_s *pool, size_t size, size_t alignment) {
    void *p;
    int ret = posix_memalign(&p, alignment, size);
    if (ret != 0) {
        printf("[%s:%d]mp_memalign failed!\n", __func__, __LINE__);
        return NULL;
    }
    struct mp_large_s *large = mp_alloc(pool, size);
    if (large == NULL) {
        free(p);
        printf("[%s:%d]mp_memalign failed!\n", __func__, __LINE__);
        return NULL;
    }
    large->alloc = p;
    large->next = pool->large;
    pool->large = large;
    return p;
}
/**
 * brief:帶內(nèi)存對齊的空間分配函數(shù)
 */
void *mp_alloc(struct mp_pool_s *pool, size_t size) {
    unsigned char *m;
    struct mp_node_s *p;
    if (size <= pool->max) {
        p = pool->current;
        do {
            m = mp_align_ptr(p->last, MP_ALIGNMENT);
            if ((size_t)(p->end - m) >= size) {
                p->last = m + size;
                return m;
            }
            p = p->next;
        }while (p);
        return mp_alloc_block(pool, size);
    }
    return mp_alloc_large(pool, size);
}
/**
 * brief:不帶內(nèi)存對齊的空間分配函數(shù),因?yàn)椴皇撬袌鼍跋露夹枰獌?nèi)存對齊
 */
void *mp_nalloc(struct mp_pool_s *pool, size_t size) {
    unsigned char *m;
    struct mp_node_s *p;
    if (size <= pool->max) {
        p = pool->current;
        do {
            m = p->last;
            if ((size_t)(p->end - m) >= size) {
                p->last = m + size;
                return m;
            }
            p = p->next;
        }while(p);
        return mp_alloc_block(pool, size);
    }
    return mp_alloc_large(pool, size);
}
void *mp_calloc(struct mp_pool_s *pool, size_t size) {
    void *p = mp_alloc(pool, size);
    if (p) memset(p, 0, size);
    return p;
}
void mp_free(struct mp_pool_s *pool, void *p) {
    struct mp_large_s *cur;
    for (cur = pool->large; cur; cur = cur->next) {
        if (p == cur->alloc) {
            free(cur->alloc);
            cur->alloc = NULL;
            return;
        }
    }
}
int main() {
    int size = 1 << 12;
    struct mp_pool_s *pool = mp_create_pool(size);
    for (int i = 0; i < 10; i++) {
        void *mp = mp_alloc(pool, 512);
    }
    for (int i = 0; i < 5; i++) {
        void *mp = mp_alloc(pool, 5120);
        mp_free(pool, mp);
    }
    mp_reset_pool(pool);
    for (int i = 0; i < 50; i++) {
        void *mp = mp_alloc(pool, 512);
    }
    mp_destroy_pool(pool);
    return 0;
}

7.整體結(jié)構(gòu)圖

8.結(jié)語

到此這篇關(guān)于從零實(shí)現(xiàn)Nginx風(fēng)格內(nèi)存池的文章就介紹到這了,更多相關(guān)Nginx內(nèi)存池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • nginx?流控使用的項(xiàng)目實(shí)踐

    nginx?流控使用的項(xiàng)目實(shí)踐

    本文主要介紹了nginx?流控使用的項(xiàng)目實(shí)踐
    2024-03-03
  • Nginx 中文域名配置詳解及實(shí)現(xiàn)

    Nginx 中文域名配置詳解及實(shí)現(xiàn)

    這篇文章主要介紹了Nginx中 文域名配置詳解及實(shí)現(xiàn)的相關(guān)資料,Nginx虛擬主機(jī)上綁定一個(gè)帶中文域名但是不能跳轉(zhuǎn),這里給大家說下如何實(shí)現(xiàn),需要的朋友可以參考下
    2016-12-12
  • 實(shí)例詳解SpringBoot+nginx實(shí)現(xiàn)資源上傳功能

    實(shí)例詳解SpringBoot+nginx實(shí)現(xiàn)資源上傳功能

    這篇文章主要介紹了SpringBoot+nginx實(shí)現(xiàn)資源上傳功能,由于小編最近在使用nginx放置靜態(tài)資源問題,遇到很多干貨,特此分享到腳本之家平臺,供大家參考,需要的朋友可以參考下
    2019-10-10
  • Nginx反爬蟲策略,防止UA抓取網(wǎng)站

    Nginx反爬蟲策略,防止UA抓取網(wǎng)站

    目前網(wǎng)絡(luò)上的爬蟲非常多,有對網(wǎng)站收錄有益的,比如百度蜘蛛(Baiduspider),也有不但不遵守robots規(guī)則對服務(wù)器造成壓力,還不能為網(wǎng)站帶來流量的無用爬蟲,為防止網(wǎng)站有可能會(huì)被別人爬,通過配置Nginx, 我們可以攔截大部分爬蟲
    2020-09-09
  • 深度剖析Nginx限速模塊的3個(gè)核心陷阱與5種正確實(shí)踐

    深度剖析Nginx限速模塊的3個(gè)核心陷阱與5種正確實(shí)踐

    這篇文章主要為大家詳細(xì)介紹了Nginx中限速模塊的3個(gè)核心陷阱與5種正確實(shí)踐,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-11-11
  • 使用Nginx搭建代理服務(wù)器(正向代理HTTPS網(wǎng)站)的操作指南

    使用Nginx搭建代理服務(wù)器(正向代理HTTPS網(wǎng)站)的操作指南

    在網(wǎng)絡(luò)應(yīng)用中,代理服務(wù)器是用于中轉(zhuǎn)用戶請求和服務(wù)端響應(yīng)的工具,正向代理主要用于客戶端與外部服務(wù)器之間的訪問代理,幫助客戶端隱藏其 IP 地址或訪問受限資源,本文將詳細(xì)介紹如何使用 Nginx 搭建正向代理服務(wù)器,特別是針對 HTTPS 網(wǎng)站的代理
    2024-11-11
  • nginx校驗(yàn)指定conf文件是否正確的方法

    nginx校驗(yàn)指定conf文件是否正確的方法

    校驗(yàn) Nginx 指定配置文件的語法是否正確,是保證 Nginx 服務(wù)穩(wěn)定運(yùn)行的關(guān)鍵一步,可以使用 Nginx 內(nèi)置的 -t 測試參數(shù),配合 -c 參數(shù)來指定配置文件,下面小編給大家詳細(xì)介紹一下,需要的朋友可以參考下
    2025-08-08
  • Nginx熱部署的實(shí)現(xiàn)

    Nginx熱部署的實(shí)現(xiàn)

    本文主要介紹了Nginx熱部署的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 解決Nginx 配置 proxy_pass 后 返回404問題

    解決Nginx 配置 proxy_pass 后 返回404問題

    這篇文章主要介紹了Nginx 配置 proxy_pass 后 返回404問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • nginx add_header指令使用方法

    nginx add_header指令使用方法

    這篇文章主要介紹了nginx add_header指令使用方法,nginx配置文件通過使用add_header指令來設(shè)置response header,需要的朋友可以參考下
    2014-03-03

最新評論

曲松县| 东台市| 二连浩特市| 张家界市| 灌阳县| 西平县| 大安市| 宜丰县| 阜城县| 高雄市| 武隆县| 浮梁县| 河间市| 泽普县| 乌拉特后旗| 平利县| 日喀则市| 峡江县| 吉首市| 临湘市| 玉田县| 平度市| 新邵县| 安义县| 广平县| 含山县| 上栗县| 冀州市| 赤水市| 遂溪县| 仁寿县| 甘南县| 阿城市| 延寿县| 乐平市| 祁连县| 常山县| 平果县| 盘山县| 卢湾区| 崇义县|