disgare 的博客
首页
博客
分类
标签
首页
博客
分类
标签
  • 网络

    • 计算机网络学习笔记
    • 网络安全相关
    • 域名和子网掩码
    • CORS 跨域资源共享
    • DNS、HTTP 与 HTTPS
    • Server-Sent Events (SSE)
    • WebSocket 长连接
  • 计算机基础

    • 操作系统 IO 相关知识
    • 操作系统学习笔记
    • 程序的机器级表示
    • 音频文件基础
    • 正则表达式相关概念
    • ffmpeg 的安装以及实现音频切分功能
    • Hex 和 Base64 编码
    • XML 的使用
  • 数据结构与算法

    • 动态规划算法学习笔记
    • 基于比较的排序算法的最坏情况下的最优下界为什么是O(nlogn)
    • 集合与数据结构学习笔记
    • 面试常见算法总结
    • 算法导论第二部分排序学习笔记
    • 算法导论第一部分学习笔记
  • Java

    • 对象之间的映射与转换
    • 反射学习笔记
    • 泛型相关概念
    • 关于 boolean 类型的坑
    • 如何使用 lambda 表达式实现排序
    • CompletableFuture 相关用法
    • CompletableFuture 源码浅要阅读
    • FutureTask 源码阅读
    • Guava 常用 API
    • Guava 源码阅读:Multimap 相关
    • Jackson 的各种使用
    • Java 的 Excel 相关操作
    • java 的常见性能问题分析以及出现场景
    • java 基础知识
    • JAVA 枚举的基础和原理
    • Java 图片文件上传下载处理
    • Java 序列化
    • Java 异常
    • Java 语法糖
    • Java 中关于字符串处理的常用方法
    • Java 中强、软、弱、虚引用
    • JAVA 注解小结
    • Java Http 访问框架
    • Java Stream 的使用
    • Java8 新特性
    • netty 学习笔记
    • Scanner 的各种用法
    • Servlet 学习笔记
    • String、StringBuffer、StringBuilder 学习笔记
  • JVM

    • 虚拟机执行子系统
    • JVM 自动内存管理
    • Linux 中 JVM 常用工具以及常见问题解决思路
  • Linux

    • crontab 表达式
    • Linux 常见命令
    • Linux 文件系统
  • 中间件

    • 关于定时任务原理
    • 详解 kafka
    • ES 搜索引擎
    • flink 提交流程
    • Grape-RAG
    • Hadoop 基础原理
  • 多线程

    • 多线程基础学习笔记
    • 简单了解并发集合
    • 如何手写单例
    • 深入理解 java 多线程安全
    • 生产者消费者问题
    • 线程池作用、用法以及原理
    • AQS 组件
    • ThreadLocal 原理以及使用
  • 非关系型数据库

    • Redis 集群
    • Redis 数据结构、对象与数据库
    • Redis 学习笔记
  • 关系型数据库

    • B+ 树的插入、删除和数据页分裂机制
    • MySQL 的 binglog、redolog、undolog
    • MySQL 的记录存储结构、存储引擎与 Buffer Pool
    • MySQL 基本的特性
    • MySQL 开发规范
    • MySQL 事务与锁与 MVCC
    • MySQL 数据类型、字符集相关内容
    • MySQL 索引与索引优化
    • PostgreSQL 更新数据时 HOT优化
    • PostgreSQL 相关用法
  • Python

    • Python 基础语法
    • Python 学习
  • Spring 项目

    • Lombok 的常用注解
    • maven 小结
    • MyBatis 框架的使用
    • MyBatis 重要知识点总结
    • MybatisPlus 的使用
    • Spring 框架基础使用
    • Spring 事务相关
    • Spring IOC 的原理及源码
    • Spring AOP 的使用和原理
    • SpringBoot 的原理
    • SpringBoot 基础使用
    • SpringWeb 重要知识点
  • 分布式

    • 初步了解 docker
    • 从 ACID 到 BASE 事务处理的实现
    • 访问远程服务
    • 分布式 id
    • 分布式缓存相关问题
    • 分布式集群理论和分布式事务协议
    • 分布式架构的观测
    • 分布式一致性算法
    • 负载均衡 Load Balancing
    • 关于分布式系统 RPC 中高可用功能的实现
    • 集群间数据同步的目的
    • 三高问题下的系统优化
    • 数据库分库分表
    • 详解 Spring Cloud
    • Dubbo 基础概念
    • Gossip 协议
    • nginx 学习笔记
      • 重要概念
        • 正向代理
        • 反向代理
        • 负载均衡
        • 动静分离
        • 高可用
        • 限流
      • nginx 使用
        • 安装
        • nginx 配置以及使用
        • ClientAbortException: java.io.IOException: Broken pipe 问题
        • SSL 证书配置
        • ng 的各种命令
      • 原理
    • Protobuf 通信协议
    • Zookeeper 基础学习
  • 架构设计

    • 参数校验与异常处理
    • 抽象方法与设计模式
    • 代码整洁之道
    • 权限系统设计
    • 用低内存处理大量数据
    • 设计模式——策略模式
    • 设计模式——过滤器模式在 Spring 中的实践
    • 状态模式
    • 统一结果返回
    • 为什么要打日志?怎么打日志?打什么日志?
    • 运维监控常见指标含义
    • 资深研发进阶
    • DDD 架构学习笔记
    • Java 常用的规则引擎
    • MVC 架构学习笔记
  • AI

    • 如何编写 Prompt
    • Agent 工程架构
    • LLM 相关内容
    • NLP 相关知识
    • vibe coding 最佳实践
    • windows 下 ollama 迁移到 D 盘
  • 开发工具

    • 如何画时序图、流程图、状态流转图
    • excel 关于 =vlookup 的用法
    • git 的学习以及使用
    • IDEA 插件推荐
    • IDEA 常用快捷键以及调试
    • Shell 脚本
    • swagger 的使用
  • 前端

    • 简单了解前端页面开发
    • 伪静态是什么
    • GitHub Pages 部署教程
    • Vercel 部署教程
    • vue-admin-template 简单使用
    • VuePress 博客搭建指南
  • 项目

    • 面试刷题网——技术方案
    • 影视资源聚合站——技术方案
  • 问题记录

    • 定时任务单线程消费 redis 中数据导致消费能力不足
    • 提供可传递的易受攻击的依赖项
    • Liteflow 在 SpringBoot 启动时无法注入组件问题 couldn‘t find chain with the id[THEN(NodeComponent)]
  • 金融

    • 股票分析——关于电力
    • 股票技术面——量价关系
    • 股票技术面——盘口
    • 股票技术面——基础
    • 基础的金融知识
    • 基金与股票
    • 韭菜的自我总结
    • 聊聊价值投资
  • 其他

    • 程序员职场工作需要注意什么
    • 创业全链路SOP:从灵光一现到系统化增长的实战指南
    • 观罗翔讲刑法随笔
    • 价格和价值
    • 立直麻将牌效益理论
    • 梅花易数学习笔记
    • 压力管理
2022-04-03
分布式
目录

nginx 学习笔记

简单来说,nginx 最多的用法就是接受外部的请求,并且将请求分发到各个服务器上。这中间涉及到域名与 ip 地址的转换相关概念

ng 作为的网关是 API 网关,作用于应用层(Layer 7)。本质是一台运行着 Nginx 软件的服务器,负责业务流量的分发、管理、限流、降级、负载均衡等操作

# 重要概念

Nginx 是一个高性能的 HTTP 和反向代理 web 服务器,采用 C 语言编写,其特点是占有内存少,并发能力强

# 正向代理

客户端本来可以直接通过 HTTP 协议访问某网站应用服务器,但是也可以在浏览器配置一个代理服务器,客户端请求代理服务器,并指定目标(原始服务器),代理服务器请求应用服务器,然后将结果返回给客户端。这种情况叫正向代理

为什么要这么做呢?比如我们现在想要访问谷歌,但是由于某些原因,无法直接访问到谷歌,我们可以通过连接一台代理服务器,代理服务将我们的请求提交到谷歌,然后再将谷歌的响应反馈给我们

上面的例子说的就是 VPN, 是在客户端设置的(并不是在远端的服务器设置)。浏览器先访问 vpn 地址,vpn 地址转发请求,并最后将请求结果原路返回来

注意,因为此时做的是代理(四层以上的操作),此时真实服务器、代理服务器、客户端三者之间是维持着两条独立的 TCP 通道来维持通信的,因此请求的来回都需要经过代理

# 反向代理

外部机器只需要将请求发送给反向代理服务器,代理服务器根据不同的请求(不同的域名)找到不同的机器,得到数据后返回给用户

反向代理是作用在服务器端的,是一个虚拟 ip(VIP)。对于用户的一个请求,会转发到多个后端处理器中的一台来处理该具体请求

正向代理更像是一对一的访问,反向代理更偏向一对多,反向代理的典型使用就是负载均衡,因为可以将请求按条件发送给不同的服务器,可以起到分流的作用

正向代理与反向代理的区别就是针对哪一方是可知的。这个可知的可以理解成哪一方知道请求是发送给了谁。比如正向代理是在客户端设置的,客户端就知道请求发送给了代理;反向代理是在服务端设置的,客户端不知道请求发送给了谁,只知道一个域名,而服务器明确的知道请求返回给了代理

# 负载均衡

当网站访问量非常大,一台服务器已经不够用时,可以将相同的应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。此时需要一种机制来让所有的请求平均分配给所有服务器,不能让某个服务器承受过多请求

nginx 支持负载均衡,它的负载均衡一般使用轮询算法或者加权轮询来实现

# 动静分离

动静分离指将动态请求和静态请求分离开来以获得更良好的访问效率,将静态资源和动态资源放置在不同的服务器上是比较主流的实现方式(也可以让动态资源和静态资源放在一起发布,通过 nginx 分离开来)

# 高可用

为了实现高可用,需要配置集群,不同与其他集群会实现主从复制、读写分离、集群扩容等额外功能,nginx 集群只用来做主备模式

nginx 也不像 ZK、Redis 提供了监视其他机器存活的功能,为了让 nginx 实现宕机时自动切换功能,需要 keepalived 这一软件的支持

注意这个软件叫 keepalived,不是 keepalive(心跳校验机制)

keepalived 还提供了另外一个非常重要的功能,网关,外部访问 nginx 集群时只会访问一个 IP,内部的 IP 切换由 keepalived 自动实现

# 限流

ng 可以做限流功能:

1,ng 可以使用漏桶算法,对全局的流量做控制 2,ng 可以配置每个转发的 ip 的最大连接数和请求的总数

使用了 ng 后我们还可以使用业务网关,ng 类似一个全局网关,业务网关中通常可以用令牌桶算法做一些限流熔断降级等高可用策略

# nginx 使用

# 安装

可以安装在 Windows 系统中,比较简单方便,但是推荐安装在 linux 系统下,功能更强大(windows 无法使用 IO 多路复用功能)

(菜鸟教程 nginx 安装)[https://www.runoob.com/linux/nginx-install-setup.html]

安装 Nginx 源

执行以下命令:

rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
1

安装该 rpm 后,我们就能在 /etc/yum.repos.d/ 目录中看到一个名为 nginx.repo 的文件

安装完 Nginx 源后,就可以正式安装 Nginx 了

yum install -y nginx
1

nginx 的配置路径一般在 etc/yum.repos.d 下,一般根据配置的不同 nginx 可以实现不同的功能。Linux 的 etc 目录是配置文件目录,例如“/etc/passwd”是系统用户配置文件,“/etc/group”是用户组配置文件。repo 是 repository 简写,仓库的意思,可以理解为存放资源的地方

找到 nginx 只需要输入 whereis nginx 即可

修改完 nginx 配置后需要 reload 一下,调用在 sbin 目录下的 nginx 来执行 ng 命令:

sudo /home/q/nginx/sbin/nginx -c /home/q/nginx/conf/nginx.conf -s reload
1

如果发现 nginx 实例不存,启动 nginx:

sudo /home/q/nginx/sbin/nginx -c /home/q/nginx/conf/nginx.conf
1

# nginx 配置以及使用

下载好 nginx 之后,在 /nginx/conf 的 /nginx.conf 中配置 nginx,主要分以下三个部分

  • 全局块:在文件开头的配置可以对 nginx 整体造成影响
  • event 块:在 event 大括号中的内容,这方面配置主要影响网络连接方面
  • http 块:修改最频繁的地方

比如在下载 ng 之后,会默认出现这些内容(include vhost/*.conf;语句是后来加进去的,其他都没变)

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include vhost/*.conf;
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    ##                  '$status $body_bytes_sent "$http_referer" '
    ##                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        ## redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        ## proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        ##    proxy_pass   http://127.0.0.1;
        #}

        ## pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        ##    root           html;
        ##    fastcgi_pass   127.0.0.1:9000;
        ##    fastcgi_index  index.php;
        ##    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        ##    include        fastcgi_params;
        #}

        ## deny access to .htaccess files, if Apache's document root
        ## concurs with nginx's one
        #
        #location ~ /\.ht {
        ##    deny  all;
        #}
    }


    ## another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    ##    listen       8000;
    ##    listen       somename:8080;
    ##    server_name  somename  alias  another.alias;

    ##    location / {
    ##        root   html;
    ##        index  index.html index.htm;
    ##    }
    #}


    ## HTTPS server
    #
    #server {
    ##    listen       443 ssl;
    ##    server_name  localhost;

    ##    ssl_certificate      cert.pem;
    ##    ssl_certificate_key  cert.key;

    ##    ssl_session_cache    shared:SSL:1m;
    ##    ssl_session_timeout  5m;

    ##    ssl_ciphers  HIGH:!aNULL:!MD5;
    ##    ssl_prefer_server_ciphers  on;

    ##    location / {
    ##        root   html;
    ##        index  index.html index.htm;
    ##    }
    #}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

现在来配置一个最简单的请求转发,也就是反向代理。在 http 块中的 server 块中配置,可以在 server 块中使用 include 关键字,将其他配置文件引入该配置文件location 块中,定义了相应的转发规则,命中了什么语句,转发到哪,都可以在这里定义

比如在 vhost 文件夹下新建一个文件,test.conf,然后简单的配置一下

## upstream 里是需要转发的服务器地址
upstream test {
        server  111.11.11.111:1111;
}
## server 里是各种配置
server {
        listen 80;
        server_name  t1.test.com;
        charset utf8;
        gzip                    off;
        gzip_http_version       1.1;
        gzip_buffers            256 64k;
        gzip_comp_level         5;
        gzip_min_length         1000;
        gzip_types              application/x-javascript text/javascript text/plain text/xml text/css image/jpeg image/jpg image/png image/gif application/x-shockwave-flash image/x-icon;

         proxy_set_header  Host  $host;
         proxy_set_header  X-Real-IP  $remote_addr;
         proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header  'X-Real-Scheme'   $scheme;
        location /
        {
            proxy_pass      http://test/;
        }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# ClientAbortException: java.io.IOException: Broken pipe 问题

这个问题是在 java 程序中报出的,但是核心是和 ng 有关系:

ng 服务器上出现很多499的错误,出现499错误的原因是客户端先关闭了连接

从服务器端视角看,问题描述如下:java 的工作线程还在执行代码,有可能是因为 IO 或者 dubbo 访问其他工程,导致工作线程很久才返回数据。这个时候因为 ng 和用户已经断开了,java 服务器回写返回值的时候就会抛出异常:Broken pipe(双方链接已经有一端断开)

如何关闭报499这个错误码呢?可以通过配置:proxy_ignore_client_abort来处理

proxy_ignore_client_abort:是否开启 proxy 忽略客户端中断。即如果此项设置为 on 开启,则服务器会忽略客户端中断,一直等着代理服务执行返回。并且如果执行没有发生错误,记录的日志是200日志。如果超时则会记录504

经过测试只有 ng 会出现这个问题,如果使用 postman 直接访问 java 程序,用户先断开链接后,服务器再返回数据,是不会出现这个问题的

参考链接:

https://stackoverflow.com/questions/43825908/org-apache-catalina-connector-clientabortexception-java-io-ioexception-apr-err

# SSL 证书配置

想要网站可以使用 https 访问,SSL 证书必不可少,购买证书之后,就是申请绑定域名,申请成功之后,之后配置需要用到 pem 和 key 文件,相应的文件下载在"已签发"这块,点击下载,选择 Nginx 版本下载之后就可以了

  • .crt 文件:是证书文件,crt 是 pem 文件的扩展名(有时候没有 crt 只有 pem 的,所以不要惊讶)
  • .key 文件:证书的私钥文件(申请证书时如果没有选择自动创建 CSR,则没有该文件)
  • .pem 扩展名的证书文件采用 Base64-encoded 的 PEM 格式文本文件,可根据需要修改扩展名

在 nginx 目录下直接建立 ssl sslkey 这两个文件夹,在 ssl 文件夹下创建 server.crt server.csr server.key 这三个文件,将上面的三个复制一下即可

如果没有配置 SSL 证书的话,可能会出现以下错误

failed (SSL: error:02001002:system library:fopen:No such file or directory
1

# ng 的各种命令

  • /conf 下是各种配置
  • /sbin 里的 nginx,用于执行各种命令

我们就使用这个 nginx 来执行各种命令,比如重新加载配置文件

sudo /home/q/nginx/sbin/nginx -c /home/q/nginx/conf/nginx.conf
1

如果在执行该命令时出现报错 nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use),一般原因是 nginx 端口被占用了,我们可以执行如下命令:

ps -ef | grep nginx
kill pad

-- 或者执行以下命令
切换到nginx sbin目录
-- 停止
sudo ./nginx -s stop 
-- 启动
./nginx
1
2
3
4
5
6
7
8
9

重启 ng

sudo /home/q/nginx/sbin/nginx -s reload
1

检查配置是否正确

sudo /home/q/nginx/sbin/nginx -t
1

# 原理

启动一个 nginx 会启动多个进程(在任务管理器中就可以看见),有一个 master 进程与多个 worker 进程,实现了 IO 多路复用,master 收到请求后通过信号通知所有的 worker 进程,worker 进程去抢夺请求连接,如果抢到了就去处理它

这么做的好处有两点:一是实现了 nginx 的热部署(闲置的进程更新配置而其他进程继续工作),因为线上的处理器在部署之后,一般不会停止并且维护。ng 的这种方式,在 master 进程修改配置之后,重新启动 master 即可,真正做事情的 worker 不会受到影响

二是所有 worker 都是独立的,不需要加锁,并且其中一个遇到问题其他进程会继续执行,不会互相干扰

worker 的连接数是2(访问静态资源服务器)或者4(访问动态资源时,需要访问额外的服务器)

ng 可以处理一些前端跨域问题,原理是使用 Nginx 转发请求。把跨域的接口写成调本域的接口,然后将这些接口转发到真正的请求地址

#nginx
最后更新: 2/25/2026, 4:06:06 AM
Gossip 协议
Protobuf 通信协议

← Gossip 协议 Protobuf 通信协议→

最近更新
01
vibe coding 最佳实践
02-24
02
立直麻将牌效益理论
02-23
03
伪静态是什么
02-08
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式