我正在一个 docker 容器上运行一个 php 应用程序。当我连接到本地数据库时,响应非常快(< 1 秒)。当我连接到外部数据库(在谷歌云或亚马逊 AWS 上运行)时,性能真的很慢(> 35 秒)。
我已尝试使用我找到的几个链接中描述的 Google 的 DNS,但没有运气。我的 DNS 解析在 docker 容器内非常快,我直接使用 IP 地址连接到 Google Cloud SQL DB。
我已查看此链接 web server running inside a docker container running inside an EC2 instance responses very slowly这个Docker slow non-local database access .这似乎是相关的,但不确定。
我认为这是一个 Docker 问题,或者与容器有点相关,因为在其他应用程序上使用相同的远程 db(在 google cloud 和 aws 上)并且速度非常快。在我看来,这与容器内的网络有关。
所以,总结一下我用来测试的场景(数据库内容完全相同):
1) 在我的 Mac 上作为本地主机在 Docker 容器中运行我的应用程序:
- 我的本地主机 (MAMP) 上的数据库:非常快(< 1 秒);
- Google Cloud SQL 上的数据库:非常慢(> 35 秒);
- Amazon RDS 上的数据库:非常慢(> 35 秒);
2) 在 Google Compute Engine 上,我的应用在 Docker 容器中运行:
- Google Cloud SQL 上的数据库:非常慢(> 35 秒);
- Amazon RDS 上的数据库:非常慢(> 35 秒);
3) 在自定义 Google 应用引擎 flex 环境中,我的应用在 Docker 中运行:
- Google Cloud SQL 上的数据库:非常慢(> 35 秒);
- Amazon RDS 上的数据库:非常慢(> 35 秒);
4) 在 PHP Google 应用引擎 flex 环境中:
- Google Cloud SQL 上的数据库:非常慢(> 35 秒);
- Amazon RDS 上的数据库:非常慢(> 35 秒);
5) 我的应用在 Google Compute Engine 实例(PHP + apache)上的 Docker 之外运行:
- Google Cloud SQL 上的数据库:非常快(< 1 秒);
- Amazon RDS 上的数据库:非常快(< 1 秒);
6) 我的应用程序在本地主机 (Mac) 上的 Docker 之外运行:
- Google Cloud SQL 上的数据库:非常快(< 1 秒);
- Amazon RDS 上的数据库:非常快(< 1 秒);
- 我的本地主机 (MAMP) 上的数据库:非常快(< 1 秒);
有人知道解决或发现问题的方法吗?我知道这是一个可能很难解决的问题。所以,我的问题与我应该如何调试以找到问题更相关。
我的 Dockerfile:
FROM php:7.0.17-apache RUN apt-get update RUN apt-get install -y apt-utils curl vim RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli RUN docker-php-ext-install pdo pdo_mysql && docker-php-ext-enable pdo_mysql RUN pecl install xdebug # The base image does not have php.ini. # Copy our own, with xdebug settings ADD ./php.ini /usr/local/etc/php/ # Configure apache RUN a2enmod rewrite RUN a2dissite 000-default.conf # Copy sites available ADD ./www.metalar.net.conf /etc/apache2/sites-available/ # Copy Ports file ADD ./ports.conf /etc/apache2/ # Copy Ports file ADD ./apache2.conf /etc/apache2/apache2.conf # Copy error log ADD ./error.log /var/log/apache2/error.log # Make directory to host project files RUN mkdir -p /srv/www/www.metalar.net # Copy App to proper destination ADD . /srv/www/www.metalar.net # Enable config RUN a2ensite www.metalar.net.conf EXPOSE 8080
netstat -s
Ip: 187 total packets received 0 forwarded 0 incoming packets discarded 187 incoming packets delivered 163 requests sent out Icmp: 0 ICMP messages received 0 input ICMP message failed. ICMP input histogram: 0 ICMP messages sent 0 ICMP messages failed ICMP output histogram: Tcp: 2 active connections openings 0 passive connection openings 0 failed connection attempts 0 connection resets received 0 connections established 181 segments received 157 segments send out 0 segments retransmited 0 bad segments received. 0 resets sent Udp: 6 packets received 0 packets to unknown port received. 0 packet receive errors 6 packets sent UdpLite: TcpExt: 2 TCP sockets finished time wait in fast timer 171 packet headers predicted 4 acknowledgments not containing data payload received TCPRcvCoalesce: 82 TCPOrigDataSent: 4 IpExt: InOctets: 234466 OutOctets: 7205 InNoECTPkts: 187
最佳答案
首先你使用的是哪个版本的Docker?
因为前段时间我的 Docker 在 Mac 上运行时遇到了类似的问题,我发现 Docker for MAC 的一个已知问题也可能与您有关。
此问题已映射到以下问题。
他们提供了 workaround ,但现在应该足以更新 Docker 以解决性能不佳的问题。
但是,这些已知问题并不能解释行为 #2 和 #3,所以我猜它不相关,但值得我提及。
调试
关键是这不是服务器或应用程序的问题,因此我将专注于调试由于某种原因无法按预期工作的 Docker 的网络部分。
这些只是一般建议,但您可以找到更多信息,例如 here或在 Docker 论坛附近。
为了调试,我会打开两个终端,第一个终端我会通过 ssh 进入我的容器,与本地机器并行运行所有命令,以便比较结果。
我会检查来自容器的网络速度是否与存储在谷歌云存储和任何随机网站中的下载文件相似
Ping
MySql 实例并比较延迟。Traceroute
到 MySql 实例并检查数据包的路径和每一跳的延迟。尝试通过命令行连接MySql,并比较建立连接和执行基本操作(创建、更新、上传、删除、ecc)的时间。
通过
tcpdump
(仅来自容器)我会检查两个实例之间的流量,以查找任何类型或错误、连接重置、连接到 db 实例时的数据包畸形以及运行应用程序也尝试执行一些 DNS 查找并比较时间
检查
/var/log
下容器端中存在的任何类型的日志,以及您是否有权访问 MySql 实例日志尝试了解哪些操作在容器内实际上需要更长的时间执行(是否只是连接到服务器?是整个过程变慢了吗?是在大数据传输期间?)
我会尝试构建一个显示性能下降的基本示例,我会在 docker 对应的 GitHub repository 中打开一个问题.
如果您发现在 localhost 和容器中运行的命令之间存在任何差异,请更新问题以查看是否有人可以帮助您实际解决问题。
附: 您还可以找到 this有趣,基本上是一个人无法连接到 MySql 实例并成功调试它
关于连接到本地数据库时 Docker 容器运行速度很快,但在外部数据库上运行速度很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48238592/