nginx的配置粗记

小白nginx的配置随笔(随便记记)

前言

我们都知道nginx有很多用途,比如:负载均衡,反向代理,网关路由,解决跨域等问题。我这次开发项目,用到的一些功能也涉及到了对nginx的配置,且听我后文慢慢讲解~

功能

1.定义网关路由转发规则

我这次开发的项目是基于调用大模型的接口api的web应用,因此我把我的接口大致分为两类,一类是我自主开发的api接口,另一种则是采用sse流式输出的接口(即调用大模型的api接口)
因此,我们需要将这两类api接口分出两个大类(提取公共的前缀)
/api/sse,请看我的nginx配置

    location /api {  # 保留请求前缀的/v1proxy_pass http://localhost:8102/api;  # # 其他可能的配置,如proxy_set_header等  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-Forwarded-Proto $scheme;  }location /sse {proxy_pass http://localhost:8102/sse; proxy_buffering off;  # 禁用缓冲chunked_transfer_encoding off;  # 禁用分块传输编码proxy_cache off;  # 禁用缓存proxy_set_header Connection '';  # 保持连接proxy_http_version 1.1;  # 使用HTTP 1.1}
2.更改请求的输出形式

通过调用大模型接口的不断深入,我发现,得需要流式输出,不单单是模型需要流式输出,我们后端返回给前端,也是需要流式响应。因此我们这里就引生出来了sse概念(有时间我自己单独写一篇doge),这里我就放上一篇博客链接吧sse在springboot工程实战应用。
后面调用接口发现如果在本地直接调用后端接口(端口是8102),是没有问题的;但是如果是调用部署在服务器的后端接口(端口是nginx监听的88),则没有出现分批数据分发给前端,导致前端无法显示大模型返回来的数据(分批的概念就跟sse分不开的)
我在想:本地和线上之间差别在于哪里呢?然后灵机一动,不就是有一个中间件nginx吗?然后我去问了gpt,才知道,对于sse流式输出,nginx有单独的一套规定,默认常规api接口转发是开启了缓冲的(会出现全量返回),而流式输出是需要关闭的。这里我还是贴一张gpt的原话吧~
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

在使用Server-Sent Events(SSE)时,Nginx充当反向代理将消息从服务器转发到客户端。出现消息合并的问题通常是由于Nginx的缓冲机制或者配置问题导致的。

SSE消息应该是连续发送到前端的,而Nginx可能会缓存这些消息并在满足一定条件后一次性发送到前端。为了解决这个问题,你需要调整Nginx的配置以确保它不会缓存这些消息,而是尽可能实时地转发它们。

以下是一些常见的配置调整方法:

  1. 关闭缓冲:设置proxy_bufferingoff,这将禁用Nginx的缓冲功能。
location /sse {proxy_pass http://your_backend;proxy_buffering off;  # 禁用缓冲chunked_transfer_encoding off;  # 禁用分块传输编码proxy_cache off;  # 禁用缓存proxy_set_header Connection '';  # 保持连接proxy_http_version 1.1;  # 使用HTTP 1.1
}
  1. 增加时间限制:确保proxy_read_timeoutproxy_send_timeout设置的时间足够长,以保持连接稳定。
location /sse {proxy_pass http://your_backend;proxy_buffering off;  # 禁用缓冲chunked_transfer_encoding off;  # 禁用分块传输编码proxy_cache off;  # 禁用缓存proxy_set_header Connection '';  # 保持连接proxy_http_version 1.1;  # 使用HTTP 1.1proxy_read_timeout 3600s;  # 读超时时间proxy_send_timeout 3600s;  # 写超时时间
}
  1. 确保后端配置正确:检查你的后端服务器配置,确保它支持并正确实现SSE。

例如,如果你使用的是Node.js,可以使用类似以下的代码来发送SSE消息:

const http = require('http');http.createServer((req, res) => {res.writeHead(200, {'Content-Type': 'text/event-stream','Cache-Control': 'no-cache','Connection': 'keep-alive'});setInterval(() => {res.write(`data: ${new Date().toISOString()}\n\n`);}, 1000);
}).listen(8000);

通过这些配置调整,Nginx应该能够正确地转发SSE消息到前端而不会将多段消息合并。如果问题依然存在,请确保所有相关的代理和缓存配置都已经正确调整,并检查是否有其他的网络组件可能影响消息的传输。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

3.溯源发起的请求

有这么需求,需要获取发起请求的ip地址,那么我的实现的思路如下图
在这里插入图片描述
关键点:

  • 免费的获取天气api接口(我用的免费api大全网站)
  • 获取客户端发起请求的ip地址
    ps:这里忽略代理导致客户端的ip地址的问题
    问题:我当时就是一直获取不到客户端真实的ip地址,获取的内网地址???这让我很疑惑,我都没有开代理呀,只有一个nginx进行接口转发。因此当时我提出一个大胆的猜想,是nginx的问题。
    毕竟nginx是前后端的中间件,相当一堵墙。nginx代替前端把请求发给后端,那么nginx理应是知道前端的发起请求是从哪里来的。可是拿到的是内网地址???说明就是配置有问题!!
    没改配置前:
    location /api {  # 保留请求前缀的/v1proxy_pass http://localhost:8102/api;  }

然后我跟着网上的说法,需要开启对前端发起请求携带的真实的ip地址
更改配置后:

    location /api {  # 保留请求前缀的/v1proxy_pass http://localhost:8102/api;  # # 其他可能的配置,如proxy_set_header等  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-Forwarded-Proto $scheme;  }

这里贴一下获取ip地址的工具代码吧(本质就是request头获取ip信息,考虑多种情况)

    public static String getIpAddr(HttpServletRequest request) {String ipAddress = null;try {ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();if (ipAddress.equals("127.0.0.1")) {// 根据网卡取本机配置的IPInetAddress inet = null;try {inet = InetAddress.getLocalHost();} catch (UnknownHostException e) {e.printStackTrace();}ipAddress = inet.getHostAddress();}}if(request.getLocalAddr().toString().contains("0:0:0:0:0:0:0:1")) {ipAddress="127.0.0.1";}// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}} catch (Exception e) {ipAddress = "";}return ipAddress;}

结语

好啦,小白对于nginx的理解又浅浅进了一小步。(看来得好好补课nginx啦~)
ps:我使用宝塔对nginx进行配置的!有一说一,真的好用!降低我对服务器操作难度哈哈~

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

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

相关文章

Vue.js 动态组件与异步组件

title: Vue.js 动态组件与异步组件 date: 2024/6/2 下午9:08:50 updated: 2024/6/2 下午9:08:50 categories: 前端开发 tags:Vue概览动态组件异步加载性能提升路由管理状态控制工具生态 第1章 Vue.js 简介 1.1 Vue.js 概述 Vue.js 是一个渐进式的JavaScript框架,…

MedSAM 学习笔记(续):训练自定义数据集

1、下载官方权重 官方的预训练权重:https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth 下载后保存在:work_dir/SAM/sam_vit_b_01ec64.pth 目录 2、摆放数据集 因为MedSAM 分割模型需要对3D数据集进行切片处理,也就是对nii.gz 数据处理成 npy 格式 …

Linux--构建进程池

目录 1.进程池 1.1.我们先完成第一步,创建子进程和信道 1.2. 通过channel控制,发送任务 1.3回收管道和子进程 1.4进行测试 1.5完整代码 1.进程池 进程池其产生原因主要是为了优化大量任务需要多进程完成时频繁创建和删除进程所带来的资源消耗&#…

Mysql(一)查询Sql是如何执行的

Hello,大家好我是极客涛😎,我最近在整理Mysql相关的知识点,所以准备开启一个Mysql的主线任务,大概耗时3周左右,整个节奏还是由浅入深,主要包括Mysql的架构、事务实现、索引组织形式、SQL优化、日…

图解大模型分布式并行各种通信原语

背景 在分布式集群上执行大模型任务时候,往往使用到数据并行,流水线并行,张量并行等技术,这些技术本质上也就是对数据进行各种方案的切分,然后放到不同的节点上运算。不同节点在计算的过程中需要对数据分发或者同步等…

python的一种集成开发工具:PyCharm开发工具

一. 简介 本文简单了解两种 python语言所使用的 集成开发环境: PyCharm、vscode。 python语言学习中,可以任意选中这两个集成开发环境的一种就可以。本文先来简单学习 PyCharm开发工具安装与使用。 二. python的一种集成开发工具:PyChar…

实现Redis和数据库数据同步问题(JAVA代码实现)

这里我用到了Redis当中的发布订阅模式实现(JAVA代码实现) 先看图示 下面为代码实现 首先将RedisMessageListenerContainer交给Spring管理. Configuration public class redisConfig {AutowiredRedisConnectionFactory redisConnectionFactory;AutowiredQualifier("car…

Linux线程:线程分离

目录 一、什么是线程分离 1.1pthread_detach 1.2pthread线程库存在的意义 1.3__thread线程的局部存储 1.4系统调用clone 一、什么是线程分离 1.1pthread_detach 默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_joi…

数据标准的制定落地

目录 什么是数据标准 基本定义 目的 数据标准体系分类 从内容层面分类 从管理视角分类 从面向的对象分类 从数据结构的角度分类 数据标准价值 业务价值 技术价值 管理价值 数据标准和数据治理的关系 数据标准在数据治理各项任务中的作用 数据标准与主数据 数据…

车联网安全入门——ICSim模拟器使用

文章目录 车联网安全入门——ISCim模拟器使用介绍主要特点:使用场景: 安装使用捕获can流量candumpcansnifferwiresharkSavvyCAN主要特点:使用场景: 重放can报文cansendSavvyCAN 总结 车联网安全入门——ISCim模拟器使用 &#x1…

LabVIEW步进电机的串口控制方法与实现

本文介绍了在LabVIEW环境中通过串口控制步进电机的方法,涵盖了基本的串口通信原理、硬件连接步骤、LabVIEW编程实现以及注意事项。通过这些方法,用户可以实现对步进电机的精确控制,适用于各种自动化和运动控制应用场景。 步进电机与串口通信…

【刷题(15】普通数组

一 普通数组基础 首先&#xff0c;我们根据下图先了解一下什么是前缀和。 既然我们明白了前缀和是怎么回事&#xff0c;那我们就来看一下我们该怎么输入 先给出答案&#xff0c;然后再给出分析。 答案&#xff1a; for (int i 1; i < n; i ){cin >> a[i];s[i] s…

Pytest框架中用例用例执行常用参数介绍

pytest 支持通过命令行参数来定制测试运行的方式。以下是一些常用的 pytest 执行参数介绍。 学习目录 -q 或 --quiet: 安静模式&#xff0c;只显示进度和摘要 -s : 选项允许在测试的输出中捕获 stdout 和 stderr。 -v : 选项会使 pytest 的输出更加详细。 -k &#xff1a;…

DIYP对接骆驼后台IPTV管理,退出菜单中显示用户名已经网络信息,MAC,剩余天数,套餐名称等

演示&#xff1a;https://url03.ctfile.com/f/1779803-1042599473-4dc000?p8976 (访问密码: 8976) 后台加上EPG&#xff0c;增加一些播放源的动态端口替换。 前台app上&#xff0c;退出菜单中显示用户名已经网络信息&#xff0c;MAC&#xff0c;剩余天数&#xff0c;套餐名称…

QT之常用控件

一个图形化界面当然需要有各种各样的控件&#xff0c;QT也不例外&#xff0c;在QT designer中就有提供各种各样的控件&#xff0c;用以开发图形化界面。 而想使用好一个QT控件&#xff0c;就需要了解这些控件。 QWidget 在QT中&#xff0c;所有控件都继承自 QWidget 类&…

中间件模版引擎

文章目录 中间件1.自定义中间件1&#xff09;全局2&#xff09;局部中间件 2.内置中间件(静态资源目录&#xff09; Art-template1.模板语法1&#xff09;输出2&#xff09;原文输出3&#xff09;条件判断4&#xff09;循环5&#xff09;子模版6&#xff09;模版继承7&#xff…

git远程仓库限额的解决方法——大文件瘦身

Git作为世界上最优秀的分布式版本控制工具&#xff0c;也是优秀的文件管理工具&#xff0c;它赋予了项目成员对项目进行远程协同开发能力&#xff0c;因此受到越来越多的行业从业人员的喜爱。很多优秀的项目管理平台&#xff0c;比如国内的Gitee&#xff0c;国外的Github&#…

Django表单革命:打造安全、高效、用户友好的Web应用

Django表单处理&#xff0c;听起来是不是有点枯燥&#xff1f;别急&#xff0c;阿佑将带你领略Django表单的艺术之美。我们将以轻松幽默的语言&#xff0c;一步步引导你从表单的创建到管理&#xff0c;再到验证和自定义&#xff0c;让你在不知不觉中掌握Django表单的精髓。文章…

SpringMVC:转发和重定向

1. 请求转发和重定向简介 参考该链接第9点 2. forward 返回下一个资源路径&#xff0c;请求转发固定格式&#xff1a;return "forward:资源路径"如 return "forward:/b" 此时为一次请求返回逻辑视图名称 返回逻辑视图不指定方式时都会默认使用请求转发in…

留给“端侧大模型”的时间不多了

端侧大模型&#xff08;Edge AI models&#xff09;&#xff0c;也就是只在设备本地&#xff08;如智能手机、IoT设备、嵌入式系统等&#xff09;运行的大模型&#xff0c;过去一两年来非常流行。 具体表现在&#xff0c;终端设备厂商&#xff0c;如苹果、荣耀、小米、OV等&…