从零手写实现 nginx-13-nginx.conf 配置例子解释 + nginx 配置文件要如何解析?

前言

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

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

github.com/houbb/nginx...

如果你想知道 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 的例子

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;
        }
    }

}

自己解析

思路

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

伪代码

java 复制代码
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;
    }
}

实际效果

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

ini 复制代码
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

优缺点

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

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

三方库解析

第二种是利用三方库。

比如 github.com/odiszapc/ng...

Nginx配置Java解析器

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

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

maven 依赖

xml 复制代码
<dependency>
    <groupId>com.github.odiszapc</groupId>
    <artifactId>nginxparser</artifactId>
    <version>0.9.3</version>
</dependency>

解析例子

java 复制代码
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);
        }
    }

}

测试日志

lua 复制代码
/var/run/nginx.pid
1024
80
server---80
server---443 ssl

转储器

java 复制代码
NgxConfig conf = NgxConfig.read("/etc/nginx/nginx.conf");
// ...
NgxDumper dumper = new NgxDumper(conf);
return dumper.dump(System.out);

自定义的解析类

思路

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

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

效果

lua 复制代码
/var/run/nginx.pid
1024
80
server---80
server---443 ssl

小结

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

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

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

开源地址

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

github.com/houbb/nginx...

相关推荐
xcl09256 小时前
北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南
java·spring boot·架构
一 乐7 小时前
动漫书销售商城|基于springboot + vue动漫书销售商城(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
卓怡学长8 小时前
w214基于jsp知道特产网
java·intellij-idea
步行cgn8 小时前
Spring 注解使用详解
java·spring
一条小小yu8 小时前
Spring IoC的理解
java·后端·spring
落魄实习生8 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
旺仔学长 哈哈9 小时前
springboot钓鱼爱好者交流平台APP设计与实现
java·spring boot·mysql·充电桩管理系统
自强的小白10 小时前
核心功能(Service接口)
java·mybatis
乌暮11 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习