从 PHP Docker 容器快速访问 PHP 会话文件后,GlusterFS 卷停顿/阻塞

从 PHP Docker 容器快速访问 PHP 会话文件后,GlusterFS 卷停顿/阻塞

2021-10-05 经过更多分析后更新了问题和文本,精简到最少的案例

简短的介绍

Nomad / Consul 集群正在运行,Traefik(最低配置)作为每个 Nomad 客户端上的系统任务。目前有 3 个 nomad 服务器、3 个 consul 服务器、3 个 nomad 客户端和 3 个 Gluster 服务器。设置与此非常相似关于设置 Nomad / Consul 集群的文章

基本图像和网站运行良好。

问题

我已经开始将第一个更大的基于 PHP 的站点(站点上有大量页面依赖加载)移植到这个集群,并且遇到了一个奇怪的问题,我已经确定了,但无法正确解决。

任务加载良好,并在 Consul、Traefik 和 Nomad 中注册为已启动。小型页面(依赖关系较少)运行良好。

每当页面有太多依赖加载时,Apache 就会暂停那些特定的连接。

当我打开一个新的隐身浏览器窗口并转到 URL 时,主页和大约 10-15 个依赖项都会加载。其他依赖项在浏览器中处于待处理状态。浏览器状态保持“旋转”(如加载中)。关闭窗口并打开一个新窗口允许我重复该过程。

我已经将问题归结为 PHP 会话目录(通过 Docker)映射到 GlusterFS 挂载上的目录。

将卷映射移动到基于同一服务器托管的其他目录可以消除该问题,并且站点可以正常加载。

结论:Docker 卷和 Gluster 安装之间的交互在“重负载”下会导致问题。只需几个请求,一切就都正常。当有大量请求访问 PHP 会话文件时,事情就会停滞并且无法恢复。

问题:这可能是由于 Gluster 配置问题或挂载配置方式造成的/etc/fstab。请帮助修复此问题!

隔离

PHP 会话目录设置为/var/php_session在图像 PHP 配置中,并在 Nomad / Docker 中映射到/数据/存储/测试/php_sessions

/数据/存储/测试/php_sessions目录由用户 20000 拥有,以确保所有节点都可以访问相同的 PHP 会话:

client:/data/storage/test$ ls -ln .
drwxr-xr-x  2 20000 20000     6 Oct  5 14:53 php_sessions
drwxr-xr-x  2 20000 20000     6 Oct  5 14:53 upload

当改变游牧卷映射时(在/etc/nomad/nomad.hcl) 从:

client {

  host_volume "test-sessions" {
    path      = "/data/storage/test/php_sessions"
    read_only = false
  }

}

client {

  host_volume "test-sessions" {
    path      = "/tmp/php_sessions"
    read_only = false
  }

}

(并确保/tmp/php_sessions也归用户 20000 所有)

一切恢复正常。

详细数据(更多数据请咨询)

内容/etc/fstab

LABEL=cloudimg-rootfs   /    ext4   defaults    0 1
LABEL=UEFI  /boot/efi   vfat    defaults    0 1
gluster-01,gluster-02,gluster-03:/storage       /data/storage   glusterfs   _netdev,defaults,direct-io-mode=disable,rw

站点镜像的 Dockerfile:

FROM php:7.4.1-apache
ENV APACHE_DOCUMENT_ROOT /var/www/htdocs
WORKDIR /var/www

RUN docker-php-ext-install mysqli pdo_mysql

# Make Apache root configurable
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

# Listen on  port 1080 by default for non-root user
RUN sed -ri 's/Listen 80/Listen 1080/g' /etc/apache2/ports.conf
RUN sed -ri 's/:80/:1080/g' /etc/apache2/sites-enabled/*

# Use own config
COPY data/000-default.conf /etc/apache2/sites-enabled/

# Enable Production ini
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini

RUN a2enmod rewrite && a2enmod remoteip

COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
COPY --chown=www-data:www-data . /var/www

RUN /usr/local/bin/composer --no-cache --no-ansi --no-interaction install

# Finally add security changes
COPY data/changes.ini /usr/local/etc/php/conf.d/

Nomad 文件被精简为触发问题的因素:使用以下 Nomad 工作计划:

job "test" {
  datacenters = ["dc1"]

  group "test-staging" {
    count = 1

    network {
      port "php_http" {
        to = 1080
      }
    }

    volume "test-sessions" {
      type      = "host"
      read_only = false
      source    = "test-sessions"
    }

    volume "test-upload" {
      type      = "host"
      read_only = false
      source    = "test-upload"
    }

    service {
      name = "test-staging"
      port = "php_http"

      tags = [
        "traefik.enable=true",
        "traefik.http.routers.test.php_staging.rule=Host(`staging.xxxxxx.com`)",
      ]

      check {
        type     = "tcp"
        port     = "php_http"
        interval = "5s"
        timeout  = "2s"
      }
    }

    task "test" {
      driver = "docker"
      user = "20000"

      config {
        image = "docker-repo:5000/test/test:latest"
        ports = ["php_http"]
      }

      volume_mount {
        volume      = "test-sessions"
        destination = "/var/php_sessions"
        read_only   = false
      }

      volume_mount {
        volume      = "test-upload"
        destination = "/var/upload"
        read_only   = false
      }

      template {
        data = <<EOF
1.2.3.4
EOF

        destination = "local/trusted-proxies.lst"
      }
    }
  }
}

相关内容