通过域名实现固定IP的Nginx转发配置

经常我们要验证线上某台服务器的单点服务是否正常.这个我相信有很多办法.很多的是通过Cookie的方式,Nginx读取配置实现动态转发.
而我们直接使用域名转发.对产品和测试更加友好,不需要手动用工具添加cookie.  

比如我们的服务地址是 http://blog.friddle.me而针对单点可以这样http://192-11-11-2.blog.friddle.me前面是固定ip的特殊写法.后面是服务地址.这样产品和测试单独测试这台就很方便的直接用域名就能访问了.特别轻松.   

我们需要解决的三个问题是:

  1. 各种网页资源格式是跟域名绑定的.
  2. 重定向是代码返回地址
  3. gzip的坑

这个是实现后的Nginx配置

      server {
        listen       80;
        server_name *.blog.friddle.me;
        access_log  logs/blog.friddle.me main;

        location / {
            set $forward_server '';
            set_by_lua_block $forward_server {
                local t=ngx.var.host;
                t=string.gmatch(t, "[^.]+")();
                t=string.gsub(t,"-",".");
                return t;
            }

            proxy_set_header Host "blog.friddle.me";
            proxy_set_header client-real-url $scheme://$host/$request_uri;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header Accept-Encoding "";
            proxy_pass http://$forward_server:8080;
            proxy_redirect http://blog.friddle.me http://$host;
            sub_filter 'blog.friddle.me' '$host';
            sub_filter_once off;
            sub_filter_types *;
        }

在此之前我们要解决两个坑.一个是set_by_lua_block是lua的nginx模块.是默认不带的.另外一个是sub_filter的模块也是默认不带的.

首先来说解决方案.有两种方式: 1.第一种可以用agentzh大大的openrsty.默认带lua模块
但是要重新编译下 ./configure --with-http_sub_module 即可:恩具体细节不说了    

2.第二种是下载nginx或者tengine.编译带lua模块和http_sub模块
提供一下Docker的buildFile.大家可以参考下安装执行

FROM  ubuntu  
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list

RUN apt-get update&&apt-get install -y curl build-essential libpcre++-dev libssh-dev  
RUN mkdir /temp||true&&curl http://tengine.taobao.org/download/tengine-2.1.2.tar.gz -o /temp/tengine.tar.gz &&\  
       cd /temp/ && tar -xzvf /temp/tengine.tar.gz -C /temp/&&mv /temp/tengine-2.1.2 /temp/tengine && \
      curl https://codeload.github.com/simpl/ngx_devel_kit/tar.gz/v0.3.0 -o /temp/ngx_dev.tar.gz && \
      tar -xzvf /temp/ngx_dev.tar.gz -C /temp/&&mv /temp/ngx_devel_kit-0.3.0 /temp/ngx_dev && \
      curl https://codeload.github.com/openresty/lua-nginx-module/tar.gz/v0.10.5 -o /temp/nginx_lua.tar.gz && \
      tar -xzvf /temp/nginx_lua.tar.gz -C /temp/&&mv /temp/lua-nginx-module-0.10.5 /temp/nginx_lua && \
      curl http://luajit.org/download/LuaJIT-2.0.3.tar.gz -o /temp/lua.tar.gz && \
      tar -xzvf /temp/lua.tar.gz -C /temp/ &&mv /temp/LuaJIT-2.0.3 /temp/lua

ENV LUAJIT_LIB /usr/local/lib/luajit/  
ENV LUAJIT_INC /usr/local/include/luajit-2.0/  
RUN bash -c "cd /temp/lua&&make&&make install"  
WORKDIR /temp/tengine/  
RUN ./configure --prefix=/usr/local/tengine --with-ld-opt="-Wl,-rpath,/usr/local/lib" --add-module=/temp/nginx_lua --add-module=/temp/ngx_dev --with-http_sub_module &&make&&make install  
WORKDIR /usr/local/tengine/
首先拿到域名ip
            set_by_lua_block $forward_server {
                local t=ngx.var.host;
                t=string.gmatch(t, "[^.]+")();
                t=string.gsub(t,"-",".");
                return t;
            }

这是一段nginx的lua语言.这段代码的用处就是获得http://192-11-11-2.blog.friddle.me192-11-11-2然后转换成192.11.11.2,然后再返回给nginx作为一个变量.

lua没有直接的split函数的,而string.gmatch(t, "[^.]+") 是匹配正则.返回第一个匹配到的值.前面是需要匹配的string,后面是正则,返回的是一个iterator.不是数组.意味着不是去获得[0]去获得第一个函数.而是执行第一次.就获得第一个匹配到的正则

gusb是一个很简单的替换函数了.第一个参数是是字符串.第二个是需要替换的字符.第三个是替换的字符

再进行转发
            proxy_set_header Host "blog.friddle.me";
            proxy_set_header client-real-url $scheme://$host/$request_uri;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header Accept-Encoding "";
            proxy_pass http://$forward_server:8080;

proxy_pass可以直接使用我们通过lua解析出来的ip.端口就只能针对不同的业务上游自己设置了.淡然.你也可以规则写的更加复杂点.但是不推荐.
当当当当:核心任务完成了.

但是我们遇到了前面说的三个问题. 1. 各种静态资源地址是跟域名绑定的.比如你的css和js都是使用的blog.friddle.me/css/hello.css这种绝对路劲(cdn大法好)
拿出subfilter大法.返回的html网页我们直接用nginx替换字符串.subfilter就是干这事情的

            sub_filter 'blog.friddle.me' '$host';
            sub_filter_once off;
            sub_filter_types *;

首先我们用sub_filter 把服务端返回的blog.friddle.me重新替换成我们请求的host.恩直接用$host就行 sub_filter_once off 然后关掉自渲染一次的选项. sub_filter_types * 哪些资源类型要取代

重定向地址的问题.比如我们做了某个操作后端会重定会定向到blog.friddle.me,但是我们并不想重定向到blog.friddle.me而是http://192-11-11-2.blog.friddle.me 请使用proxy_redirect http://blog.friddle.me http://$host;

有时候你发现你的subfilter没用.文件没有替换.很有可能是因为你的html被压缩了.subfilter不识别.怎么办了? proxy_set_header Accept-Encoding ""; 告诉上游.你只接受文本格式.不接受压缩.

这样是不是就很方便的查看单点了?而且还是动态的不需要多一台就去配置一台服务器.特别方便.也不需要手动改cookie.更加方便.

friddle

继续阅读此作者的更多文章