分类 Nginx 下的文章

理解HTTP之keep-alive

理解HTTP之keep-alive

在前面一篇文章中讲了TCP的keepalive,这篇文章再讲讲HTTP层面keep-alive。两种keepalive在拼写上面就是不一样的,只是发音一样,于是乎大家就都迷茫了。HTTP层面的keep-alive是我们接触比较多的,也是大家平时口头上的"keepalive"。下面我们就来谈谈HTTP的keep-alive

短连接&长连接&并行连接

再说keep-alive之前,先说说HTTP的短连接&长连接。

  • 短连接

    所谓短连接,就是每次请求一个资源就建立连接,请求完成后连接立马关闭。每次请求都经过“创建tcp连接->请求资源->响应资源->释放连接”这样的过程

  • 长连接

    所谓长连接(persistent connection),就是只建立一次连接,多次资源请求都复用该连接,完成后关闭。要请求一个页面上的十张图,只需要建立一次tcp连接,然后依次请求十张图,等待资源响应,释放连接。

  • 并行连接

    所谓并行连接(multiple connections),其实就是并发的短连接。

- 阅读剩余部分 -

理解TCP之Keepalive

理解Keepalive(1)

大家都听过keepalive,但是其实对于keepalive这个词还是很晦涩的,至少我一直都只知道一个大概,直到之前排查线上一些问题,发现keepalive还是有很多玄机的。其实keepalive有两种,一种是TCP层的keepalive,另一种是HTTP层的Keep-Alive。这篇文章先说说tcp层的keepalive

tcp keepalive

设想有一种场景:A和B两边通过三次握手建立好TCP连接,然后突然间B就宕机了,之后时间内B再也没有起来。如果B宕机后A和B一直没有数据通信的需求,A就永远都发现不了B已经挂了,那么A的内核里还维护着一份关于A&B之间TCP连接的信息,浪费系统资源。于是在TCP层面引入了keepalive的机制,A会定期给B发空的数据包,通俗讲就是心跳包,一旦发现到B的网络不通就关闭连接。这一点在LVS内尤为明显,因为LVS维护着两边大量的连接状态信息,一旦超时就需要释放连接。

Linux内核对于tcp keepalive的调整主要有以下三个参数

1. tcp_keepalive_time

 the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further

2. tcp_keepalive_intvl

 the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime

3. tcp_keepalive_probes

 the number of unacknowledged probes to send before considering the connection dead and notifying the application layer

Example

$ cat /proc/sys/net/ipv4/tcp_keepalive_time
  7200
$ cat /proc/sys/net/ipv4/tcp_keepalive_intvl
  75
$ cat /proc/sys/net/ipv4/tcp_keepalive_probes
  9

当tcp发现有tcp_keepalive_time(7200)秒未收到对端数据后,开始以间隔tcp_keepalive_intvl(75)秒的频率发送的空心跳包,如果连续tcp_keepalive_probes(9)次以上未响应代码对端已经down了,close连接

在socket编程时候,可以调用setsockopt指定不同的宏来更改上面几个参数

TCP_KEEPCNT: tcp_keepalive_probes

TCP_KEEPIDLE: tcp_keepalive_time

TCP_KEEPINTVL: tcp_keepalive_intvl

- 阅读剩余部分 -

Nginx负载均衡+监控状态检测

Nginx负载均衡+监控状态检测

想用Nginx或者Tengine替代LVS,即能做七层的负载均衡,又能做监控状态检测,一旦发现后面的realserver挂了就自动剔除,恢复后自动加入服务池里,可以用Tengine的ngx_http_upstream_check_module模块。该模块在Tengine-1.4.0版本以前没有默认开启,它可以在配置编译选项的时候开启:./configure --with-http_upstream_check_module。

Nginx.conf 配置

http {
    upstream fire_server{
    ip_hash;
    server 192.168.1.1:80;
    server 192.168.1.2:80;

    check interval=3000 rise=2 fall=5 timeout=1000 type=http ;
    check_http_send "GET /status.html HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx ;
    }

    server {
        listen       80;
        server_name  localhost default;

        location / {
            proxy_pass http://fire_server;
            access_log logs/fire_server_access.log main;
            error_log logs/error.log debug;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }   
}

- 阅读剩余部分 -

Nginx实现TCP反向代理

之前对于Nginx的理解一直都是认为是基于HTTP层的反向代理+负载均衡,今天想用Nginx实现TCP层的反向代理,实现基于TCP的端口转发,之前一篇文章iptables实现tcp端口转发已经用iptables实现了。

安装

$ git clone git@github.com:yaoweibin/nginx_tcp_proxy_module.git
$ wget http://tengine.taobao.org/download/tengine-2.0.3.tar.gz
$ tar -zxvf  tengine-2.0.3.tar.gz
$ cd tengine-2.0.3
这一步很重要,根据Ngx的源码打patch,不然就会编译失败
$ patch –p1 < /path/nginx_tcp_proxy_module
$ ./configure  --user=www --group=www --prefix=/opt/nginx --with-syslog --add-module=/path/nginx_tcp_proxy_module/
$ make && sudo make install

TCP反向代理配置

模块指令是TCP,它是不属于HTTP框架内的,所以和HTTP{}同级别。

events {
    worker_connections  1024;
}

http {
    ...
}

tcp {

    upstream firefoxbug {
        # simple round-robin
        server localhost:2221;
        server localhost:2222;
        check interval=3000 rise=2 fall=5 timeout=1000;

        #check interval=3000 rise=2 fall=5 timeout=1000 type=ssl_hello;

        #check interval=3000 rise=2 fall=5 timeout=1000 type=http;
        #check_http_send "GET / HTTP/1.0\r\n\r\n";
        #check_http_expect_alive http_2xx http_3xx;
    }

    server {
        listen 9999;
        proxy_pass firefoxbug;
    }
}

upstream的模块依赖是Ngx之前HTTP反向代理的模块,对于负载均衡的方式配置可以查看Nginx Upstream负载均衡模块

结果

所有到Nginx的9999端口都被转发到22221和22222端口,实现了forward功能。

Nginx Pugre返回404

之前一直都是认为purge返回404的原因就是因为所请求的资源并没有被cache,今天在测试过程中无意发现这点认识有错误。

基础环境

  • 确保编译Nginx的时候添加了proxy_cache和purge模块
  • 测试域名: www.cdnhub.org
  • 测试URL: http://www.cdnhub.org/1.txt
  • 资源路径: echo "firefoxbug" > /var/www/cdnhub/1.txt
  • Cache文件安装域名存放,在/home/cache下面
  • 具体查看Nginx配置文件

- 阅读剩余部分 -

通过Nginx配置文件抵御攻击

前言

大家好,我们是OpenCDN团队的Twwy。这次我们来讲讲如何通过简单的配置文件来实现nginx防御攻击的效果。

其实很多时候,各种防攻击的思路我们都明白,比如限制IP啊,过滤攻击字符串啊,识别攻击指纹啦。可是要如何去实现它呢?用守护脚本吗?用PHP在外面包一层过滤?还是直接加防火墙吗?这些都是防御手段。不过本文将要介绍的是直接通过nginx的普通模块和配置文件的组合来达到一定的防御效果。

验证浏览器行为

- 阅读剩余部分 -

Nginx反向代理和php解析配置

Nginx纯反向代理配置

upstream  firefoxbug{
        ip_hash; 
        server 10.161.171.87:80;
        server 10.160.55.81;
        server 10.160.55.93;
}

server {
    server_name         www.firefoxbug.net firefoxbug.net;
    listen              80;
    gzip                on;


    error_log           /home/logs/www_firefoxbug_net_error.log error;
    access_log          /home/logs/www_firefoxbug_net_access.log;

    ## Bypass For All
    location / {
        proxy_redirect      off;
        proxy_pass          http://firefoxbug; 
        proxy_set_header Host   $host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

- 阅读剩余部分 -

Nginx反代内容替换

Nginx做反向代理的时候因为流量都是从Nginx过,所以有时候会有需求修改页面,替换个元素,标签,logo等等。这个功能可以用ngx_http_subs_filter_module来解决。

具体的安装过程和普通的三方模块一样

- 阅读剩余部分 -

Nginx Cache中$request_filename

对于Nginx的$request_filename变量指的就是请求的资源路径。在原先OpenCDN节点端配置里面是这样的。

location ~ .*\.(png|html|htm|ico|jpg|jpeg|bmp|gif|js|css)$ {
        ## 忽略浏览器的缓存
        proxy_ignore_headers Cache-Control;
        proxy_ignore_headers Expires;

        proxy_cache cache_one;
        proxy_cache_valid 200 304 1h;

        proxy_cache_key $host$uri$is_args$args;
        expires 1h;
        ## 此处为host锁定,可定制有无
        proxy_set_header        Host    $host;

        add_header OpenCDN-Cache "$upstream_cache_status";

       if (!-f $request_filename) {
                proxy_pass http://ocdn_www.firefoxbug.net;
                break;
        }
}

- 阅读剩余部分 -

Nginx缓存详细配置

Nginx的proxy_cache是有大讲究的。

用proxy_cache来指定cache的名字空间,proxy_cache_path来指定cache的属性。
proxy_cache_path /home/cache levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=10g;
cache的路径是/home/cache,levels是2级目录(名字分别为一个字符和两个字符),名字是cache_one,分配的内存空间是200M,有效期是1天,最大可以存取的磁盘大小是10G,一旦满了就会被移除。

- 阅读剩余部分 -

Nginx和Apache区别

转载请注明出处:http://www.firefoxbug.com/?p=1932

Nginx的高并发得益于其采用了epoll模型,与传统的服务器程序架构不同,epoll是linux内核2.6以后才出现的。下面通过比较Apache和Nginx工作原理来比较。

传统Apache都是多进程或者多线程来工作,假设是多进程工作(prefork),apache会先生成几个进程,类似进程池的工作原理,只不过这里的进程池会随着请求数目的增加而增加。对于每一个连接,apache都是在一个进程内处理完毕。具体是 recv(),以及根据 URI 去进行磁盘I/O来寻找文件,还有 send()都是阻塞的。其实说白了都是 apche 对于套接字的I/O,读或者写,但是读或者写都是阻塞的,阻塞意味着进程就得挂起进入sleep状态,那么一旦连接数很多,Apache必然要生成更多的进程来响应请求,一旦进程多了,CPU对于进程的切换就频繁了,很耗资源和时间,所以就导致apache性能下了,说白了就是处理不过来这么多进程了。其实仔细想想,如果对于进程每个请求都没有阻塞,那么肯定效率会提高很多。

- 阅读剩余部分 -

Nginx源码分析核心模块加载

装载请注明出处:http://www.firefoxbug.com/?p=2053

之前一篇Nginx源码分析模块加载大概描述了Nginx官方定义的6个核心模块,本文再详细介绍这几类模块的加载。这些核心模块都属于宏NGX_CORE_MODULE,对应的模块上下文配置结构体是 ngx_core_module_t。

typedef struct {
    ngx_str_t             name;                                         //模块名,即ngx_core_module_ctx结构体对象的
    void               *(*create_conf)(ngx_cycle_t *cycle);             //解析配置项,nginx框架会调用create_conf方法
    char               *(*init_conf)(ngx_cycle_t *cycle, void *conf);   //解析配置项完成后,nginx框架会调用init_conf方法
} ngx_core_module_t;

NGX_CORE_MODULE这6类核心模块都用ngx_core_module_t接口定义上下文。

- 阅读剩余部分 -

Nginx代理被墙域名

转载请注明出处:http://www.firefoxbug.com/?p=2042

今天一用户想用OpenCDN使用被墙域名,所谓被墙域名和未备案域名还是有区别的。域名被墙,是指被中国的GFW防火墙屏蔽,使用域名访问时,出现连接重置的情况。我猜想就是GFW把HTTP的URL和Host字段进行过滤,所以某个域名的包都被deny了,但是可以通过Nginx反向代理来解决这个问题。下面大概说明下

www.ooxx.com是被墙域名
源站IP是192.168.1.1(国外)
反代NginxIP是192.168.2.1(国内)

- 阅读剩余部分 -

Nginx源码分析模块指令加载

上文写到了Nginx配置文件读取以及解析,本文介绍模块的指令加载。还是以前文的nginx_move_domain_cache为例

server {
        listen 80;
        server_name www.firefoxbug.net;
        gzip on;
 
        location /mv_cache{
                mv_cache;
        }
        ....
}

上面有一模块mv_cache,这个模块里面的指令是mv_cache,参数是0个。再比如server_name也是一个指令,参数是一个"www.firefoxbug.net"。调用前文的ngx_conf_parse读取配置文件,然后调用handler函数进行解析,对于普通的处理(普通指令),会调用ngx_conf_handler,这里再回顾下模块的指令数组定义结构

- 阅读剩余部分 -

Nginx源码分析模块加载

转载请注明出处:http://www.firefoxbug.com/?p=2030

前文说了Nginx里万物皆模块,今天描述下模块的加载,因为模块的加载是一个递归的过程,所以比较难以理解。

模块类型


Nginx官方定义了6种核心模块,定义宏声明是NGX_CORE_MODULE,分别是ngx_core_module,ngx_http_module,ngx_events_module,ngx_mail_module,ngx_errlog_module,ngx_openssl_module。这6种核心模块又可以定义自己全新的模块,比如ngx_events_module重新定义events类型为NGX_EVENT_MODULE,ngx_http_module定义http模块类型NGX_HTTP_MODULE。在上文叙述的ngx_command_s第二个字段就是指定这些模块类型。

- 阅读剩余部分 -

Nginx源码分析模块化

断断续续读了近半个多月Nginx的源码,感觉还是比较吃力,因为Nginx模块化的设计带来的是复杂的结构体以及回调函数,逻辑比较复杂。到现在也不知道改怎么写好Nginx源码分析这类博客,但是只能硬着头皮去写,希望写的过程中能出现各种疑问从而解决。目前还没完整地读完源码,按照Nginx执行顺序写还力不从心,所以先从如何编写三方模块开始。

在之前一篇文章写了一个Nginx删除域名Cache的三方模块 http://www.firefoxbug.com/?p=1985,Nginx源码分析就从这个模块进行分析。至于什么是模块?我们从Nginx的配置文件出发来解释。

- 阅读剩余部分 -

Nginx动态加载模块

参考 http://tengine.taobao.org/document/dso.html

Tengine支持了动态加载模块,个人感觉这使得Nginx这个优秀的设计更加完美,在开发三方模块的时候大大提高了效率。下面举例子如何加载一个三方的模块,加载前面的站点cache一键清除模块(http://www.firefoxbug.com/?p=1985)。

/usr/local/nginx/sbin/dso_tool模块已经把编译成动态库的参数都写好了,只需要调用这个工具就行,参数是源码路径,包含要configure文件。

/usr/local/nginx/sbin/dso_tool -a=/home/nginx_move_domain_cache
或者
/usr/local/nginx/sbin/dso_tool --add-module=/home/node/Tengine/nginx_move_domain_cache

这样会自动生成 ngx_http__module.so 动态库并且dso_tool工具会将其copy到/usr/local/nginx/modules,下面就是配置Nginx。
events {
        use epoll;
        worker_connections  51200;
}

dso {
        load ngx_http_move_domain_cache_module.so;
}

http {
      ....
}

这样就能动态的加载 .so 模块,dso也是一个main级的配置。

Nginx添加访客地理位置到日志(GeoIP模块)

之前项目里用Nginx吐出access日志,然后用awstats来统计分析,结果对于访客地理位置比较头痛,于是自己写了几个程序查找(纯真库和GeoIP查找的方法不一样),今天看Nginx源码时候发现了可以利用--with-http_geoip_module这个模块,然后指定变量到日志。具体会有瓶颈,下面看怎么实现。

GeoIP库安装

- 阅读剩余部分 -

Nginx一键清除域名下Cache

装载请注明出处:http://www.firefoxbug.com/?p=1985
在前面一篇文章 http://www.firefoxbug.com/?p=1861 已经介绍如何把站点缓存分域名存放。相比之前的purge一个个URL刷新,按照域名存放对于站点Cache一键刷新是很方便的。本文会介绍如何通过开发一个Nginx三方模块,一键刷新某个域名站点下缓存。 注意:在使用下面模块之前必须根据前文,站点Cache已经按照目录存储,目录在 /home/cache/下。比如 www.firefoxbug.net 的 Cache 是 /home/cache/www.firefoxbug.net/ ,通过模块能一键清除此目录cache。

- 阅读剩余部分 -