NGINX源码之:listen和server_name命令与listening监听创建

2023-11-02

在http块的server块解析中,通过解析listen和server_name命令配置,完成端口监听的初始化,虚拟主机配置关联,实现从host+port到虚拟主机的映射关系。在进入解析源码之前,先来看看server块集中配置:

server {
        listen       8081 default;//default作为默认虚拟主机配置,当不匹配其他servername时,默认使用该配映射;*:8081与8081等效
        server_name  localhost;
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }


    server{
        listen localhost:8081;//localhost会被解析出两个ip,一个是ipv4:127.0.0.1;一个是ipv6 [::1]
        server_name www.a.com www.b.com *.c.com;
        location / {
            root   html;
            index  index.html index.htm;
        }
    }
    server{
        listen localhost:8081;//有两个相同的listen配置时,才会构建servername的hash表
        server_name www.test.com  *.t.com;
        location /test {
            root   html;
            index  index.html index.htm;
        }
    }

    server{
        listen 127.0.0.1:8082;
        server_name www.a.com .c.com ~^www\.d\..*$;//设置正则格式的servername
        location / {
            root   html;
            index  index.html index.htm;
        }
    }
    server{
        listen 127.0.0.1:8083 default_server;//default_server等同于default
        server_name www.a.com .c.com *.test.com;
        location / {
            root   html;
            index  index.html index.htm;
        }
    }

一、listen命令解析
在解析server块时,首先解析listen命令,这时进入ngx_http_core_listen()方法:
在这里插入图片描述
下面主要看下的ngx_parse_url()与ngx_http_add_listen()两个方法
1、ngx_parse_url()
在这里插入图片描述
这里重点关注ipv4的处理:ngx_parse_inet_url();

在这里插入图片描述
ngx_inet_resolve_host() 将配置的hostname通过操作系统hosts文件解析出对应的一个或多个ip,再分别每个ip调用ngx_inet_add_addr()
在这里插入图片描述
经过上面的URL解析,大概有两种结构,一种是单个ip的,一种是经过host解析出多个ip的:
单个ip配置的,如listen 8081

在这里插入图片描述
多个ip配置的,如listen localhost:8081:
在这里插入图片描述

2、ngx_http_add_listen()
在这里插入图片描述
ngx_http_add_listen方法完成的结构如下:
在这里插入图片描述
最终,在整个listen配置解析阶段,生成的结构如下:

在这里插入图片描述

在ports数组中,每个端口可能有两种port元素(ipv4的port元素,ipv6的port元素),每个port元素可能有多个addr,如8081,加入同时配置多个server块,每个server的listen配置分别为 8081、localhost:8081,ports会有两个8081的port元素,那么ipv4port元素中的addrs元素就有两个,分别为0.0.0.0:8081、127.0.0.1:8081;ipv6port元素的addrs数组中元素只有一个[::]:8081;
当有多个server块,同时配了相同的listen,如多个server块配置listen localhost:8081,那么127.0.0.1:8081、[::]:8081对应的ngx_http_conf_addr元素中的servers数组就会有多个元素。

在给sockaddr赋值sin_port时,需要将端口号转成网络字节序,网络字节序用的都是大端字节序。内存读取都是按字节读取,每次读取8位,将8081转换字节序:
8081二进制为:0001 1111 1001 0001;为小端字节序,即每8位从左往右高位到地位,而大端字节序,每8位从左往右是低位到高位;那么转换后为1001 0001 0001 1111,十进制为37141

二、server_name命令解析

在这里插入图片描述

server_name解析完成每个server_name配置关联对应的srv_conf,后续将对server_name优化构建hash表,可通过hash表查找每个server_name对应的srv_conf配置。

三、ngx_http_optimize_servers()虚拟主机优化
在这里插入图片描述
1、ngx_http_server_names()
方法将单个addr的多个server块配置中server_names配置建立server_name到server块配置srv_conf的映射,然后将多个server块所有的server_name的映射构建hash表。具体构建hash表的方法,参考我的另一篇博客ngx_hash,addr的hash指针指向构建的hash表。
仅以本例,构造的结构如下:
在这里插入图片描述

2、ngx_http_init_listening()
在这里插入图片描述
2.1、ngx_http_add_listening()
在这里插入图片描述
2.2、ngx_http_add_addrs()
在这里插入图片描述在这里插入图片描述
创建listening后的结构如图:
在这里插入图片描述在整个过程中,会有ngx_addr_t(addr)、ngx_http_conf_addr_t(addr)、ngx_http_in_addr_t(addr)三种类型的addr、分别在listen命令解析(ngx_parse_url)、添加port到ports数组、创建listening三个流程节点中使用。后一个addr通常需要前一个addr复制,需注意区分。

四、绑定地址与开启监听
在ngx_init_cycle()方法中,完成ngx_conf_parse()之后,会先将旧的cycle中的listening数组中的元素中可继承的部分拷贝到新的cycle的listening中,这部分操作主要是为了热重启平滑过渡,防止用户连接丢失用的,直接启动的Nginx旧的cycle中是没有listening数组元素的。这里还涉及到main()方法中调用ngx_add_inherited_sockets()获取对应已经存在sockets连接的文件描述符。平滑热重启后面有时间再研究,这里暂时不解读这方面的内容。
在这里插入图片描述
在这里插入图片描述
最后,通过ngx_open_listening_sockets()遍历cycle中listening数组的每一个元素调用ngx_socket()生成一个socket并占用一个文件描述符,调用系统函数bind()绑定ip:port,并通过调用系统函数listen()开启监听。此时通过netstat -anp|grep nginx可以查看到开启的监听:在这里插入图片描述
另外可查看对应的文件描述符:在这里插入图片描述

8081端口有ipv4和ipv6两种监听,同时,8081ipv4的addr中,原本还有127.0.0.1的,但是有通配配置的存在,只剩通配形式的监听,这些都符合第三章中的原理解读。

除此之外,通过ngx_configure_listening_sockets()完成socket 接收缓存、发送缓存、Keepalive等socketopt的设置。sockopt的设置可参考setsockopt()函数使用详解

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NGINX源码之:listen和server_name命令与listening监听创建 的相关文章

随机推荐

  • 基于springboot+vue的网上商城管理系统,附源码+数据库+lw文档+PPT,适合课程设计、毕业设计

    1 项目介绍 在Internet高速发展的今天 我们生活的各个领域都涉及到计算机的应用 其中包括网上图书商城的网络应用 在外国网上图书商城已经是很普遍的方式 不过国内的管理网站可能还处于起步阶段 网上图书商城具有网上图书信息管理功能的选择
  • Visual Studio在Release模式下开启debug调试,编译器提示变量已被优化掉,因而不可用

    系列文章目录 文章目录 系列文章目录 前言 一 解决办法 1 修改工程属性 参考 前言 我们在编写代码的时候 如果用到别人的库 而别人只提供了release版本 所有我们也只能生成release版本的工程 但是 我们又想调试代码 如果我们直
  • vue3 naiveui 自定义v-loading指令

    1 在sr目录下创建loading文件夹 包含index ts和index vue 2 index ts import render VNode createVNode from vue import Loading from index
  • 【Java基础知识 12】java枚举详解

    Java学习路线 搬砖工逆袭Java架构师 简介 Java领域优质创作者 CSDN哪吒公众号作者 Java架构师奋斗者 扫描主页左侧二维码 加入群聊 一起学习 一起进步 欢迎点赞 收藏 留言 目录 一 基本概念 二 枚举的优缺点 1 优点
  • focal loss的几种实现版本(Keras/Tensorflow)

    起源于在工作中使用focal loss遇到的一个bug 我仔细的学习多个靠谱的focal loss讲解及实现版本 通过测试 我发现了这样一个奇怪的现象 几乎每个版本的focal loss实现对同样的输入计算出的loss都是不同的 通过仔细的
  • 吃透Kafka底层通信机制后,我把系统网络性能提升了10倍以上!

    V xin ruyuanhadeng获得600 页原创精品文章汇总PDF 目录 1 客户端与服务端的交互 2 频繁网络通信带来的性能低下问题 3 batch机制 多条消息打包成一个batch 4 request机制 多个batch打包成一个
  • 使用遗传算法解决旅行商问题

    遗传算法 Genetic Algorithm GA 最早是由美国的 John holland于20世纪70年代提出 该算法是根据大自然中生物体进化规律而设计提出的 是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型 是一种
  • Install and Configure JRebel for MyEclipse

    http www zeroturnaround com jrebel using jrebel with myeclipse utm source jrebelDLpage utm medium idepluginlink utm camp
  • Zabbix 邮件告警

    一 登录邮箱 这里使用126邮箱 http mail 126 com 二 开启POP3的授权码 三 Zabbix服务器与邮箱服务器的连通性测试 root zabbix server nc smtp 126 com t 25 220 126
  • chatgpt赋能python:Python长度转换程序:方便快捷的单位转换工具

    Python长度转换程序 方便快捷的单位转换工具 如果你曾经需要将英寸转换为厘米 或是想知道你的身高在米制和英制中是多少 那么你一定知道这是一个烦人的任务 为了解决这个问题 我们创建了基于Python的长度转换程序 能够帮助你轻松转换任何单
  • wsl2安装及相关编程环境配置

    wsl2的安装及相关环境配置 1 设置 gt 更新和安全 gt 开发者选项 gt 开发人员模式 2 设置 gt 应用 gt 应用和功能 gt 程序和功能 gt 程序和功能 gt 启用或关闭windows功能 gt 适用于linux的wind
  • 编程训练————岛屿数量(C++)

    岛屿数量 题目描述 主要思想 深度优先搜索 广度优先搜索 代码实现 深度优先搜索 广度优先搜索 题目描述 给你一个由 1 陆地 和 0 水 组成的的二维网格 请你计算网格中岛屿的数量 岛屿总是被水包围 并且每座岛屿只能由水平方向或竖直方向上
  • 如何升级numpy的版本

    嗯 如何升级numpy的版本 这是个很火的问题 解决方案如下 在命令下输入pip install U numpy 就可以升级numpy包了 pip install upgrade numpy 这样也可以
  • 统计二叉树中度为1的节点,层序遍历实现

    include
  • 分布式高可靠:负载均衡

    分布式高可靠 负载均衡 前言 什么是负载均衡 服务请求的负载均衡方法 轮询策略 顺序轮询 加权轮询 随机策略 哈希和一致性哈希策略 对比分析 知识扩展 如果要考虑请求所需资源不同的话 应该如何设计负载均衡策略呢 总结 前言 分布式可靠性相关
  • chrome浏览器安装右键翻译插件

    平常打开网页查看相关文章的时候 遇到一些不会的英文单词 可能第一反应是复制英文单词到百度翻译里面 下面为介绍一种直接右键选中英文单词 实现在线翻译的插件 这边用到的是 划词翻译 插件 安装步骤如下 第一步 下载扩展程序插件 链接 https
  • 深入JVM - 实例详解invoke相关操作码

    Java虚拟机规范中有一个章节专门列出了操作码助记符 对应的链接为 Java Virtual Machine Specification Chapter 7 Opcode Mnemonics by Opcode 其中 方法调用相关的操作码为
  • 毕业设计 基于Arduino的肺活量计

    0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩的要求 这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求 为了大家能够顺利以及最少的精力通过毕设 学长分享优质毕业设计项
  • 编程语言Java与c#的区别浅谈

    Java和c 都是编程的语言 它们是两个不同方向的两种语言 它们到底有什么区别呢 现在我给大家介绍一下 首先 我给大家说说他们的相同点吧 它们都是面向对象的语言 也就是说 它们都能够实现面向对象的思想 封装 继承 多态 下面给大家介绍一下它
  • NGINX源码之:listen和server_name命令与listening监听创建

    在http块的server块解析中 通过解析listen和server name命令配置 完成端口监听的初始化 虚拟主机配置关联 实现从host port到虚拟主机的映射关系 在进入解析源码之前 先来看看server块集中配置 server