双十一淘宝、京东服务器瘫痪大揭秘

本文回顾了2012年双十一期间淘宝与京东所遭遇的技术挑战,重点分析了服务器响应时间、可用性等问题,并提供了改进措施。

双十一淘宝、京东服务器瘫痪大揭秘


11月11日,各大电商风云大战,淘宝网和京东网为首的电商赚足了眼球。淘宝双十一网络瘫痪遭诟病,支付宝被”抢瘫”,好不容易进入支付过程,支付宝提示系统繁忙,经过反复尝试,花费用户很长时间实现支付。而京东当天流量暴涨,大量用户登录。结果京东商城的服务器被大流量冲垮,服务器也瘫痪。

AD

2012年11月11日,各大电商风云大战,淘宝网和京东网为首的电商赚足了眼球。淘宝双十一网络瘫痪遭诟病,支付宝被”抢瘫”,好不容易进入支付过程,支付宝提示系统繁忙,经过反复尝试,花费用户很长时间实现支付。而京东当天流量暴涨,大量用户登录。结果京东商城的服务器被大流量冲垮,服务器也瘫痪。

从这件事情可以看出电商们脆弱的服务器和网站后台系统。把钱过多的花在了门面工程上,在物流推广方面都做的相当不错。可惜在技术层面,在网站程序的开发,服务器的稳定问题上做的还非常不够。

云测宝APM性能监测平台对这两家商城网站做了一次11.11全天24小时性能监测,以下是从服务器的响应时间和可用性以及网络运营商进行综合对比分析。

1、响应时间对比

响应时间是从手机客户端发出请求(信息包层或交易层)至收到最后一个响应的时间就是整体的响应时间。网络,服务器和应用都对整体响应时间有影响。响应时间是重定向、域名解析、建立连接、发送请求、等待响应、接收数据这几个阶段的用时总和。

从图中可得出,京东商城响应时间逊色于淘宝网。京东商城下载内容时间为725.75ms,约是淘宝网的14倍。

而淘宝网总重定向时间为710.05ms,重定向是通过各种的方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。

总体来说:淘宝网好于京东商城,而京东商城主要原因是页面下载内容时间过长。网络,服务器和网站都有对整体响应时间有影响,商家应该根据自己的情况去判断找到问题根结。

2、可用性对比

服务器的可用性,其实就是要求服务器具有高可靠性和高稳定性。可用性也是反映应用、网站可用性情况的指标,其计算方法为:(总监测次数-监测故障次数) / 总监测次数。

常见的故障类型主要有DNS无法解析、连接超时、响应超时、重定向次数过多、服务器无响应。

图中淘宝可行性为97.7%,京东为97.18%,两者在可用性方面相当。

可用性统计图如下:

由图中可看到淘宝和京东商城故障类型主要是连接超时和响应超时。可以分别看到出现故障次数。

3、响应时间趋势对比和可用性趋势对比图

从图中可以看到在9:00-12:00以及18:30-24:00这个时间段京东商城比淘宝网响应时间长。而具体原因京东可以根据自己网站流量数据监测来分析到底是服务器不稳定的原因还是网站本身的原因。淘宝在下午15:00左右响应时间达到一天中的顶峰值,可能在这段时间用户访问量最大,导致服务器压力过大。

京东商城在早上10:00可用性达到一天的低峰,其可用性低于85%,而在下午13:00后可用性慢慢好转。反应在这时间段上服务器可靠性和稳定性极差。

导致此情况的原因有很多,很可能在这段时间用户访问量量暴涨,导致服务器瘫痪的问题。

4、区域响应时间对比和区域可用性对比

云测宝网络分布在全国各地城市。从图中我们可以看到手机客户端访问京东商城和淘宝在各个区域的响应时间对照图。上海的手机客户端访问淘宝网的响应时间最短,而京东是在湖南手机客户端访问速度最快。在内蒙古的手机用户访问二者商城都是最慢的,这可能跟商家服务区分布区域以及网络运营商等有关。

从图中可看出两家商城在可用性方面相当。严格来说淘宝要好于京东,但差距不明显。

总结:

以上从各个层面和维度监测并分析淘宝和京东两大电商在光棍节那天服务器瘫痪的具体数据分析和报告图展示。

电商一定要考虑好网站的发展问题,一旦发现网站的流量和用户增长了,就要立刻升级空间,或者将空间变成服务器。平时应该做好服务器和网站性能监测,随时对网站的用户增长进行预估,做好充分准备。当网站被突然暴涨的用户搞挂掉的时候可以有备用的网站使用,同时分析哪些服务器访问量,哪些服务器访问量低,做到资源合理分配利用。

以上来自云测宝专业报告。

非常感谢你的耐心反馈,我们来**彻底排查并解决“踢人后服务器瘫痪”这个核心问题**。 --- ## 🚨 问题定位:服务器踢人后无法继续处理新连接或消息 ### ❓问题本质分析: 我们已经做了以下处理: - 使用 `std::atomic<bool> serverRunning` 控制主线程踢人线程。 - 对 `accept()` 做了异常处理。 - 使用 `mutex` 保护客户端列表。 - 正确关闭 socket。 **但问题依旧存在,说明问题可能出在:** ### ✅ 问题根源分析: #### 1. **主线程中 `accept()` 依赖的 `serverSocket` 被意外关闭** - 在踢人操作中,如果误操作了 `serverSocket`,例如误传 socket 句柄或误关闭。 - 或者在踢人时未正确释放资源,导致后续 `accept()` 失败。 #### 2. **踢人操作中使用了 `erase` `break`,但未 `return`,导致线程继续执行后续代码** - `handleClient()` 函数中踢人后没有 `return`,导致继续执行 `recv()`,但 socket 已被关闭,程序卡死。 #### 3. **Windows 下 socket 资源未正确释放** - 某些情况下 socket 被关闭后未调用 `WSACleanup()` 或资源未释放,导致 `accept()` 卡死。 --- ## ✅ 修复方案 ### ✅ 1. **踢人后立即 `return`,避免继续执行 `recv()`** ```cpp if (isFlooding(*client)) { ... closesocket(client->socket); clients.erase(remove_if(...)); mtx.unlock(); return; // ✅ 必须 return,避免继续执行 recv() } ``` ### ✅ 2. **主线程中确保 `accept()` 持续运行,即使出错也继续循环** ```cpp while (serverRunning) { sockaddr_in clientAddr{}; int clientAddrLen = sizeof(clientAddr); SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientAddrLen); if (clientSocket == INVALID_SOCKET) { cout << "accept 失败,尝试重新监听..." << endl; continue; } thread(handleClient, clientSocket).detach(); } ``` ### ✅ 3. **确保踢人操作中不误操作 `serverSocket`** - 确保踢人时只操作客户端 socket,不要影响到 `serverSocket`。 - 不要 `closesocket(serverSocket)`。 --- ## ✅ 最终修复后的核心函数代码如下: ### ✅ `handleClient()` 函数修复: ```cpp void handleClient(SOCKET clientSocket) { char buffer[4096]; char username[128]; int bytesReceived = recv(clientSocket, username, sizeof(username) - 1, 0); if (bytesReceived <= 0) { cout << "接收用户名失败" << endl; closesocket(clientSocket); return; } username[bytesReceived] = '\0'; string ip = getClientIP(clientSocket); string joinMsg = "[" + ip + "] " + string(username) + " 进入了聊天室"; cout << joinMsg << endl; broadcastMessage(joinMsg); ClientInfo clientInfo; clientInfo.socket = clientSocket; clientInfo.ip = ip; clientInfo.username = string(username); clientInfo.lastMsgTime = time(nullptr); clientInfo.msgCount = 0; mtx.lock(); clients.push_back(clientInfo); mtx.unlock(); while (serverRunning) { bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0); if (bytesReceived <= 0) { string leaveMsg = "[" + ip + "] " + string(username) + " 离开了聊天室"; cout << leaveMsg << endl; broadcastMessage(leaveMsg); mtx.lock(); for (auto it = clients.begin(); it != clients.end(); ++it) { if (it->socket == clientSocket) { clients.erase(it); break; } } mtx.unlock(); closesocket(clientSocket); return; } buffer[bytesReceived] = '\0'; string rawMessage(buffer); mtx.lock(); ClientInfo* client = nullptr; for (auto& c : clients) { if (c.socket == clientSocket) { client = &c; break; } } if (!client) { mtx.unlock(); continue; } if (isFlooding(*client)) { string floodMsg = "[系统] 用户 " + client->username + " 因刷屏被踢出聊天室"; string clientFloodMsg = "[系统] 您因刷屏被踢出聊天室"; cout << floodMsg << endl; broadcastMessage(floodMsg); sendMessage(client->socket, clientFloodMsg); closesocket(client->socket); clients.erase(remove_if(clients.begin(), clients.end(), [&](const ClientInfo& c) { return c.socket == clientSocket; }), clients.end()); mtx.unlock(); return; // ✅ 关键:踢人后立即 return,避免继续 recv() } mtx.unlock(); string message = "[" + ip + "] " + string(username) + " : "; if (containsSensitiveWord(rawMessage)) { message += "[屏蔽消息]"; } else { message += rawMessage; } cout << message << endl; broadcastMessage(message); } } ``` --- ### ✅ 主线程修复: ```cpp while (serverRunning) { sockaddr_in clientAddr{}; int clientAddrLen = sizeof(clientAddr); SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientAddrLen); if (clientSocket == INVALID_SOCKET) { cout << "accept 失败,尝试重新监听..." << endl; continue; } thread(handleClient, clientSocket).detach(); } ``` --- ## ✅ 总结修复内容: | 修复点 | 描述 | |--------|------| | ✅ 踢人后立即 `return` | 避免继续执行 `recv()`,防止崩溃 | | ✅ 主线程持续监听 | `accept()` 出错后继续运行,保证新连接 | | ✅ socket 资源正确释放 | 不影响 `serverSocket`,保证主线程正常 | | ✅ 线程安全 | 使用 `std::atomic<bool>` `mutex` 保证多线程安全 | --- ## ✅ 建议后续测试方法: 1. 多客户端连接,发送消息。 2. 手动 `/kick` 某个用户。 3. 查看服务器是否仍能接收新客户端连接。 4. 查看踢人后服务器是否仍能接收消息。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值