如何使用ngxin的 upstream

news2024/12/23 11:05:26

1.引言:

1.1反向代理:

反向代理是充当Web服务器网关的代理服务器。当您将请求发送到使用反向代理的Web服务器时,他们将先转到反向代理,由该代理将确定是将其路由到Web服务器还是将其阻止。

这意味着有了反向代理,您永远不会与使用它的Web服务器进行直接通信。可以将它们看作web服务器或服务器集群的某种包装器。通过负载平衡和缓存,它们可以保护web免遭攻击,并提供更好的web性能

1.2ngxin访问第三方服务:

Nginx提供了两种全异步方式来与第三方服务器通信:upstream与subrequest。

1.2.1upstream

可以保证在与第三方服务器交互时(包括三次握手建立TCP连接、 发送请求、 接收响应、 四次握手关闭TCP连接等) 不会阻塞Nginx进程处理其他请求, 也就是说, Nginx仍然可以保持它的高性能

1.2.2:subrequest

只是分解复杂请求的一种设计模式, 它本质上与访问第三方服务没有任何关系,但从HTTP模块开发者的角度而言, 使用subrequest访问第三方服务却很常用, 当然,subrequest访问第三方服务最终也是基于upstream实现的

1.2.3:两者的区别

从名称中可以看出, upstream被定义为访问上游服务器, 也就是说, 它把Nginx定义为代理服务器, 首要功能是透传, 其次才是以TCP获取第三方服务器的内容。 Nginx的HTTP反向代理模块就是基于upstream方式实现的

顾名思义, subrequest是从属请求的意思, 在这里我们更倾向于称它为子请求, 也就是说,subrequest将会为客户请求创建子请求, 这是为什么呢? 因为异步无阻塞程序的开发过于复
杂, 所以HTTP框架提供了这种机制将一个复杂的请求分解为多个子请求, 每个子请求负责
一种功能, 而最初的原始请求负责构成并发送响应给客户端.

综合举例子:

用subrequest访问第三方服务, 一般都是派生出子请求访问上游服务器, 父请求在完全取得上游服务器的响应后再决定如何处理来自客户端的请求。 这样做的好处是每个子请求专注于一种功能。 例如, 对于一个子请求, 通常在NGX_HTTP_CONTENT_PHASE阶段仅会使用一个HTTP模块处理, 这大大降低了模块开发的复杂度。 从HTTP框架的内部来说, subrequest与upstream也完全不同,upstream是从属于用户请求的, subrequest与原始的用户请求相比是一个(或多个) 独立的新请求, 只是新的子请求与原始请求之间可以并发的处理。

2.upstream的使用方法:

2.1ngxin的核心功能-反向代理举例

反向代理模块是在先接收完客户请求的HTTP包体后, 才向上游服务器建立连接并转
发请求的
。 假设用户要上传大小为1GB的文件, 由于网速限制, 文件完整地到达Nginx需要
10小时, 恰巧Nginx与上游服务器间的网络也很差(当然这种情况很少见) , 反向代理这个
请求到上游服务也需要10小时, 因此, 根据用户的网速也许本来只要10个小时的上传过程,
最终可能需要20个小时才能完成

2.2 upstream的工作机制

 

1) 首先需要创建上面介绍的upstream成员, 注意,upstream在初始状态下是NULL空指
针。 可以调用HTTP框架提供好的ngx_http_upstream_create方法来创建upstream。

upstream 存在于一个ngx_http_request_t r中:

typedef struct ngx_http_request_s ngx_http_request_t; 
struct ngx_http_request_s {
… 
ngx_http_upstream_t *upstream;
…
};

2) 接着设置上游服务器的地址。在HTTP反向代理功能中似乎只能使用在nginx.conf中配置好的上游服务器 ,而实际上upstream机制并没有这种要求,用户能够以任意方式指定上游服务器的IP地址。 例如, 可以从请求的URL或HTTP头部中动态地获取上游服务器地址, ngx_http_upstream_t中的resolved成员就可以帮助用户设置上游服务器


3) 由于upstream非常灵活, 在各个执行阶段中都会试图回调使用它的HTTP模块实现的8
个方法 , 用户要定义好这些回调方法。

4) 在http模块中, 调用ngx_http_upstream_init方法即可启动upstream机制。 注意,自己的模板回调方法此时必须返回NGX_DONE, 这是在要求HTTP框架不要按阶段继续向下处理请求了, 同时它告诉HTTP框架请求必须停留在当前阶段, 等待某个HTTP模块主动地继续处理这个请求(例如, 在上游服务器主动关闭连接时, upstream模块就会主动地继续处理这个请求, 很可能会向客户端发送502响应码)。
 

2.3upstream的执行机制

下图所示的upstream流程包含了epoll模块多次调度、 处理一个请求的过程, 它虽然与实
际代码执行关系不大, 但却指出了最常用的3个回调方法——create_request、
process_header、 finalize_request是如何回调的。

 

2.4 结ngx_http_upstream_t 结构体

typedef struct ngx_http_upstream_s ngx_http_upstream_t; 
struct ngx_http_upstream_s {
… 

ngx_chain_t *request_bufs; 



ngx_http_upstream_conf_t *conf;

ngx_http_upstream_resolved_t *resolved;


ngx_buf_t buffer;

// 构造发往上游服务器的请求内容
ngx_int_t (*create_request)(ngx_http_request_t *r); 


ngx_int_t (*process_header)(ngx_http_request_t *r); 
// 销毁upstream请求时调用

void (*finalize_request)(ngx_http_request_t *r, ngx_int_t rc); 

// 5个可选的回调方法
ngx_int_t (*input_filter_init)(void *data); 
ngx_int_t (*input_filter)(void *data, ssize_t bytes);
....

//SSL协议访问上游服务器
unsigned ssl:1;


unsigned buffering:1; …

};

结构成员简介:

1.ngx_chain_t *request_bufs;

request_bufs决定发送什么样的请求给上游服务器, 在实现create_request方法时需要设置它

2.conf and resolve 

一个限制参数 另外一个是解析参数

3.ngx_buf_t buffer;

 buffer成员存储接收自上游服务器发来的响应内容, 由于它会被复用, 所以具有下列多种意义:

a)在使用process_header方法解析上游响应的包头时,buffer中将会保存完整的响应包头;

b)当下面的buffering成员为1, 而且此时upstream是向下游转发上游的包体时,buffer没有意义;

c)当buffering标志位为0时,buffer缓冲区会被用于反复地接收上游的包体, 进而向下游转发;

d)当upstream并不用于转发上游包体时,buffer会被用于反复接收上游的包体,HTTP模块实现的input_filter方法需要关注它

4.ngx_int_t (*process_header)(ngx_http_request_t *r); 

收到上游服务器的响应后就会回调process_header方法。 如果process_header返NGX_AGAIN, 那么是在告诉upstream还没有收到完整的响应包头, 此时, 对于本次upstream请求来说, 再接收到上游服务器发来的TCP流时, 还会调用process_header方法处理, 直到process_header函数返回非NGX_AGAIN值这一阶段才会停止

5.unsigned buffering:1;

在向客户端转发上游服务器的包体时才有用。 当buffering为1时, 表示使用多个缓冲区以及磁盘文件来转发上游的响应包体。当Nginx与上游间的网速远大于Nginx与下游客户端间的网速时, 让Nginx开辟更多的内存甚至使用磁盘文件来缓存上游的响应包体, 这是有意义的, 它可以减轻上游服务器的并发压力。

当buffering为0时, 表示只使用上面的这一个
buffer缓冲区来向下游转发响应包体
 

总的解析:

upstream有3种处理上游响应包体的方式, 但HTTP模块如何告诉upstream使用哪一种方式处理上游的响应包体呢?

当请求的ngx_http_request_t结构体中subrequest_in_memory标志位为1时, 将采用第1种方式, 即upstream不转发响应包体到下游,由HTTP模块实现的input_filter方法处理包体;

当subrequest_in_memory为0时, upstream会转发响应包体。

当ngx_http_upstream_conf_t配置结构体中的buffering标志位为1时, 将开启更多的内存和磁盘文件用于缓存上游的响应包体, 这意味上游网速更快;

当buffering为0时, 将使用固定大小的缓冲区(就是上面介绍的buffer缓冲区) 来转发响应包体

2.5解析conf

ngx_http_upstream_t中的conf成员, 它用于设置upstream模块处理请求时的参数, 包括连接、 发送、 接收的超时时间等。

typedef struct {
… 
//连接上游服务器的超时时间, 单位为毫秒
ngx_msec_t connect_timeout; 

// 发送TCP包到上游服务器的超时时间, 单位为毫秒
ngx_msec_t send_timeout;

// 接收TCP包到上游服务器的超时时间, 单位为毫秒
ngx_msec_t read_timeout;
 …

} ngx_http_upstream_conf_t;

事实上,HTTP反向代理模块在nginx.conf文件中提供的配置项大都是用来设置ngx_http_upstream_conf_t结构体中的成员的。 上面列出的3个超时时间是必须要设置的, 因为它们默认为0, 如果不设置将永远无法与上游服务器建立起TCP连接(因为connect_timeout值为0) 。
 

接下来以设置connect_timeout连接超时时间为例说明如何编写ngx_command_t来读取配置
文件

static ngx_command_t ngx_http_mytest_commands[] =
 {…

{ ngx_string("upstream_connect_timeout"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_LOC_CONF_OFFSET,
/*给出
connect_timeout成员在
ngx_http_mytest_conf_t结构体中的偏移字节数
*/

offsetof(ngx_http_mytest_conf_t, upstream.connect_timeout), NULL },


…
}


效果:nginx.conf文件中的upstream_conn_timeout配置项将被解析到ngx_http_mytest_conf_t
结构体的upstream.connect_timeout成员中。 在处理实际请求时, 只要把ngx_http_mytest_conf_t
配置项的upstream成员赋给ngx_http_upstream_t中的conf成员即

ngx_http_mytest_conf_t *mycf =
(ngx_http_mytest_conf_t *) ngx_http_get_module_loc_conf(r, ngx_http_mytest_module_t)


2.6设置需要访问的第三方服务器

ngx_http_upstream_t结构中的resolved成员可以直接设置上游服务器的地址。

首先介绍一下resolved的类型。

typedef struct {
… 
//
地址个数
ngx_uint_t naddrs;
// 上游服务器的地址
struct sockaddr *sockaddr;

socklen_t socklen;
…
} ngx_http_upstream_resolved_t;


 

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

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

相关文章

Java Stream流1

目录1 Stream流1.1 Stream流的生成方式1.2 Stream流中间操作之 filter1.3 Stream流中间操作之 limit 和 skip1.4 Stream流中间操作之 concat 和 distinct1 Stream流 体验Stream流需求 package test;import java.lang.reflect.Array; import java.util.ArrayList;public clas…

Arduino IDE搭建Heltec开发板开发环境

Arduino IDE搭建Heltec开发板开发环境Heltec开发板开发环境下载与搭建Arduino IDE下载与安装搭建Heltec开发板的开发环境添加package URL方法通过Git的方法安装离线安装Heltec开发板开发环境下载与搭建 Arduino IDE下载与安装 Heltec的ESP系列和大部分的LoRa系列开发板都是用A…

2.Gin内容介绍

目录 参考 主要内容 关于Web 创建项目 为什么要用框架 Gin框架介绍 Gin框架安装与使用 安装 第一个Gin示例: RESTful API Gin渲染 HTML渲染 自定义模板函数 静态文件处理 使用模板继承 补充文件路径处理 JSON渲染 XML渲染 YMAL渲染 protobuf渲染…

【Java基础 下】 024 -- 集合进阶(双列集合、HashMap、LinkedHashMap、TreeMap、Collections)

学习内容: 目录 一、双列集合 1、双列集合的特点 2、双列集合的常见API 示例代码 3、Map的遍历方式 ①、第一种遍历方式:键找值(keySet) ②、第二种遍历方式:键值对(entrySet) ③、第三种遍历方…

LeetCode 周赛 333,你管这叫 Medium 难度?

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 大家好,我是小彭。 上周是 LeetCode 第 333 场周赛,你参加了吗?这场周赛质量很高,但难度标得不对,我真的会谢。算法…

深度学习在视频多目标跟踪中的应用综述

文章目录摘要1、简介2、MOT:算法、指标和数据集2.1、MOT算法简介2.2、指标经典的指标完整的MOT指标ID 分数2.3、基准数据集3、MOT中的深度学习3.1、深度学习中的检测步骤3.1.1、Faster R-CNN3.1.2、SSD3.1.3、Other detectors3.1.4、cnn在检测步骤中的其他用途3.2、深度学习在特…

Git的常用命令

1:软件安装1.1:Git下载与安装百度上搜索Git官网:https://git-scm.com/下载:https://git-scm.com/download/win下载Git安装程序,双击安装 Git-2.9.3.2-64-bit.exe配置环境变量path 使用git --version查看 git 是否安装成…

儿童袖套上架美国亚马逊CPC认证

袖套,也称套袖。是戴在袖管外的套子,旨在保护衣服的袖管。通常戴时松垂于另外一只衣袖外面的袖子。美国CPC认证简介:CPC认证是Children’s Product Certificate的英文简称,CPC证书就类似于国内的质检报告,在通过相关检…

(十七)docker安装RocketMQ

一、简介 操作系统:Linux CentOS 7.3 64位 docker版本:19.03.8 RocketMQ版本:4.3.2 二、实践 1、拉取镜像 docker pull rocketmqinc/rocketmq:4.3.2 2、运行容器 我们先搭建namesrv(Name Server)服务。 它充当路由消息的提供者&#…

vue2提取vue-router的title单独存放,使用i18n实现

成品效果 首先引入i18n(vue-i18n官网文档) 依赖包 npm install vue-i18n8然后单独在src目录下新建一个文件夹lang,存放相对应的变量名称,我这里只做显示中文所以其他引入我都注释了,具体目录如下: src\lang/zh.js部分代码 export…

记一次:request请求总结

前言:和前端联调的时候发现前端人员请求的方式不对,固做此总结问题:request请求方式有多少种?答:Java后端查看有8种,spring-web中的java枚举图如下而使用PostMan查看有15种,如下图GET&#xff0…

前端页面jquery规范写法

使用最新版本的 jQuery 最新版本的 jQuery 会改进性能和增加新功能,若不是为了兼容旧浏览器,建议使用最新版本的 jQuery。以下是三条常见的 jQuery 语句,版本越新,性能越好: $(.elem) $(.elem, context) context.find(.elem) 结果 1.6.2 版执行次数远超两个老版本。 jQ…

eclipse中整理左侧项目栏文件

💡在使用eclipse的过程中,随着项目越来越多,会使得项目管理变得困难,介绍一下eclipse中对于项目分类存放(Java Working Set)的解决方案。如果按照默认的方式查看项目列表是这种效果:⭕当创建使用小项目过多…

Prometheus+Grafana监控

1、简介1.1 Prometheus官网地址:https://prometheus.io/Prometheus是一个开源的监控系统,起源于SoundCloud。它由以下几个核心组件构成:数据爬虫: 根据配置的时间定期的通过HTTP抓去metrics数据。time-series 数据库: …

Ubantu 安装到VMware详解

想要在VMware中运行Linux系统,那么就需要Linux系统安装到VMware虚拟机上面。在这里,以把ubantu16.04安装到VMware虚拟机中为教程进行图文讲解,共分为三个步骤,分别是创建新的虚拟机、安装到ubantu系统、安装VMware Tools。 1.1 创…

响应式网络建站公司网站源码+完整教程

分享一个开源的自适应的三网合一的网络建站公司网站的完整源码,当做互联网公司官网特别合适,带完整搭建教程。此款网站源码适用于小程序制作公司、网络公司、网站建设公司等等,这些都可以用这个网站模板,网站整体非常高端大气&…

vue+vite项目部署会遇到的几个问题

今天来打包硅谷外卖项目,通过解决项目中遇到的问题来加深对vite打包的理解。 运行yarn build 报错,报[WARNING] Expected identifier but found “*” [css-syntax-error] 既然zoom:1是没有变化,直接把它去掉即可。 然后继续yarn build 不出所料还是报…

有序表的应用:设计一个增、删、查数据的时间复杂度均为O(logN)的结构

1、题目描述 设计一个结构包含如下三个方法: void add(int index, int num); //把num加入到index位置 int get(int index); //取出index位置的值(是自然序的index位置,非排序后) void remove(int index); //把index位置上的值删…

【Linux】vim拒绝服务安全漏洞修复

根据国家信息安全漏洞共享平台于2023年2月19日发布的安全漏洞通知,Linux系统自带的vim编辑器存在两个高危安全漏洞(CNVD-2023-09166、CNVD-2023-09647),攻击者可以利用该漏洞发起拒绝服务攻击,并可能运行(恶…

【编程入门】应用市场(Vue版)

背景 前面已输出多个系列: 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 《N种编程语言做个记事本》 目标 为编程初学者打造入门学习项目,使…