nginx相关面试题30道

一、基础概念与核心特性

1. 什么是 Nginx?它的主要用途有哪些?

答案
Nginx 是一款高性能的开源 Web 服务器、反向代理服务器及负载均衡器,基于事件驱动的异步非阻塞架构,擅长处理高并发场景。
主要用途

  • 静态资源服务(HTML/CSS/JS/ 图片等)
  • 反向代理与负载均衡(分发请求到后端服务器集群)
  • API 网关(处理动态请求转发)
  • 缓存服务(通过proxy_cachefastcgi_cache加速动态内容)
  • 实时消息代理(支持 WebSocket 长连接)
2. Nginx 相比 Apache 的核心优势是什么?

答案

对比维度NginxApache
架构单主进程 + 多 worker 进程(异步非阻塞)多进程 / 线程(同步阻塞,如 prefork/worker)
高并发性能支持数万并发连接,内存占用低并发能力较低,内存占用高
静态资源处理原生高效,无需插件需要mod_static等插件
动态请求处理需配合 FastCGI/Proxy 转发给后端可通过模块(如mod_php)直接处理
配置灵活性基于模块化设计,配置简洁模块化丰富但配置较复杂

解析:Nginx 的异步非阻塞模型(基于 epoll/kqueue)避免了多线程 / 进程的上下文切换开销,适合高并发、低延迟场景;Apache 则在需要复杂模块(如 PHP 解析)时更便捷。

3. 解释 Nginx 的 Master-Worker 进程模型及其作用

答案

  • Master 进程
    • 读取并验证配置文件(nginx.conf
    • 管理 Worker 进程(启动 / 停止 / 重启 / 平滑升级)
    • 监听端口,将请求分发到 Worker 进程
  • Worker 进程
    • 实际处理客户端请求,单进程支持数千并发连接
    • 通过worker_connections控制单个进程最大连接数
    • 多 Worker 进程间通过负载均衡(如轮询)处理请求

优势:Master 负责管理,Worker 专注处理请求,实现资源隔离与高效并发。

4. 什么是反向代理?反向代理与正向代理的区别?

答案

  • 反向代理:位于服务器端,代理后端集群接收客户端请求,隐藏真实服务器地址。例如 Nginx 接收请求后转发到 Tomcat/Node.js 服务器。
  • 正向代理:位于客户端侧,代理客户端向目标服务器发送请求(如浏览器通过代理访问外网)。
    核心区别
  • 反向代理代理的是服务器,客户端不知道真实后端;正向代理代理的是客户端,服务器不知道真实客户端 IP。
5. 简述 Nginx 处理 HTTP 请求的流程

答案

  1. 客户端发送请求到 Nginx 监听端口(如 80/443)。
  2. Master 进程接收请求,分配给某个 Worker 进程。
  3. Worker 进程根据server块和location匹配规则处理请求:
    • 若为静态资源,直接读取文件返回(如root/alias指定路径)。
    • 若为动态请求,通过proxy_pass/fastcgi_pass转发到后端服务器。
  4. 后端服务器处理请求并返回结果,Nginx 将响应返回给客户端(可能经过缓存、压缩等处理)。

二、配置与优化

6. 如何配置 Nginx 监听多个端口?如何指定域名绑定?

答案

server {listen 80;          # 监听80端口listen 443 ssl;     # 监听443端口并启用HTTPSserver_name example.com www.example.com;  # 绑定域名# 配置HTTPS证书ssl_certificate /path/to/cert.pem;ssl_certificate_key /path/to/key.pem;
}
7. 如何实现 URL 重写(Rewrite)?举例说明场景

答案
使用rewrite指令结合正则表达式实现重写,场景如:

  • 强制 HTTPS:
    server {listen 80;server_name example.com;rewrite ^(.*)$ https://$server_name$1 permanent;  # 301重定向
    }
    
  • 路径跳转:
    location /old-path/ {rewrite ^/old-path/(.*)$ /new-path/$1 break;  # 内部重写,不返回客户端
    }
    

指令说明permanent(301)、redirect(302)、break(内部跳转)。

8. 如何配置 Nginx 禁止特定 IP 访问?

答案
使用ngx_http_access_module模块:

location / {deny 192.168.1.100;  # 禁止单个IPdeny 192.168.1.0/24; # 禁止IP段allow all;           # 允许其他IP
}
9. 如何优化 Nginx 的静态资源访问性能?

答案

  • 开启sendfile高效传输:
    http {sendfile on;  # 直接通过内核传输文件,减少用户态/内核态拷贝tcp_nopush on; # 合并TCP包,减少网络IO
    }
    
  • 配置缓存头(Cache-Control/Expires):
    location ~* \.(js|css|png|jpg)$ {expires 7d;  # 浏览器缓存7天add_header Cache-Control "public";
    }
    
  • 启用 Gzip 压缩:
    gzip on;
    gzip_types text/css application/javascript;
    
10. 如何限制客户端请求频率(限流)?

答案
使用ngx_http_limit_req_module模块(漏桶算法):

http {limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;  # 按IP限流,每秒1请求server {location / {limit_req zone=one burst=5 nodelay;  # 突发请求允许5个排队}}
}

Nginx 的惊群问题(Thundering Herd Problem)及解决方案

什么是惊群问题?

        当多个进程(如 Nginx 的 Worker 进程)同时监听同一个端口时,若有新的连接请求到达,所有等待该端口的进程会被同时唤醒,但最终只有一个进程能成功处理连接,其他进程会重新进入休眠状态。这种现象称为 惊群效应(Thundering Herd Problem)。
影响:频繁的进程上下文切换会消耗 CPU 资源,降低服务器性能,尤其在高并发场景下更为明显。

Nginx 惊群问题的触发场景

Nginx 使用 Master-Worker 多进程模型

  • Master 进程:负责管理 Worker 进程,监听端口并分配连接。
  • Worker 进程:多个 Worker 进程共同监听 Master 进程打开的端口,等待处理客户端请求。
    在旧版本的 Nginx(或未优化配置时),当新连接到达时,所有 Worker 进程会被唤醒并竞争处理连接,导致惊群效应。
解决方案:利用 SO_REUSEPORT 套接字选项

现代操作系统(如 Linux 3.9+、FreeBSD 10+)支持 SO_REUSEPORT 选项,允许 多个套接字绑定到同一 IP 地址和端口,内核会自动将连接请求分发到不同的 Worker 进程,避免惊群问题。

配置步骤
  1. 在 Nginx 配置中启用 use_reuseport

    worker_processes 4;  # 设置合理的 Worker 进程数(建议等于 CPU 核心数)
    worker_rlimit_nofile 65535;  # 调整文件描述符限制events {worker_connections 1024;  # 每个 Worker 进程的最大连接数use epoll;  # 使用高效的事件驱动模型(Linux 推荐 epoll)multi_accept on;  # 一次尽可能多地接受新连接(可选优化)
    }http {# 在 http 块或 server 块中添加:server {listen 80 reuseport;  # 关键配置:启用 SO_REUSEPORTserver_name example.com;# ... 其他配置}
    }
    
    • listen 80 reuseport:告诉内核使用 SO_REUSEPORT 选项绑定端口,每个 Worker 进程独立监听自己的套接字。
    • worker_processes 需大于 1,否则无需处理惊群问题。
  2. 验证配置生效
    重启 Nginx 后,通过 ss -ltnp | grep nginx 查看端口监听情况,应看到每个 Worker 进程独立监听端口:

    tcp    LISTEN     0      128       :::80                    :::*                   users:(("nginx",pid=1234,fd=6),("nginx",pid=1235,fd=6),("nginx",pid=1236,fd=6),("nginx",pid=1237,fd=6))
    

    每个 Worker 进程对应一个独立的监听套接字(fd=6 是示例文件描述符)。

其他优化:accept_mutex 锁(旧方案)

在不支持 SO_REUSEPORT 的系统中,Nginx 默认通过 accept_mutex 互斥锁 缓解惊群问题:

 
  • 多个 Worker 进程竞争一把锁,只有获得锁的进程才能处理新连接,减少同时唤醒的进程数。
  • 配置示例(默认开启,无需手动设置):
    events {accept_mutex on;  # 启用互斥锁(默认 on)accept_mutex_delay 50ms;  # 锁竞争失败后的等待时间(默认 50ms)
    }
    
    缺点:锁竞争仍会带来一定性能损耗,不如 SO_REUSEPORT 高效。

三、负载均衡与代理

11. Nginx 支持哪些负载均衡算法?如何配置?

答案

  • 轮询(默认):依次分配请求到后端服务器。
    upstream backend {server 192.168.1.1;server 192.168.1.2;
    }
    
  • 权重轮询(weight:按权重分配,适用于性能不均的服务器。
    server 192.168.1.1 weight=3;  # 权重3(默认1)
    
  • IP 哈希(ip_hash:相同 IP 固定访问同一服务器(解决 Session 问题)。
    upstream backend {ip_hash;server 192.168.1.1;
    }
    
  • 最少连接(least_conn:分配给当前连接最少的服务器。
    upstream backend {least_conn;server 192.168.1.1;
    }
    
  • URL 哈希(需自定义模块,如ngx_http_upstream_hash_module:按 URL 哈希值分配。
12. 如何实现后端服务器的健康检查?

答案
使用ngx_http_proxy_moduleproxy_next_upstream指令,配置失败重试:

upstream backend {server 192.168.1.1 max_fails=3 fail_timeout=30s;  # 3次失败则标记为不可用,30s后重试server 192.168.1.2;
}
location / {proxy_pass http://backend;proxy_next_upstream error timeout http_502 http_504;  # 失败时转发到下一台服务器
}

 

13. 反向代理时如何传递客户端真实 IP?

答案
默认 Nginx 传递的X-Forwarded-For可能被多级代理修改,需配置:

location / {proxy_pass http://backend;proxy_set_header X-Real-IP $remote_addr;       # 传递真实客户端IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 保留代理链IP
}
14. 如何配置 Nginx 作为 WebSocket 代理?

答案
需在proxy_pass中设置 WebSocket 协议头:

location /ws/ {proxy_pass http://websocket-server;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";
}
15. 什么是动静分离?如何实现?

答案
动静分离:将静态资源(如图片、JS)与动态请求(如 API)分离处理,静态资源由 Nginx 直接响应,动态请求转发给后端服务器。
实现方式

server {location /static/ {root /var/www/app;  # 直接返回静态文件autoindex on;       # 开启目录浏览(可选)}location /api/ {proxy_pass http://backend-api;  # 转发动态请求}
}

四、高级特性与故障处理

16. 如何配置 Nginx 的 HTTP 缓存(Proxy Cache)?

答案
使用ngx_http_proxy_cache_module模块:

http {proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;proxy_cache_key $scheme$host$request_uri;  # 缓存键规则server {location / {proxy_pass http://backend;proxy_cache my_cache;          # 启用缓存proxy_cache_valid 200 302 1h;  # 200/302响应缓存1小时proxy_cache_valid 404 1m;      # 404响应缓存1分钟}}
}
17. 常见的 502 Bad Gateway 错误原因及解决方法?

答案
原因

  • 后端服务器宕机或未启动
  • 后端服务请求超时(Nginx 等待后端响应超时)
  • 负载均衡配置错误(如upstream服务器地址错误)
  • 后端服务连接数耗尽

解决方法

  1. 检查后端服务状态(systemctl status tomcat等)。
  2. 调整 Nginx 超时参数:
    proxy_connect_timeout 10s;    # 连接后端超时
    proxy_read_timeout 30s;       # 读取后端响应超时
    
  3. 增加后端服务器节点或优化服务性能。
18. 如何查看 Nginx 的实时并发连接数?

答案

  • 使用nginx -s status(需配置stub_status模块):
    location /status {stub_status on;access_log off;
    }
    
    访问http://your-nginx/status查看:
    Active connections: 123  
    server accepts handled requests  10000 10000 20000  
    Reading: 2 Writing: 50 Waiting: 71  # Waiting为空闲keep-alive连接
    
  • 命令行工具:netstat -ant | grep :80 | wc -l(统计 80 端口连接数)。
19. 如何实现 Nginx 配置的平滑重启?

答案

  • 验证配置正确性:nginx -t
  • 平滑重启(不中断现有连接):
    nginx -s reload  # 重新加载配置
    nginx -s reopen  # 重新打开日志文件
    
  • 原理:Master 进程生成新 Worker 进程,旧 Worker 处理完剩余请求后退出。
20. 如何禁止 Nginx 记录特定 URL 的访问日志?

答案
location中关闭日志记录:

location /static/ {root /var/www/static;access_log off;  # 关闭该路径的访问日志
}

五、扩展与实战

21. 如何为 Nginx 添加自定义模块?

答案

  1. 下载 Nginx 源码并解压:
    wget http://nginx.org/download/nginx-1.24.0.tar.gz
    tar -zxvf nginx-1.24.0.tar.gz
    
  2. 编译时添加模块(以ngx_http_sub_module为例):
    cd nginx-1.24.0
    ./configure --add-module=/path/to/module
    make && make install
    
  3. 重启 Nginx 使模块生效。
22. 如何配置 Nginx 支持 HTTP/2?

答案

  1. 确保编译时启用ngx_http_v2_module(默认开启)。
  2. 配置 HTTPS 并启用 HTTP/2:
    server {listen 443 ssl http2;  # 声明HTTP/2server_name example.com;ssl_certificate /path/to/cert.pem;ssl_certificate_key /path/to/key.pem;# 其他HTTPS优化配置(如TLS版本、加密算法)
    }
    
23. 如何实现 Nginx 的请求体大小限制?

答案
通过client_max_body_size指令限制(默认 1MB):

http {client_max_body_size 10m;  # 允许最大请求体10MBserver {location /upload/ {client_max_body_size 50m;  # 针对特定路径单独配置}}
}
24. 解释 Nginx 中rootalias的区别

答案

  • root:将请求路径拼接到配置路径后查找文件。
    例:root /var/www; location /static/ → 访问/static/test.js对应文件/var/www/static/test.js
  • alias:直接替换请求路径为配置路径。
    例:alias /var/www/static/; location /static/ → 访问/static/test.js对应文件/var/www/static/test.js
    关键区别alias会覆盖location路径,root则拼接路径;alias后需加 /root无需。
25. 如何配置 Nginx 的跨域资源共享(CORS)?

答案
使用add_header添加 CORS 响应头:

location /api/ {proxy_pass http://backend;add_header Access-Control-Allow-Origin *;         # 允许所有来源add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";add_header Access-Control-Allow-Headers "DNT,User-Agent,Content-Type";if ($request_method = 'OPTIONS') {return 204;  # 处理预检请求}
}

六、性能与安全

26. 如何优化 Nginx 的 SSL/TLS 性能?

答案

  • 启用 TLS 1.3(比 1.2 更快):
    ssl_protocols TLSv1.3 TLSv1.2;
    
  • 选择高效加密算法:
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;
    
  • 开启会话缓存(减少握手次数):
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
27. 如何防范 Nginx 的 CC 攻击(分布式请求伪造)?

答案

  • 限制同一 IP 的并发连接数(ngx_http_limit_conn_module):
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
    server {location / {limit_conn conn_limit 10;  # 单个IP最多10个连接limit_conn_status 429;     # 超出限制返回429}
    }
    
  • 结合 WAF(如 ModSecurity)或云防护服务。
28. 解释 Nginx 中worker_rlimit_nofile的作用

答案
该指令用于设置 Worker 进程的最大打开文件数,解决 “Too many open files” 错误。

worker_rlimit_nofile 65535;  # 单个Worker进程最多打开65535个文件描述符

场景:高并发场景下,需确保该值大于worker_connections(默认 1024)。

29. 如何实现 Nginx 的请求日志切割?

答案

  • 手动切割
    mv /var/log/nginx/access.log /var/log/nginx/access.log.`date +%Y%m%d`
    kill -USR1 `cat /var/run/nginx.pid`  # 通知Nginx重新生成日志文件
    
  • 自动切割(通过 cron 任务)
    0 0 * * * mv /var/log/nginx/access.log /var/log/nginx/access.log.$(date +\%Y\%m\%d) && /usr/sbin/nginx -s reopen
    
30. 简述 Nginx 在微服务架构中的应用场景

答案

  • API 网关:统一入口,处理请求路由、限流、认证。
  • 静态资源服务器:独立部署,减轻后端压力。
  • 服务网格边缘代理:配合 Istio/Linkerd 处理南北向流量。
  • 灰度发布:通过权重轮询或流量镜像实现分批次发布。

0voice · GitHub 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/83646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库实验报告 数据定义操作 3

实验报告(第3次) 实验名称 数据定义操作 实验时间 10月12日1-2节 一、实验内容 1、本次实验是用sql语句创建库和表,语句是固定的,要求熟记这些sql语句。 二、源程序及主…

霍夫圆变换全面解析(OpenCV)

文章目录 一、霍夫圆变换基础1.1 霍夫圆变换概述1.2 圆的数学表达与参数化 二、霍夫圆变换算法实现2.1 标准霍夫圆变换算法流程2.2 参数空间的表示与优化 三、关键参数解析3.1 OpenCV中的HoughCircles参数3.2 参数调优策略 四、Python与OpenCV实现参考4.1 基本实现代码4.2 改进…

记录一次修改nacos安全问题导致服务调用出现404

1、nacos默认值修改 nacos.core.auth.plugin.nacos.token.secret.key**** nacos.core.auth.server.identity.key******** nacos.core.auth.server.identity.value************ 重启nacos, 这时候微服务的token认证会立即失效,等待自动重连认证或者手动重启服务 2、…

Python面试总结

hello,大家好,我是potato,我总结一下最近的面试遇到的问题~ 1.Python开发(软通动力) 自我介绍主要问了项目(YOLOv11)项目遇到的难点和解决方法is,列表和元组的区别Python多线程有什么问题?Pyt…

5.18 day24

知识点回顾: 元组可迭代对象os模块 作业:对自己电脑的不同文件夹利用今天学到的知识操作下,理解下os路径。 元组 元组的特点: 有序,可以重复,这一点和列表一样 元组中的元素不能修改,这一点…

Uniapp中小程序调用腾讯地图(获取定位地址)

1、先配置权限: 这是上图的代码: "permission": { "scope.userLocation": { "desc": "你的位置信息将用于小程序位置接口的效果展示" } } 第二步:写代码: //下面是uniapp的模版代码 主…

写spark程序数据计算( 数据库的计算,求和,汇总之类的)连接mysql数据库,写入计算结果

1. 添加依赖 在项目的 pom.xml&#xff08;Maven&#xff09;中添加以下依赖&#xff1a; xml <!-- Spark SQL --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.12</artifactId> <version>3.3.0…

nginx服务器实验

1.实验要求 1&#xff09;在Nginx服务器上搭建LNMP服务&#xff0c;并且能够对外提供Discuz论坛服务。 在Web1、Web2服务器上搭建Tomcat 服务。 2&#xff09;为nginx服务配置虚拟主机&#xff0c;新增两个域名 www.kgc.com 和 www.benet.com&#xff0c;使用http://www.kgc.…

Spring Boot 与 RabbitMQ 的深度集成实践(一)

引言 ** 在当今的分布式系统架构中&#xff0c;随着业务复杂度的不断提升以及系统规模的持续扩张&#xff0c;如何实现系统组件之间高效、可靠的通信成为了关键问题。消息队列作为一种重要的中间件技术&#xff0c;应运而生并发挥着举足轻重的作用。 消息队列的核心价值在于其…

c++多线程debug

debug demo 命令行查看 ps -eLf|grep cam_det //查看当前运行的轻量级进程 ps -aux | grep 执行文件 //查看当前运行的进程 ps -aL | grep 执行文件 //查看当前运行的轻量级进程 pstree -p 主线程ID //查看主线程和新线程的关系 查看线程栈结构 pstack 线程ID 步骤&…

10.7 LangChain v0.3架构大升级:模块化设计+多阶段混合检索,开发效率飙升3倍!

LangChain v0.3 技术生态与未来发展 关键词:LangChain Chains, Agents 架构, Retrieval Strategy, LangGraph, 模块化设计 3. LangChain 项目:Chains, Agents, Retrieval Strategy LangChain v0.3 通过 Chains-Agents-Retrieval 三位一体的技术栈,构建起完整的大模型应用开…

分布式 ID 生成的五种方法:优缺点与适用场景

0.简介 在分布式系统中&#xff0c;生成全局唯一的id是一个常见的需求。由于分布式系统的特性&#xff08;多节点&#xff0c;网络分区&#xff0c;时钟不同步等&#xff09;&#xff0c;传统的单机ID生成方式不再适用&#xff0c;所以一些分布式生成方式应运而生&#xff0c;…

基于单片机路灯自动控制仪仿真设计

标题:基于单片机路灯自动控制仪仿真设计 内容:1.摘要 本设计旨在解决传统路灯控制方式效率低、能耗大的问题&#xff0c;开展了基于单片机的路灯自动控制仪仿真设计。采用单片机作为核心控制单元&#xff0c;结合光照传感器、时钟模块等硬件&#xff0c;运用相关软件进行编程和…

计算机网络-MPLS VPN基础概念

前面几篇文章我们学习了MPLS的标签转发原理&#xff0c;有静态标签分发和LDP动态标签协议&#xff0c;可以实现LSR设备基于标签实现数据高效转发。现在开始学习MPLS在企业实际应用的场景-MPLS VPN。 一、MPLS VPN概念 MPLS&#xff08;多协议标签交换&#xff09;位于TCP/IP协…

LWIP的Socket接口

Socket接口简介 类似于文件操作的一种网络连接接口&#xff0c;通常将其称之为“套接字”。lwIP的Socket接口兼容BSD Socket接口&#xff0c;但只实现完整Socket的部分功能 netconn是对RAW的封装 Socket是对netconn的封装 SOCKET结构体 struct sockaddr { u8_t sa_len; /* 长…

windows 安装gdal实现png转tif,以及栅格拼接

windows 安装gdal实现png转tif&#xff0c;以及栅格拼接 一、安装gdal 网上有很多安装gdal的方法&#xff0c;此处通过osgeo4w安装gdal 1.下载osgeo4w 下载地址 https://trac.osgeo.org/osgeo4w/ 2、安装osgeo4w exe文件安装&#xff0c;前面部分很简单&#xff0c;就不再…

Node.js 源码概览

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境&#xff0c;它的源码结构相当庞大且复杂。下面我将为你讲解 Node.js 源码的主要结构和关键组成部分。 源码结构 Node.js 的主要源码目录结构如下&#xff1a; node/ ├── lib/ # JavaScript 核心模…

Linux :线程 【生产者消费者模型】

Linux &#xff1a;线程 【生产者消费者模型与信号量】 &#xff08;一&#xff09;生产消费模型1、生产消费模式概念2、生产者消费者之间的关系3、生产者消费者模型优点 &#xff08;二&#xff09;基于BlockingQueue的生产者消费者模型1、基于阻塞队列模型2、模拟实现基于阻塞…

mac本地docker镜像上传指定虚拟机

在Mac本地将Docker镜像上传至指定虚拟机的完整步骤 1. 在Mac本地保存Docker镜像为文件 通过docker save命令将镜像打包为.tar文件&#xff0c;便于传输至虚拟机。 # 示例&#xff1a;保存名为"my_image"的镜像到当前目录 docker save -o my_image.tar my_image:ta…

C++跨平台开发经验与解决方案

在当今软件开发领域&#xff0c;跨平台开发已成为一个重要的需求。C作为一种强大的系统级编程语言&#xff0c;在跨平台开发中扮演着重要角色。本文将分享在实际项目中的跨平台开发经验和解决方案。 1. 构建系统选择 CMake的优势 跨平台兼容性好 支持多种编译器和IDE 强大…