阅读博客 添加收藏 nginx动态代理方案

       我做的是nginx +lua+redis

       0、需求:动态调整转发策略

    数据库存放着大量的用户数据,需要制定一个策略,负载均衡服务器可以根据用户信息,动态转发请求。

    比如A用户(001)的请求转发到A服务器(192.168.1.101),B用户(002)的请求转发到B服务器(192.168.1.102),C用户(003)的请求转发到A服务器(192.168.1.103),等等。

1、服务器上下文

   前端nginx服务器 + N台后端应用服务器。准备用单台服务器模拟。

   前端:192.168.1.101:80

   后端:192.168.1.101:81

 

2、技术头脑风暴

    程序员们脑袋里开始有好几个方案了,有的是直觉,有的是经验,如下:

a、写nginx模块,模块里实现读数据库或nosql,根据数据值做转发。

b、找现成的模块,看能不能直接改根据或脚本就可以解决。据说ngx_lua很强大,可以考虑。

c、服务器必须保证不能有任何阻塞,模块实现时得用nginx的subrequest机制。

d、blalala...

 

3、程序员的脑袋里装的什么呢? 简单

    任务1:web程序员A,写个http api接口,返回具体的服务器信息(ip+port)。

    任务2:系统工程师B,做个nginx配置,根据A的api让nginx根据返回信息实现动态转发。

 

4、开始实现:

   任务1:分分钟搞定,写个php脚本呗。

   任务2:继续拆解

             任务2.1:实现最简单转发

server {
    listen  80;

    location / {
        proxy_pass  192.168.1.101:81;
    }
}


server {
    listen  81;

    location / {
        root  html;
    }
}

            任务2.2:实现动态转发

                 看下源码proxy_pass能不能使用变量

static char *
ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ...

    value = cf->args->elts;

    url = &value[1];

    n = ngx_http_script_variables_count(url);  // 找到这里了,可以使用变量

    if (n) {
        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

        sc.cf = cf;
        sc.source = url;  
        ...
     }
     ...
}

        改下配置,测试ok,继续往下走

server {
    listen  80;

    location / {
        set  $url 192.168.1.101:81;
        proxy_pass  $url;
    }
}

            任务2.3:根据api设置变量$url的值

                 好像没有现成的模块,脑袋里过滤了一遍,有的话必须是跟subrequest有关的模块,想起了 auth_request 模块,它可以配置一个http请求,根据http请求的返回结果决定给客户端是否正常访问,去看下源码先。

static ngx_int_t
ngx_http_auth_request_handler(ngx_http_request_t *r)
{ 
    ...
    if (ctx != NULL) {
        ...
        if (ngx_http_auth_request_set_variables(r, arcf, ctx) != NGX_OK) {  // 看函数名感觉这里有干货
            return NGX_ERROR;
        }

        /* return appropriate status */

        if (ctx->status == NGX_HTTP_FORBIDDEN) { // 403
            return ctx->status;
        }
        
        // 200 and ...
        if (ctx->status >= NGX_HTTP_OK
            && ctx->status < NGX_HTTP_SPECIAL_RESPONSE)
        {
            return NGX_OK;
        }

        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "auth request unexpected status: %d", ctx->status);

        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }  ...

    return NGX_AGAIN;
}

           从源码我们掌握两个信息:1、api返回状态码要为200  2、ngx_http_auth_request_set_variables 可能有我们要的信息,继续查看:

static ngx_int_t
ngx_http_auth_request_set_variables(ngx_http_request_t *r,
    ngx_http_auth_request_conf_t *arcf, ngx_http_auth_request_ctx_t *ctx)
{
    ...
    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
    v = cmcf->variables.elts;

    av = arcf->vars->elts;
    last = av + arcf->vars->nelts;

    // 遍历 arcf->vars 这个东东
    while (av < last) {  
        /*
         * explicitly set new value to make sure it will be available after
         * internal redirects
         */

        vv = &r->variables[av->index];

        if (ngx_http_complex_value(ctx->subrequest, &av->value, &val)
            != NGX_OK)
        {
            return NGX_ERROR;
        }

        vv->valid = 1;
        vv->not_found = 0;
        vv->data = val.data;
        vv->len = val.len;

        if (av->set_handler) {
            /*
             * set_handler only available in cmcf->variables_keys, so we store
             * it explicitly
             */

            av->set_handler(r, vv, v[av->index].data);  // 设置变量
        }

        av++;
    }

    return NGX_OK;
}

           代码逻辑很简单,遍历这个模块的配置的某个成员,肯定是跟变量有关的了,找配置信息了

static ngx_command_t  ngx_http_auth_request_commands[] = {

    { ngx_string("auth_request"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_http_auth_request,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },

    { ngx_string("auth_request_set"), // 名称很像设置变量,就是它了
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
      ngx_http_auth_request_set, // 看一下这函数实现,印证了猜测是正确的
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },

      ngx_null_command
};

       整理一下,就是当接收到api的返回信息后,模块处理了设置变量。so配置为如下,测试ok,继续

server {
    listen  80;

    location / {
        auth_request  /api.php; #用php模拟
        auth_request_set  $url 192.168.1.101:81; #保持简单,先用正确值模拟
        proxy_pass  $url;
    }

    location ~ \.php$ { # 为了处理上面的 /api.php 
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root/$fastcgi_script_name;
        include        fastcgi_params;
    }
}

         任务2.4:让$url的值从api返回信息里获取

         (请不要在2.3里一步搞定整个模拟,保持每步正确和简单,是不是很像代码重构的原则)

         我们要解决这个:auth_request_set   $url  192.168.1.101:81;

         nginx有什么变量可以让我们获取请求的返回信息呢,头部信息也可以(其实这里心里已经判断肯定只能从头部信息里获取,以对nginx的代码熟悉了解程度)。去看下获取变量值的函数吧。

ngx_http_variable_value_t *
ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
{
    ...
    v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);

    if (v) {
        if (v->flags & NGX_HTTP_VAR_INDEXED) {
            return ngx_http_get_flushed_variable(r, v->index);

        } else {

            vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));

            if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
                return vv;
            }

            return NULL;
        }
    }

    vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
    if (vv == NULL) {
        return NULL;
    }

    // 我清楚nginx可以通过 http_xxx 获取请求的头部信息 xxx: ...
    if (ngx_strncmp(name->data, "http_", 5) == 0) {

        if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name)
            == NGX_OK)
        {
            return vv;
        }

        return NULL;
    }

    // 这个没看过,不知道哪个版本加上的,感觉很意外,看名字应该就是我要找的
    if (ngx_strncmp(name->data, "sent_http_", 10) == 0) {
        // 这个函数怎么实现的,看了下类似上面的,上面用于获取header_in即请求,
           它用于获取header_out,就是我们要的响应信息
        if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name)
            == NGX_OK) 
        {
            return vv;
        }

        return NULL;
    }

    ...

    vv->not_found = 1;

    return vv;
}

         到这里心里已经很有数了,写php代码,并且直接访问测试正常

api.php

<?php

$url = "192.168.1.101:81";
header("url: $url");

         改nginx配置:        

server {
    listen  80;

    location / {
        auth_request  /api.php; #用php模拟
        auth_request_set  $url $sent_http_url; #保持简单,先用正确值模拟
        proxy_pass  $url;
    }

    location ~ \.php$ { # 为了处理上面的 /api.php 
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root/$fastcgi_script_name;
        include        fastcgi_params;
    }
} 

        搞定,心情特好 ,预期半个小时验证方案,提前5分钟完成。


5、整个方案整理:

a、> ./configure --with-http_auth_request_module && make && ./objs/nginx

b、nginx.conf

server {
    listen  80;

    location / {
        auth_request  /api.php; #用php模拟
        auth_request_set  $url $sent_http_url; #保持简单,先用正确值模拟
        proxy_pass  $url;
    }

    location ~ \.php$ { # 为了处理上面的 /api.php 
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root/$fastcgi_script_name;
        include        fastcgi_params;
    }
} 


server {
    listen  81;

    location / {
        root  html;
    }
}

   c、api.php

<?php

$url = "192.168.1.101:81";
header("url: $url")


转自:https://m.oschina.net/blog/347365
Nginx配置动态反向代理 Nginx配置动态反向代理。业务场景中有一个接口,需要根据不同业务代理几十个地址,如果使用传统代理模式需要一个个地址代理非常繁琐且工作量大增也不好维护,这个时候使用动态代理就非常方便了。请求地址:http://127.0.0.1:8080/proxy/127.0.0.1:2023/api/test。请求地址:http://127.0.0.1:8080/api/test。准备工作:起两个项目。 阅读详情

相关推荐

allegro如何设置走线等长

设置走线等长!

weixin_42499230的博客 6856

Nginx+lua通过url传参的方式实现动态代理

需求大致如下:通过url传参的方式,让Nginx代理到不同的服务器 浏览器输入:http://127.0.0.1/remote?port=8081被代理到:http://192.168.108.2:8081

冷门但实用:Python爬取微信公众号历史文章,突破微信反爬限制(2025有效)

2025年微信公众号爬取的核心是「冷门方法+指纹伪装」,而非常规接口破解,itchat-uos+Playwright组合是突破设备指纹的关键;登录态持久化、动态Token实时获取、频率严格控制是避免被封禁的三大核心;文章内容解析需解决2025新增的编码混淆问题,chardet+BeautifulSoup是冷门但有效的方案;合规是前提,爬取频率、数据用途需严格遵守平台/法律规则。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 3647

nginx动态请求代理配置

nginx动态请求代理配置

ApexPredator的博客 2373

配置Nginx作为动态应用程序代理

在本教学文章中,我们将学习如何将Nginx配置为代理动态应用程序,如PHP、Python或Node.js,以处理动态请求。通过将Nginx配置动态应用程序代理,我们可以提供高性能、可靠和安全的动态内容传递。本教程将介绍如何配置Nginx作为动态应用程序代理,并处理动态请求。在本教程中,我们学习了如何将Nginx配置为代理动态应用程序,以处理动态请求。通过按照上述步骤配置Nginx,并了解如何传递代理请求的头部信息,您可以确保Nginx能够可靠地代理动态应用程序,并提供动态内容传递的能力。

qq_44539748的博客 1965

Nginx动态反向代理(2022/11/12)

工作中经常遇到需要在前端访问第三方平台接口的情况,前端直接访问会遇到跨域、http 禁止调用 https 等问题,故需要在后台通过 Nginx 进行反向代理。随着第三方平台的增加,反向代理配置文件越来越复杂,因此笔者在考虑通过参数传递目标地址实现动态反向代理,本文将详细介绍实现过程。

xiaoQQya的博客 7300

基于 Nginx动态代理

小编精心为大家准备了一手资料以上Java高级架构资料、源码、笔记、视频。Dubbo、Redis、设计模式、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术【附】架构书籍BAT面试的20道高频数据库问题解析Java面试宝典Netty实战算法BATJ面试要点及Java架构师进阶资料《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取![外链图片转存中…(img-SZZuEqoU-1712894343639)]

2401_84048521的博客 1378

nginx 根据参数动态代理

这个反向代理表示访问80端口跳转到 http://myapp1 地址。现在有需求代理的目的地址由动态传参决定,不能配置成静态的,传的参数为URL,然后反向代理到URL地址。在配置过程中,会解决跳转后跨域问题和代理后地址自动拼接问题。

YSTXDONG的专栏 4017

Nginx- 生产环境 Nginx 的多进程与多线程配置优化

🔍 Nginx 生产环境多进程与多线程配置优化 本文深入探讨 Nginx 在高并发场景下的性能优化策略,重点分析多进程与多线程模型的优劣势及最佳实践。通过对比测试数据,揭示了 Nginx 事件驱动模型相比传统多线程架构的性能优势(内存节省15倍,吞吐量提升2倍)。文章提供了详细的配置指南,包括: 多进程优化: worker_processes设置原则(静态资源与动态代理的不同策略) worker_cpu_affinity绑核技术(实测提升23% QPS) NUMA架构下的高级调优技巧 异步I/O机制: e

千淘万漉虽辛苦,吹尽狂沙始到金 8493

【架构师成长必备】如何阅读一个开源项目的源码?【石杉的架构笔记】

目录 1、从最简单的源码开始:别幻想一步登天 2、循序渐进:先搞定底层依赖的技术 3、一定要以Hello World作为入口来阅读 4、抓大放小,边写注释边画图 5、反复三遍,真正理解源码 6、借力打力,参考源码分析书籍及博客 7、最后寄语:用几年时间锻造自己的核心技术 前言 这篇文章,给大家简单介绍一下很多同学都非常关心的一个问题:如何阅读一个开源项目的源码。 我相信很多同学...

P876643136的博客 704

Nginx- Nginx 核心配置文件结构与基础语法解析

📝 Nginx 核心配置文件摘要 本文深入解析了 Nginx 的核心配置文件结构与基础语法,主要内容包括: 层级结构:采用洋葱模型的分层配置体系,从主配置文件(nginx.conf)到http/server/location多级上下文嵌套 核心模块:详细介绍了main/events/http/server/location/upstream等关键配置模块的作用域和典型指令 语法规则:指令的基本结构、参数传递方式和继承覆盖机制 配置管理:include机制、配置加载顺序和热重载操作流程 实用指令:重点解析了

千淘万漉虽辛苦,吹尽狂沙始到金 1万+

Nginx- 自定义 Nginx 的错误页面样式与内容

📝 文章摘要 本文全面介绍了如何为Nginx配置自定义错误页面以提升用户体验和品牌一致性。主要内容包括: 为什么需要自定义错误页面: 改善第一印象,降低跳出率 保持品牌视觉一致性 增强安全性(隐藏服务器信息) 支持多语言和监控分析 Nginx的底层机制: 使用error_page指令实现错误重定向 关键配置项解析和安全性考虑(internal指令) 状态码修改技巧 静态错误页面实现: 文件结构规划建议 提供完整的404页面HTML+CSS示例代码 响应式设计和关键样式内联技巧 进阶功能: 动态内容生成 与

千淘万漉虽辛苦,吹尽狂沙始到金 1万+

Nginx- 反向代理进阶:域名转发与路径重写配置

Nginx反向代理进阶指南:域名转发与路径重写 本文深入探讨Nginx反向代理的高级应用,重点解析域名转发和路径重写两大核心功能: 核心知识点: 基础proxy_pass配置的路径处理机制 注意proxy_pass带路径与不带路径的区别 路径拼接规则及常见陷阱 多域名转发配置 通过server_name实现不同域名的独立路由 SSL证书的域名匹配策略 路径重写高级技巧 rewrite指令的正则表达式应用 路径前缀修改与后端服务解耦 重定向与内部重写的区别 实践建议: 统一路径规则(建议使用尾部斜杠) 确保H

千淘万漉虽辛苦,吹尽狂沙始到金 1万+

Java开发经典实战!java架构师技术图谱

美团一面: 中间省略掉大概几个问题,因为我不记得了,下面记得的基本都是我没怎么答好的。 了解SOA,微服务吗? 分布式系统如何负载均衡?如何确定访问的资源在哪个服务器上? 一.轮询。二.随机。三.最小响应时间。四. 最小并发数。五.哈希。 设计一个分布式负载均衡缓冲系统,如何快速定位到是那个服务器(使用key分段、一致性hash) 如何保证缓冲区和数据库之间的强一致性(使用加锁) HashMap高并发情况下会出现什么问题,(扩容问题) 说一说在浏览器中输入一个url后,直到浏览器显示页面的过程中发生了什么

m0_56830725的博客 230

Nginx如何支持HTTPS?含BATJM大厂

1. 前言 最近面试了几家公司,体验了一下电话面试和今年刚火起来的视频面试, 虽然之前就有一些公司会先通过电话面试的形式先评估下候选人的能力水平,但好像不多,至少我以前的面试形式100%都是现场面试。 面试过程中,不可避免的被问到了很多面试题,本篇博客就总结下面试过程中被问到的关于String的2道面试题,分别是: 如何判断一个字符串中某个字符出现的次数? 如何反转一个字符串? 其余的面试题,目前都已梳理出来,后续会以博客的形式进行分享。 One:JVM实践思维图(完整版) Two: 走近Java 概

100

【面试题】面试题 问题之书

一、Java基础 集合 HashMap 1.7和1.8的区别 源码阅读jdk1.8 ConcurrentHashMap的实现原理以及1.7和1.8的区别 Java提供的排序算法是怎么实现的? Object 序列化和反序列化底层的实现原理等相关问题 new String()一共创建了几个对象? Java Integer和String内存存储常见问题 hashCode和equals相关...

opi 364

07_Nginx_auth_request模块

07_Nginx_auth_request模块1. auth_request模块是什么2. auth_request模块的用途3. auth_request的启用4. auth_request的官方示例 1. auth_request模块是什么 ngx_http_auth_request_module模块(1.5.4+)实现了基于一子请求的结果的客户端的授权。如果子请求返回2xx响应码,则允许访问。如果它返回401或403,则访问被拒绝并显示相应的错误代码。子请求返回的任何其他响应代码都被认为是错误的。 a

田一一 8622

nginx配置属性监控、nginx代理动态服务器、nginx访客IP黑名单、负载均衡、平滑升级及tomcat安装与配置

同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。这样,当来自某一个IP的用户在后端Web服务器A上登录后,再访问该站点的其他URL,能保证其访问的还是后端web服务器A。解决服务器的高并发压力,提高应用程序的处理性能;# 使用老的nginx进程创建新的进程,此时会出现两套master进程,这个时候处理客户请求的就是新的nginx服务了。简述:即把请求转发给连接数较少的后端服务器,解决轮询导致后端负载较高的问题,可以达到更好的负载均衡效果。

m0_74614835的博客 1613

nginx使用lua文件动态代理websocket

创建的websocket服务,可以直接使用http://192.168.11.199:21899/访问,如下 但现在不想对外暴露websocket的端口号,通过nginx反向代理:待访问的url为http://192.168.11.199:81/?destip=192.168.11.199:21899 destip参数即为websocket服务的ip与port 一、第一次的nginx.conf配置如下 1.1、nginx.conf location / { ...

无痕的博客 2791

Blender:超详细的甜甜圈制作教程

根据Youtube上的作者Blender Guru制作的教程整理成的文档,详细的介绍了使用Blender制作一只甜甜圈的过程。

上一篇: nginx 取不到返回值的分析过程
下一篇: nginx支持js语言
ronon77
博客等级 码龄15年 96粉丝 746原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值