当前位置:首页 > 休闲

多个网站无法同时运行的常见原因

服务器上跑着三个网站,多个的常突然只有第一个能打开,网站无法另外两个要么超时,运行因要么直接返回502。见原这种事我遇到过不止一次。多个的常最离谱的网站无法一回,某台测试机上的运行因WordPress、一个Node.js API和一个静态文档站同时挂了,见原排查了半天才发现是多个的常Nginx的`worker_connections`设成了默认的512,而三个站点的网站无法并发请求加起来直接把它撑爆了。

端口冲突是运行因最常见的原因,没有之一。见原很多人部署第二个网站时,多个的常习惯性照抄第一个的网站无法配置,Nginx监听80,运行因Apache也监听80,Tomcat默认8080,另一个Spring Boot应用还是8080。系统只允许一个进程绑定同一个端口,后来的那个要么启动失败,要么把前面的挤掉。Windows上更隐蔽——IIS占着80,你装个Apache,它不报错,但就是不起作用,因为HTTP.sys已经把流量截走了。

资源隔离没做好是另一个大坑。我见过一台4GB内存的VPS上跑了五个PHP站点,每个站点的php-fpm进程池都设了`pm.max_children = 50`。结果流量稍微一上来,内存直接耗尽,OOM Killer随机杀进程,五个站点轮流挂。你单独访问每个站都正常,同时访问就崩,因为内存根本不够分。CPU也一样,一个站点跑个死循环或者大量计算,其他站点跟着卡成幻灯片。

数据库连接池的问题经常被忽略。三个网站共用一个MySQL实例,每个站点的连接池上限都是100。MySQL默认`max_connections`是151,三个站点同时稍微有点负载,连接数瞬间打满,第四个请求直接报“Too many connections”。更麻烦的是,有些框架连接池不释放空闲连接,跑一晚上,连接数只增不减,第二天早上所有站点一起挂。

配置文件互相覆盖这种事,在共享环境里太常见了。比如两个站点都用`.htaccess`,一个写了`RewriteRule`把所有请求重写到`index.php`,另一个站点放在子目录里,结果它的静态资源请求也被第一个站点的规则拦截了。Nginx的`server_name`配错也会导致问题——两个`server`块都写了`listen 80 default_server`,Nginx启动时直接报冲突,或者请求全被第一个`server`块吃掉。

SSL证书和SNI算是个隐蔽陷阱。老版本的客户端或者某些HTTP库不支持SNI,当你在同一个IP上配了多个HTTPS站点,没有SNI的客户端只会拿到默认站点的证书。浏览器现在基本都支持,但如果你用`curl`或者Java的`HttpURLConnection`去测,就会遇到证书不匹配的报错,看起来像是“站点无法访问”,其实是握手阶段就失败了。

还有文件锁和会话共享的问题。两个PHP站点共用同一个`session.save_path`,一个站点写了`session_write_close`,另一个站点的会话数据就被覆盖了。日志文件也是,两个进程同时写同一个`error.log`,没有加锁的话,日志内容会交错混乱,严重时甚至导致进程阻塞。

排查这类问题,我的习惯是先看端口占用:`ss -tlnp`或者`netstat -ano`,确认没有重复绑定。然后看资源:`free -m`、`top`、`iostat`,确认内存和CPU没被某个站点吃光。接着查数据库连接数:`SHOW STATUS LIKE 'Threads_connected'`。最后看Web服务器的错误日志和访问日志,通常会有“connection refused”、“upstream timed out”或者“no live upstreams”这类关键词。

说到底,多个网站同时运行不是简单地把配置文件复制粘贴就完事。端口、内存、连接数、文件句柄、SSL上下文,这些资源都是有限的,也是共享的。一个站点出问题,很容易把其他站点拖下水。部署之前算一下资源账,比事后救火省事得多。

分享到: