美文网首页
从零手写实现 nginx-13-nginx.conf 配置例子解

从零手写实现 nginx-13-nginx.conf 配置例子解

作者: 老马啸西风2020 | 来源:发表于2024-06-08 18:56 被阅读0次

    前言

    大家好,我是老马。很高兴遇到你。

    我们为 java 开发者实现了 java 版本的 nginx

    https://github.com/houbb/nginx4j

    如果你想知道 servlet 如何处理的,可以参考我的另一个项目:

    手写从零实现简易版 tomcat minicat

    手写 nginx 系列

    如果你对 nginx 原理感兴趣,可以阅读:

    从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?

    从零手写实现 nginx-02-nginx 的核心能力

    从零手写实现 nginx-03-nginx 基于 Netty 实现

    从零手写实现 nginx-04-基于 netty http 出入参优化处理

    从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)

    从零手写实现 nginx-06-文件夹自动索引

    从零手写实现 nginx-07-大文件下载

    从零手写实现 nginx-08-范围查询

    从零手写实现 nginx-09-文件压缩

    从零手写实现 nginx-10-sendfile 零拷贝

    从零手写实现 nginx-11-file+range 合并

    从零手写实现 nginx-12-keep-alive 连接复用

    从零手写实现 nginx-13-nginx.conf 配置文件介绍

    从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?

    从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?

    从零手写实现 nginx-16-nginx 支持配置多个 server

    从零手写实现 nginx-17-nginx 默认配置优化

    从零手写实现 nginx-18-nginx 请求头+响应头操作

    从零手写实现 nginx-19-nginx cors

    一个 nginx.conf 的例子

    # nginx.conf
    
    # 定义运行Nginx的用户和组
    user nginx;
    
    # 主进程的PID文件存放位置
    pid /var/run/nginx.pid;
    
    # 事件模块配置
    events {
        worker_connections 1024;  # 每个工作进程的最大连接数
    }
    
    # HTTP模块配置
    http {
        include /etc/nginx/mime.types;  # MIME类型配置文件
        default_type application/octet-stream;  # 默认的MIME类型
    
        # 访问日志配置
        access_log /var/log/nginx/access.log;  # 访问日志文件路径
        # 错误日志配置
        error_log /var/log/nginx/error.log;  # 错误日志文件路径
    
        # 文件传输设置
        sendfile on;  # 开启高效文件传输
        tcp_nopush on;  # 防止网络拥塞
    
        # Keepalive超时设置
        keepalive_timeout 65;
    
        # 定义服务器块
        server {
            listen 80;  # 监听80端口
            server_name example.com;  # 服务器域名
    
            # 静态文件的根目录
            root /usr/share/nginx/html;  # 静态文件存放的根目录
            index index.html index.htm;  # 默认首页
    
            # 定义location块,处理对根目录的请求
            location / {
                try_files $uri $uri/ =404;  # 尝试提供请求的文件,如果不存在则404
            }
        }
    
        server {
            listen 443 ssl;
            server_name  secure-example.com;
    
            ssl_certificate     /etc/nginx/ssl/secure-example.com.crt;
            ssl_certificate_key /etc/nginx/ssl/secure-example.com.key;
    
            location / {
                root   /var/www/secure-example.com;
                index  index.html index.htm;
            }
        }
    
    }
    

    自己解析

    思路

    我们可以自己写一堆代码,然后解析这个配置文件。

    伪代码

    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class NginxConfigParser {
        public static void main(String[] args) {
            Map<String, String> configMap = parseNginxConfig("/path/to/nginx.conf");
            System.out.println("Nginx configuration settings:");
            for (Map.Entry<String, String> entry : configMap.entrySet()) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }
        }
    
        public static Map<String, String> parseNginxConfig(String filePath) {
            Map<String, String> configMap = new HashMap<>();
            try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
                String line;
                String currentBlock = "";
                Pattern pattern = Pattern.compile("^\\s*([^#\\s][^\\s]*)\\s*([^#]+)?");
                while ((line = reader.readLine()) != null) {
                    Matcher matcher = pattern.matcher(line);
                    if (matcher.find()) {
                        String directive = matcher.group(1);
                        String value = matcher.group(2);
                        if (value != null) {
                            value = value.trim();
                            if (value.endsWith(";")) {
                                value = value.substring(0, value.length() - 1).trim();
                            }
                        }
                        if (directive.equals("server")) {
                            currentBlock = "server";
                        } else if (directive.equals("location")) {
                            currentBlock = "location";
                        }
                        if (!directive.isEmpty()) {
                            configMap.put(currentBlock + "." + directive, value);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return configMap;
        }
    }
    

    实际效果

    上面的内容,如果用这个方法解析,实际上并不太准确。

    Nginx configuration settings:
    .events = {
    location.} = null
    server.listen = 80
    .error_log = /var/log/nginx/error.log
    server.server = {
    location.try_files = $uri $uri/ =404
    .include = /etc/nginx/mime.types
    .keepalive_timeout = 65
    .user = nginx
    .tcp_nopush = on
    .pid = /var/run/nginx.pid
    server.server_name = example.com
    .} = null
    .http = {
    .default_type = application/octet-stream
    .worker_connections = 1024
    location.location = / {
    server.root = /usr/share/nginx/html
    server.index = index.html index.htm
    .access_log = /var/log/nginx/access.log
    .sendfile = on
    

    优缺点

    自己实现,可控性相对比较强。

    但是缺点是比较麻烦,可能还会引入一堆问题。

    三方库解析

    第二种是利用三方库。

    比如 https://github.com/odiszapc/nginx-java-parser

    Nginx配置Java解析器

    这个库帮助分析Nginx Web服务器配置文件,查找指定的参数、块、正则表达式或注释。

    然后AST可以被修改并转换回纯文本文件。

    maven 依赖

    <dependency>
        <groupId>com.github.odiszapc</groupId>
        <artifactId>nginxparser</artifactId>
        <version>0.9.3</version>
    </dependency>
    

    解析例子

    package com.github.houbb.nginx4j.config;
    
    import com.github.odiszapc.nginxparser.NgxBlock;
    import com.github.odiszapc.nginxparser.NgxConfig;
    import com.github.odiszapc.nginxparser.NgxEntry;
    import com.github.odiszapc.nginxparser.NgxParam;
    
    import java.io.IOException;
    import java.util.List;
    
    public class NginxConfigParserTest {
    
        public static void main(String[] args) throws IOException {
            NgxConfig conf = NgxConfig.read("D:\\github\\nginx4j\\src\\test\\resources\\nginx-demo.conf");
    
            // 基本信息
            NgxParam pidParam = conf.findParam("pid");
            System.out.println(pidParam.getValue());;
    
            NgxParam worker_connectionsParam = conf.findParam("events", "worker_connections");
            System.out.println(worker_connectionsParam.getValue());
    
            // 模块下多级
            NgxParam listen = conf.findParam("http", "server", "listen"); // 示例2
            System.out.println(listen.getValue()); // "8889"
    
            // 首先获取 block
            List<NgxEntry> servers = conf.findAll(NgxConfig.BLOCK, "http", "server"); // 示例3
            for (NgxEntry entry : servers) {
                NgxBlock ngxBlock = (NgxBlock) entry;
                String name = ngxBlock.getName();
    
                // value
                String value = ngxBlock.findParam("listen").getValue(); // 第一次迭代返回"on",第二次迭代返回"off"
                System.out.println(name + "---" + value);
            }
        }
    
    }
    

    测试日志

    /var/run/nginx.pid
    1024
    80
    server---80
    server---443 ssl
    

    转储器

    NgxConfig conf = NgxConfig.read("/etc/nginx/nginx.conf");
    // ...
    NgxDumper dumper = new NgxDumper(conf);
    return dumper.dump(System.out);
    

    自定义的解析类

    思路

    我们首先进行一层封装,方便后续的接口替换。

    目前底层使用 nginxparser 来统一实现。

    效果

    /var/run/nginx.pid
    1024
    80
    server---80
    server---443 ssl
    

    小结

    本文介绍了 nginx 配置文件的例子,和自己解析的思路。

    不过还是推荐使用三方标准库来处理,这样很多情况解决的比较充分。

    我是老马,期待与你的下次重逢。

    开源地址

    为了便于大家学习,已经将 nginx 开源

    https://github.com/houbb/nginx4j

    相关文章

      网友评论

          本文标题:从零手写实现 nginx-13-nginx.conf 配置例子解

          本文链接:https://www.haomeiwen.com/subject/qczvqjtx.html