nginx技术分享之二
Nginx是一个轻量级、高性能、稳定性高、并发性好的HTTP和反向代理服务器。也是由于其的特性,其应用非常广。
主要功能
Nginx在反向代理上,提供灵活的功能,可以根据不同的正则采用不同的转发策略,如图设置好后不同的请求就可以走不同的服务器,如下图。

其原理就是将数据流量分摊到多个服务器执行,减轻每台服务器的压力,多台服务器(集群)共同完成工作任务,从而提高了数据的吞吐量.如下图。

Nginx可以根据配置对不同的请求做不同转发,这是动态分离的基础。静态请求对应的静态资源可以直接放在Nginx上做缓冲,更好的做法是放在相应的缓冲服务器上。动态请求由相应的后端服务器处理。
配置文件
ngxin的各种功能的实现基本上是靠配置文件驱动的,配置文件大致划分为以下几个板块,如下图

设置防盗链
server {
listen 8080;
server_name xxx.abc.com
location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ {
valid_referers none blocked www.xxx.com www.yyy.com *.baidu.com *.tabobao.com;
if ($invalid_referer) {
rewrite ^/ http://www.xxx.com/images/forbidden.png;
}
}
}
server {
listen 8080;
server_name xxx.abc.com
location /file/ {
root /server/file/;
valid_referers none blocked www.xxx.com www.yyy.com *.baidu.com *.tabobao.com;
if ($invalid_referer) {
rewrite ^/ http://www.xxx.com/images/forbidden.png;
}
}
}
Nginx的负载均衡策略
参数 | 说明 |
---|
不写任何参数 | 默认轮询 |
weight | 权重 |
ip_hash | 依据ip分配 |
least_conn | 最少连接 |
url_hash(第三方) | 依据URL分配 |
air(第三方) | 响应时间 |
nginx负载均衡策略(轮询、hash_ip、随机、权重、fail、url_hash)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端务器down掉,能自动剔除,nginx如下配置
upstream backserver {
server 192.168.0.14;
server 192.168.0.15;
}
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况,nginx如下配置
upstream backserver {
server 192.168.0.14 weight=3;
server 192.168.0.15 weight=7;
}
解决了已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息会丢失的问题,nginx如下配置
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
待会重点讲ip_hash
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backserver {
server server1;
server server2;
fair;
}
按访问url的hash结果来分配请求,使每个url定向到同一个(对应的)后端服务器,后端服务器为缓存时比较有效。
upstream backserver {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
举个栗子
nginx限流之令牌桶算法和漏桶算法
令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务

package main
import (
"fmt"
"time"
)
func logs(args ...interface{}) {
fmt.Println(args...)
}
func tokenBucket(limit int, rate int) chan struct{} {
tb := make(chan struct{}, limit)
ticker := time.NewTicker(time.Duration(1) * time.Second)
for i := 0; i < limit; i++ {
tb <- struct{}{}
}
go func() {
for {
for i := 0; i < rate; i++ {
tb <- struct{}{}
}
<-ticker.C
}
}()
return tb
}
func popToken(bucket chan struct{}, n int) {
for i := 0; i < n; i++ {
<-bucket
}
}
func testTokenBucket() {
rate := 10
tb := tokenBucket(20, rate)
dataLen := 100
for i := 0; i <= dataLen; i += rate {
popToken(tb, rate)
logs(i)
}
}
漏桶(Leaky Bucket)算法思路也比较简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下

package main
import (
"fmt"
"time"
)
type LeakBucket struct {
capacity int
interval time.Duration
dropsNum int
lastAccessTime time.Time
}
func (b *LeakBucket) accessControl() bool {
now := time.Now()
pastTime := now.Sub(b.lastAccessTime)
leaks := int(float64(pastTime) / float64(b.interval))
if leaks > 0 {
if b.dropsNum <= leaks {
b.dropsNum = 0
} else {
b.dropsNum -= leaks
}
b.lastAccessTime = now
}
if b.dropsNum < b.capacity {
b.dropsNum ++
return true
} else {
return false
}
}
func main() {
bucket := &LeakBucket{
capacity: 10,
interval: time.Second,
}
for i := 0; i < 12; i++ {
allowed := bucket.accessControl()
fmt.Println("i",i)
fmt.Println("i",allowed)
time.Sleep(time.Millisecond * 500)
}
time.Sleep(time.Second*3)
fmt.Println("空档期走完")
for j := 0; j < 20; j++ {
fmt.Println("BEFORE",bucket.dropsNum)
allowed := bucket.accessControl()
fmt.Println("AFTER",bucket.dropsNum)
fmt.Println("j", j)
fmt.Println("j",allowed)
time.Sleep(time.Millisecond * 500)
}
}
参考文档
死磕nginx系列--nginx 限流配置
一致性hash算法的理解与实践
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异