• 初识Nginx


    1.为什么选择Nginx

    Nginx是当前最流行的Web服务器之一,与Apache相比,Nginx在高并发情况下具有巨大的性能优势。

    Nginx具有高扩展性,高可靠性,低内存消耗等特点,并且Nginx拥有无数官方功能模块,第三方功能模块,这些功能模块可以叠加以实现更加强大/复杂的功能。

    选择Nginx的核心理由是它能在支持高并发请求的同时保持高效的服务。

    2.Nginx的安装与运行Nginx官方下载地址:http://nginx.org/en/download.html

    解压:$ tar -zxvf nginx-1.4.4.tar.gz

    进入nginx目录,执行如下命令:

    $ ./configure
    $ make
    $ make install

    启动Nginx:$ /usr/local/nginx/sbin/nginx

    检测Nginx是否成功运行:打开http://localhost/,看是否有Nginx欢迎界面。

    停止Nginx服务:/usr/local/nginx/sbin/nginx -s stop

    3.开发一个简单的HTTP模块-Hello World

    Nginx提供了一种简单的方式将第三方模块编译到Nginx中。

    首先把源代码文件全部放到一个目录中:

    my_test_module/

    ├── config

    └── ngx_http_mytest_module.c

    configure用于通知Nginx如何编译本模块,而且必须命名为configure。configure文件其实是一个可执行shell脚本,需要定义以下3个变量:

    ngx_addon_name:仅在configure执行时使用,一般设置为模块名称。
    HTTP_MODULES:保存所有的HTTP模块名称,每个HTTP模块间由空格相连。
    NGX_ADDON_SRCS:用于制定新增模块的源代码,多个待编译的源代码间以空格相连。

    这里configure内容如下:

    ngx_addon_name=ngx_http_mytest_module
    HTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module"
    NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_module.c"
    

     这里ngx_http_mytest_module.c内容如下:

    #include <ngx_config.h>
    #include <ngx_core.h>
    #include <ngx_http.h>
    
    static char *
    ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    
    static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r);
    
    static ngx_command_t  ngx_http_mytest_commands[] =
    {
    
        {
            ngx_string("mytest"),
            NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS,
            ngx_http_mytest,
            NGX_HTTP_LOC_CONF_OFFSET,
            0,
            NULL
        },
    
        ngx_null_command
    };
    
    static ngx_http_module_t  ngx_http_mytest_module_ctx =
    {
        NULL,                              /* preconfiguration */
        NULL,                  		/* postconfiguration */
    
        NULL,                              /* create main configuration */
        NULL,                              /* init main configuration */
    
        NULL,                              /* create server configuration */
        NULL,                              /* merge server configuration */
    
        NULL,       			/* create location configuration */
        NULL         			/* merge location configuration */
    };
    
    ngx_module_t  ngx_http_mytest_module =
    {
        NGX_MODULE_V1,
        &ngx_http_mytest_module_ctx,           /* module context */
        ngx_http_mytest_commands,              /* module directives */
        NGX_HTTP_MODULE,                       /* module type */
        NULL,                                  /* init master */
        NULL,                                  /* init module */
        NULL,                                  /* init process */
        NULL,                                  /* init thread */
        NULL,                                  /* exit thread */
        NULL,                                  /* exit process */
        NULL,                                  /* exit master */
        NGX_MODULE_V1_PADDING
    };
    
    
    static char *
    ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
        ngx_http_core_loc_conf_t  *clcf;
    
        //首先找到mytest配置项所属的配置块,clcf貌似是location块内的数据
    //结构,其实不然,它可以是main、srv或者loc级别配置项,也就是说在每个
    //http{}和server{}内也都有一个ngx_http_core_loc_conf_t结构体
        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    
        //http框架在处理用户请求进行到NGX_HTTP_CONTENT_PHASE阶段时,如果
    //请求的主机域名、URI与mytest配置项所在的配置块相匹配,就将调用我们
    //实现的ngx_http_mytest_handler方法处理这个请求
        clcf->handler = ngx_http_mytest_handler;
    
        return NGX_CONF_OK;
    }
    
    
    static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r)
    {
        //必须是GET或者HEAD方法,否则返回405 Not Allowed
        if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)))
        {
            return NGX_HTTP_NOT_ALLOWED;
        }
    
        //丢弃请求中的包体
        ngx_int_t rc = ngx_http_discard_request_body(r);
        if (rc != NGX_OK)
        {
            return rc;
        }
    
        //设置返回的Content-Type。注意,ngx_str_t有一个很方便的初始化宏
    //ngx_string,它可以把ngx_str_t的data和len成员都设置好
        ngx_str_t type = ngx_string("text/plain");
        //返回的包体内容
        ngx_str_t response = ngx_string("Hello World!");
        //设置返回状态码
        r->headers_out.status = NGX_HTTP_OK;
        //响应包是有包体内容的,所以需要设置Content-Length长度
        r->headers_out.content_length_n = response.len;
        //设置Content-Type
        r->headers_out.content_type = type;
    
        //发送http头部
        rc = ngx_http_send_header(r);
        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
        {
            return rc;
        }
    
        //构造ngx_buf_t结构准备发送包体
        ngx_buf_t                 *b;
        b = ngx_create_temp_buf(r->pool, response.len);
        if (b == NULL)
        {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
        //将Hello World拷贝到ngx_buf_t指向的内存中
        ngx_memcpy(b->pos, response.data, response.len);
        //注意,一定要设置好last指针
        b->last = b->pos + response.len;
        //声明这是最后一块缓冲区
        b->last_buf = 1;
    
        //构造发送时的ngx_chain_t结构体
        ngx_chain_t		out;
        //赋值ngx_buf_t
        out.buf = b;
        //设置next为NULL
        out.next = NULL;
    
        //最后一步发送包体,http框架会调用ngx_http_finalize_request方法
    //结束请求
        return ngx_http_output_filter(r, &out);
    }
    

    修改配置文件:$ vim //usr/local/nginx/conf/nginx.conf,增加下面的配置:

    http {
        include mime.types;
        default_type application/octet-stream;
        server {
            listen 80;
            server_name localhost;
            location / {
                root html;
                index index.php index.html index.htm;
            }
            location /test {
                mytest;
            }
        }
    }
    

    编译安装模块:

    ./configure --prefix=/usr/local/nginx(指定安装部署后的根目录) --add-module=/home/luhaiyang/ngxdev/ngx_http_mytest(新模块存放目录)  
    make  
    sudo make install 
    

     测试模块:$ curl -i http://localhost/test

    HTTP/1.1 200 OK
    Server: nginx/1.4.4
    Date: Mon, 02 Dec 2013 09:35:50 GMT
    Content-Type: text/plain
    Content-Length: 12
    Connection: keep-alive
    
    Hello World!
    

    阅读《深入理解Nginx》,简单知道了Nginx的基本概念,并参照书籍配置了一个静态Web服务器。在我的学习习惯里,我喜欢先赶紧实现一个简单的例子,这样对于新事物有一个大概的总体的了解,知道它到底是什么,能干什么,然后再继续深入挖掘理解。

    最近与基友ZK讨论学习习惯的问题,他这段之间在接受java培训,与我讲述了他的烦恼。他认为只有学习掌握好了当前内容才能继续下一阶段的学习,所以不能理解他的项目经理提前讲解后面的知识章节,然后我跟他分享了我的学习方法。我认为这是两种不同的学习习惯,只有适合自己的才是最好的。

    参考资料:《深入理解Nginx》

  • 相关阅读:
    Day 29 作业/服务端实现接收客户端的连接并发
    Day 28 操作系统发展/进程
    Day 27 作业(FTP)
    Day 27 subprocess模块/粘包问题以及解决/UDP协议/socketserver
    Day 26 作业
    Day 26 互联网协议/Socket套接字
    Day 22 绑定方法和非绑定方法/isinstance/issubclass/反射/魔法方法/单例模式
    Day 21 作业
    Day 21 组合/封装/property特性/多态和多态性/抽象类/鸭子类型
    day 20 作业
  • 原文地址:https://www.cnblogs.com/Rosanna/p/3453201.html
Copyright © 2020-2023  润新知