Django与Flask混合架构:孕婴知识电商平台实战与踩坑全记录
去年我帮一个母婴内容团队搭了一套知识科普商城一体化的孕婴护理平台项目本身不复杂但在实际开发中踩了一堆意料之外的坑。今天把整个项目的设计思路、技术选型、核心实现和问题排查整理出来希望能给正在做同类型平台、或者纠结Django和Flask怎么配合使用的朋友一些参考。这个项目定位很明确面向准妈妈和新手父母提供分孕周的护理科普内容同时打通母婴商品购买链路。前100字可以提炼成一句话——它解决的是看科普和买东西割裂的问题。用户看完一篇产检注意事项顺手就能买到对应的孕期用品而不需要跳出去重新搜索、识别质量、担心买错。技术层面用了Python生态主体业务基于Django轻量级推荐与推送服务基于Flask前后端数据联动用WebSocket实现实时通知。适合谁参考两类人。一类是学生或刚入职场的开发者想完整走一遍从需求分析到技术选型再到部署上线的Web开发全流程另一类是想做垂直细分电商、但不想从零造轮子的小团队。这篇会把关键模块的建模思路、代码片段、配置细节和踩坑实录都摊开讲清楚可以直接照着改自己的业务。1. 项目整体设计与技术选型思路1.1 需求拆解科普和商城两个命题怎么捏在一起孕婴护理平台和普通电商最大的不同在于用户决策链条里多了一个知识信任环节。买一箱牛奶用户不会先看三篇论文但买一个婴儿推车、选一款胎教仪新手父母真的会花大量时间查资料、对比参数、看评测。所以这个平台的核心并不是卖货而是先建立专业信任再承接消费需求。需求拆出来其实有两条主线内容线科普文章、护理课程、问答内容具备典型的CMS属性。文章要有分类、标签、作者、审核状态、发布时间、阅读量还要按孕周维度做内容组织比如备孕期、孕早期、孕中期、孕晚期、产后恢复五个阶段。交易线商品、SKU库存、购物车、订单、支付回调、物流信息具备典型的电商属性。用户购买前往往需要参考科普内容购买后可能又会触发对下一阶段知识的需求。两条线不是平行关系而是一种闭环内容引导认知认知驱动购买购买后的使用反馈又沉淀成新的内容素材。我在设计数据模型时就刻意让文章和商品通过标签体系关联起来每一篇文章详情页右侧可以展示相关好物每个商品详情页上方可以推荐相关科普。这个设计后来实测下来的转化率表现不错因为在孕婴场景下用户本身就有先搞清楚再买的心理预期顺着内容流向商品是阻力最小的路径。技术层面为什么最后选了Django做主体、Flask做辅助服务的混合架构而不是只用其中一个这是有明确边界的不是炫技。Django自带ORM、Admin后台、表单处理、用户认证、权限框架做内容管理、订单系统、会员体系这类规范明确、表单密集的活非常高效几乎不用自己写底层代码。而Flask轻量灵活适合做独立的推荐服务、消息推送网关这类单一职责、要快速迭代的模块。两个框架之间通过HTTP接口通信互不干扰部署时也可以分开扩容。1.2 Django和Flask的分工边界谁是主体谁是辅助先聊一个很多初学者纠结的问题Django和Flask到底选哪个我的答案取决于项目的表单密度和模块耦合度。孕婴商城这种项目用户注册、收货地址、订单备注、商品评论、文章投稿几乎每个功能都离不开表单和数据库交互Django的ModelForm、Admin、ORM能省掉大量重复劳动。而且Django自带的安全机制CSRF防护、XSS过滤、SQL注入防护对刚上线的电商项目是刚需自己用Flask手写这些很容易漏。但Flask在这个项目里也不是摆设它承担了三件事推荐服务基于孕周标签、商品标签、内容标签做轻量级个性化推荐算法代码放在独立的Flask进程中数据和主库共享但逻辑解耦方便单独优化和重启。消息推送网关对接WebSocket通道把后台产生的事件审核通过、库存预警、订单状态变更推送给在线前端。这部分如果用Django Channels也可以做但Django项目本身已经很重再挂一套异步层会让新手维护起来头疼拆给Flask反而清爽。数据采集接口接收前端埋点上报的浏览行为、停留时长、点击事件写入独立分析库不影响主业务数据库性能。当然也要说明这种Django Flask双框架架构并不是所有项目都适用。如果团队只有一个人且项目规模不大老老实实全用Django就够了否则两套代码、两套依赖、两套部署运维成本翻倍。我这个项目之所以拆是因为当时预估推送和推荐逻辑会频繁改动不希望每次改动都重新发版整个电商系统用Flask做独立服务可以单独迭代。用一个生活化的类比Django是精装交付的公寓水电、墙面、门窗都给你弄好了你只需要买家具搬进去Flask是毛坯房给你水泥、砖头和图纸装修方案完全自己定。住公寓省心但不好改结构装毛坯灵活但要自己处理很多基础问题。孕婴商城这种业务大部分功能是成熟的、规范的适合住公寓而推荐和推送这类变数大、需求不明确的部分更适合毛坯房自己装。1.3 实时推送为什么是孕婴平台的刚需而不是花架子看热搜词里有django websocket实现后台有数据前端推送这个需求在孕婴场景里太真实了。举几个具体例子用户提交一篇育儿笔记运营在后台点审核通过用户前台页面要立刻看到状态从审核中变成已发布而不是刷新好几次才看到。某款妊娠油库存只剩最后20件在线的用户要收到实时提醒该商品库存紧张制造紧迫感。用户关注的孕周内容有新文章发布前端要弹出轻提示推送。如果用传统的HTTP轮询每3秒请求一次接口在线用户多了以后对服务器压力不小而且通知实时性也差用户可能看到提示时已经过了10秒紧迫感大打折扣。WebSocket的好处是建立一条长连接服务器有数据变化时主动往客户端推省掉了大量无效请求实时性也提升到毫秒级。这里先埋一个伏笔具体实现细节放在第3章。节点在于Django本身是同步框架要跑WebSocket需要引入Channels这个异步层配置过程有一堆坑。最典型的是ASGI和WSGI两套配置的兼容问题处理不好会出现开发环境push正常生产环境一部署就断连的诡异现象。2. 核心功能模块设计与数据模型搭建2.1 科普内容模块文章不是文章是带着孕周标签的知识节点内容模块的建模我建议不要简单照搬通用博客系统。孕婴场景的内容天然带两个附加维度孕周阶段和内容可信度。孕周阶段决定内容推给谁。一篇孕中期胎动规律的文章推给产后妈妈看既浪费流量又伤害体验。所以我在模型设计里给文章加了一个stage字段可选值包括pre备孕、early孕早期、mid孕中期、late孕晚期、post产后和all通用。用户完善个人档案时填了当前孕周系统自动映射到对应stage推荐和首页内容就是按这个字段过滤的。内容可信度则体现在审核机制和作者体系上。普通用户可以在经验分享板块投稿但专家科普板块必须由入驻的医生、营养师或持证育儿顾问发布。这两类内容在数据库里用author_type字段区分展示时也会打上不同标签。用户搜索时系统默认优先展示专家内容确保优先级安全。Django模型核心设计如下# article/models.py from django.db import models from django.contrib.auth.models import User STAGE_CHOICES [ (pre, 备孕), (early, 孕早期), (mid, 孕中期), (late, 孕晚期), (post, 产后), (all, 通用), ] class Article(models.Model): title models.CharField(max_length200, verbose_name标题) stage models.CharField(max_length10, choicesSTAGE_CHOICES, defaultall) author models.ForeignKey(User, on_deletemodels.CASCADE) author_type models.CharField(max_length10, choices[ (expert, 专家), (user, 用户投稿), ], defaultuser) content_md models.TextField(verbose_nameMarkdown内容) cover_image models.ImageField(upload_tocovers/, blankTrue) status models.CharField(max_length10, choices[ (draft, 草稿), (pending, 待审核), (published, 已发布), (rejected, 已驳回), ], defaultdraft) view_count models.PositiveIntegerField(default0) created_at models.DateTimeField(auto_now_addTrue) updated_at models.DateTimeField(auto_nowTrue) class Meta: indexes [ models.Index(fields[stage, status]), models.Index(fields[created_at]), ]注意给stage和status建了联合索引因为首页列表、推荐列表的主要查询条件都是某个孕周已发布。上线后这个索引效果很明显100万数据量下查询时间从几百毫秒降到几十毫秒。后台运营编辑直接用Django Admin就能搞定。我重写了admin.py注册Article模型的时候配置了list_filter按stage和status筛选、search_fields按标题搜索、list_editable让运营可以直接在下拉框里改审核状态。这套配置半小时就能做出来比单独写一个后台管理页面省了至少三个工作日。2.2 商城模块商品、购物车、订单的状态流转商城模块是整个项目里最容易出隐藏bug的部分。表面上看是展示商品→加购物车→下单→支付→发货一条直线实际上每个环节背后都有状态机在约束。商品模型有几个关键字段要提前想清楚spu和sku的关系SPU是商品品类比如孕妇DHA藻油SKU是具体规格比如60粒装/90粒装。下单时锁定的库存是SKU级别的库存用户看到的也是SKU级别的价格。上下架状态包括草稿、上架中、下架、售罄这是一个独立字段不要用库存为0来表示下架否则商品列表查询SQL会变得很别扭。关联标签用于和科普内容打通比如某商品关联孕中期-补钙的标签内容详情页才能推送相关好物。购物车我用了Redis缓存key设计为cart_{user_id}value是JSON字符串存商品SPU、SKU、数量、加入时间。购物车不落数据库的好处是读写快、临时性清理方便用户未登录时也可以把购物车存在Cookie里登录后合并到Redis。这一步对转化率很关键因为很多孕婴用户是断断续续决策的今天收藏明天买购物车一旦丢失用户基本就流失了。订单部分最核心的是状态机。我在项目里定义了六种状态pending_payment待支付paid已支付shipping配送中completed已完成cancelled已取消refunding退款中每个状态之间的跳转是有严格条件的比如待支付只能跳转已支付或已取消已支付只能跳转配送中或退款中。我在代码里用了一个字典结构做状态迁移表跳转不合法直接抛异常ORDER_STATUS_FLOW { pending_payment: [paid, cancelled], paid: [shipping, refunding], shipping: [completed, refunding], completed: [refunding], refunding: [completed], cancelled: [], }库存扣减时机也有讲究。我采用的是下单锁定库存支付确认扣减方案。用户提交订单时先把SKU库存锁定锁库存数130分钟未支付自动解锁支付回调成功后正式扣减可售库存。这样做防止了超卖又不会因为用户卡在支付页就占着库存不放。支付对接的是微信支付和支付宝的官方接口。接入时最大的坑在回调验签回调URL要写在公网可访问的HTTPS地址上并且要校验回调参数的真实性不能凭从请求里拿到的金额和订单金额一致就直接改订单状态必须用官方SDK验签函数验证签名。这一步漏了用户伪造一个支付成功的回调订单就能白嫖。2.3 用户体系与RBAC权限控制孕婴平台的用户角色比普通电商要复杂不少。除了买家和卖家还有内容生产者和平台运营所以权限设计不能只靠is_staff一个布尔值硬撑要上RBAC基于角色的访问控制。我的角色划分如下普通用户浏览内容、购买商品、发布经验分享、维护宝宝档案科普作者发布专家文章、修改自己的文章、查看自己文章数据商家管理自己店铺的商品、处理自己店铺的订单、查看店铺营收数据运营审核文章、审核商品上下架、管理用户评论、查看全站数据看板超级管理员一切权限包括角色分配和系统配置Django本身有Group和Permission机制但默认的Permission是模型的增删改查级别的颗粒度不够细。比如修改自己的文章和修改别人的文章都要改Article模型但前者是合理的、后者是越权的。所以我在应用层加了一层封装自定义了两个通用权限# permission_ex.py def check_object_permission(user, obj): # 运营和超管拥有全部操作权限 if user.is_staff or user.is_superuser: return True # 普通作者只能操作自己创建的对象 if hasattr(obj, author) and obj.author user: return True return False在视图函数里统一调用这个校验函数不通过的返回403页面。后来发现这个方案比引入django-guardian这类第三方库更轻量代码也容易看懂。当然如果项目规模变大、权限规则变得极其复杂再考虑引入专门的权限框架也不迟。用户档案我还扩展了原生User模型加了一个Profile模型OneToOne关联存宝宝昵称、孕周阶段、预产期、收货偏好等信息。孕周阶段在用户首次完善档案后存入之后内容推荐、商城推荐都会以此为依据动态变化。3. 实操过程与核心环节实现3.1 开发环境准备与VSCode配置Python环境的搭建看起来简单实际也是新手翻车重灾区。我建议直接装Python 3.10以上版本用conda或venv建一个独立虚拟环境防止和系统Python打架。一个常见问题是macOS上自带Python2在终端敲python进的是旧版本代码却是用Python3写的运行时报一堆语法错误。解决办法是创建虚拟环境后用which python手动确认路径。VSCode配置Python开发环境有几个关键点装Python扩展在左下角选择解释器时一定要选中虚拟环境里的Python而不是全局的。.vscode/settings.json里手动指定设置比如python.defaultInterpreterPath。调试配置launch.jsonDjango的调试模式不需要自己拼命令直接用Python: Django模板会自动带上runserver参数。项目骨架我用了标准的Django工程结构django-admin startproject pregnancy_shop cd pregnancy_shop python manage.py startapp article python manage.py startapp mall python manage.py startapp user_center python manage.py startapp order python manage.py startapp notification每个app按业务域划分article管科普内容mall管商品和购物车user_center管用户档案order管订单notification管WebSocket推送。这种划分后续维护起来非常清晰避免了一个app里堆了十几个models文件的臃肿问题。3.2 WebSocket推送的完整实现后端数据发生变化时主动推送到前端WebSocket通道是这个项目技术含量最高的部分。Django默认是同步框架跑WebSocket需要引入Channels原理是额外启动一个ASGI服务器来处理长连接。具体实现分四步第一步安装django-channels并把它加入INSTALLED_APPS。第二步在项目根目录建asgi.py配置ASGI路由# asgi.py import os import django from channels.routing import ProtocolTypeRouter, URLRouter from django.core.asgi import get_asgi_application os.environ.setdefault(DJANGO_SETTINGS_MODULE, pregnancy_shop.settings) django.setup() from notification.routing import websocket_urlpatterns application ProtocolTypeRouter({ http: get_asgi_application(), websocket: URLRouter(websocket_urlpatterns), })第三步在notification应用里定义Consumer。这里有个关键选择用异步Consumer还是同步Consumer。异步Consumer更高效但无法直接操作Django ORMORM是同步的需要用database_sync_to_async包装同步Consumer代码写起来顺手但长连接多了会占线程资源。我这个项目用的是异步Consumer加database_sync_to_async代码稍微绕一点但性能好# notification/consumers.py import json from channels.generic.websocket import AsyncWebsocketConsumer from asgiref.sync import database_sync_to_async class NotificationConsumer(AsyncWebsocketConsumer): async def connect(self): self.user self.scope[user] if self.user.is_authenticated: self.group_name fuser_{self.user.id} await self.channel_layer.group_add(self.group_name, self.channel_name) await self.accept() else: await self.close() async def disconnect(self, close_code): await self.channel_layer.group_discard(self.group_name, self.channel_name) async def send_notification(self, event): await self.send(text_datajson.dumps({ type: notification, message: event[message], timestamp: event[timestamp], }))第四步后台任何地方需要触发推送时直接调用channel_layerfrom channels.layers import get_channel_layer from asgiref.sync import async_to_sync channel_layer get_channel_layer() async_to_sync(channel_layer.group_send)( fuser_{user_id}, { type: send_notification, message: 您的文章已审核通过, timestamp: str(time.time()), }, )一点经验之谈Channels自带的内存channel_layer在单机开发没问题但生产环境如果跑了多个worker进程内存模式会丢消息必须换成Redis channel layer配置CHANNEL_LAYERS用channels_redis。这个坑我上线当天就踩了当时表现为用户A的推送时好时坏检查半天才发现是两个worker进程各自维护自己的内存缓存消息路由不到正确的进程上。3.3 Flask推荐服务与相似度匹配实现推荐服务用Flask独立实现跑在Another端口Django通过HTTP调用。推荐逻辑的核心是标签相似度计算。孕婴场景下的推荐可以简单理解给用户当前所处的孕周阶段找最相关的内容和商品。具体做法是把每篇文章、每个商品都打上多个标签然后计算用户标签向量与物品标签向量的相似度。标签相似度我用了Jaccard相似系数公式很简单交集大小除以并集大小。比如用户当前标签是[孕中期, 补钙, 胎教]一篇文章的标签是[孕中期, 胎教, 音乐]交集是[孕中期, 胎教]大小2并集是[孕中期, 补钙, 胎教, 音乐]大小4相似度就是2/40.5。阈值设为0.3够到线的就推荐。Flask端核心代码# recommend_service/app.py from flask import Flask, request, jsonify app Flask(__name__) def jaccard_similarity(set_a, set_b): if not set_a or not set_b: return 0.0 inter len(set_a set_b) union len(set_a | set_b) return inter / union app.route(/api/recommend, methods[GET]) def recommend(): user_tags set(request.args.get(tags, ).split(,)) candidate_items fetch_all_items() results [] for item in candidate_items: item_tags set(item[tags]) score jaccard_similarity(user_tags, item_tags) if score 0.3: results.append({item_id: item[id], score: score}) results.sort(keylambda x: x[score], reverseTrue) return jsonify({code: 0, data: results[:10]})实际运行中我还加入了两层过滤。第一层验证内容完整度标题、正文主图、价格商品/正文文章至少要有完整字段否则直接排除防止推送不完整的内容给用户。第二层做无效信息过滤把广告词、违禁词、明显的灌水内容挡在推荐池之外用了一个简单的词表匹配。这套推荐方案精度不算高但胜在实现简单、冷启动友好。用户第一次登录、没有任何行为数据时至少还有孕周标签可以用推荐结果不会太离谱。后续如果积累了足够多的行为数据再升级成协同过滤或者向量召回也不迟Flask服务的边界已经留好了替换内部算法不动接口就行。3.4 Django模板渲染与静态文件处理前端页面主要用了Django的模板系统做服务端渲染配合少量Vue和原生JavaScript处理交互。为什么不直接用前后端分离方案因为这个项目的大部分页面是内容展示型的SEO要求高。服务端渲染能保证搜索引擎直接抓到正文HTML对科普内容平台的流量获取很重要。商城这种交互复杂的模块以后升级成Vue或React重构也不冲突因为API接口都是现成的。模板层的核心是布局继承。base.html定义了公共的导航、页脚、底部浮动购买条内容页和商品页都继承它只需要填充各自的block。这个方案比每个页面复制一遍公共代码好维护得多改一次底部导航全站生效。要说这个环节最容易翻车的问题就是热词里那条VSCode写img标签在Django的static文件中显示不了。很多人刚接触Django时在模板里直接写了img src/static/images/banner.png但图片就是不出来。核心原因是Django对static文件的处理需要两个前提STATIC_URL /static/必须在settings.py里配置。开发环境要在urls.py里手动加上static文件的serve路由或者在INSTALLED_APPS里启用django.contrib.staticfiles并开启DEBUGTrue。正确的模板写法是{% load static %} img src{% static images/banner.png %} altbanner{% static %}模板标签会根据STATIC_URL前缀拼接出正确路径这样将来如果换了CDN域名只需要改settings里的配置就行模板不用动。另外开发时改完CSS、JS常常发现浏览器不刷新这不是代码问题是浏览器缓存。Django的static标签默认会带上文件mtime校验文件变了会thread_guard生成新版本号。但如果用了class-based view的静态文件服方式可能没有这个机制需要手动在URL后加?v20250101之类的版本参数来绕过缓存。3.5 项目部署Gunicorn、Supervisor、Nginx部署环节我踩的坑比开发环节还多值得单独拉出来详细写。部署方案是Django和Flask各挂在一个Gunicorn进程上Supervisor守护进程保证崩溃自动拉起Nginx做反向代理把80端口流量分发给两个后端服务。WebSocket连接比较特殊Nginx需要配上Upgrade头才能正确转发map $http_upgrade $connection_upgrade { default upgrade; close; } upstream django_backend { server 127.0.0.1:8001; } upstream flask_recommend { server 127.0.0.1:8002; } server { listen 80; server_name your_domain.com; location /static/ { alias /var/www/pregnancy_shop/static/; } location /ws/ { proxy_pass http://django_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } location /api/recommend/ { proxy_pass http://flask_recommend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { proxy_pass http://django_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }部署时数据库用了MySQL需要注意字符集。建库时一定要指定utf8mb4否则用户提交的emoji存进去会变成问号。我用的建表语句是CREATE DATABASE pregnancy_shop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Django的settings里配置OPTIONS加入charsetutf8mb4。static文件在部署环境是另行处理的执行python manage.py collectstatic把所有静态文件收集到STATIC_ROOT然后Nginx直接serve这个目录。忘记执行collectstatic是另一个高频问题症状就是页面排版全乱CSS、JS全部404。4. 常见问题与排查技巧实录4.1 Django静态文件不显示的完整排查思路这个问题在热搜里出现了而且我确实被它折腾过一整个下午。排查顺序建议从外到内先看浏览器Network面板CSS/JS/图片是404还是403还是200但内容不对。404基本是路径错了403基本是权限问题。接着在服务器上直接curl图片URL区分是Nginx问题还是Django问题。确认设置里STATICFILES_DIRS是否包含自定义的静态目录staticfiles_apps是否在INSTALLED_APPS里。最常见的情况是开发环境能用、部署环境不能用因为collectstatic没执行或者STATIC_ROOT配置错误。另外注意STATICFILES_DIRS和STATIC_ROOT不能指向同一个目录否则collectstatic会报错。4.2 Django ORM查询与删除对象时容易踩的坑django执行查询-删除对象这个热词说明很多人遇到过ORM操作的迷惑行为。我总结几个高频问题get和filter的区别必须清楚。get()返回单个对象匹配不到或多条都会抛异常适合按唯一主键查filter()返回QuerySet永远不抛异常查不到是空的。新手用get查一个不存在的ID页面直接500。删除对象时的级联风险也很大。Django默认在某些外键关系上开启CASCADE比如User删除后他关联的Article全部级联删除。在一个运营后台里如果把一个僵尸用户删了连带他写的几百篇高质量专家文章也删了那就麻烦了。做法是ForeignKey字段显式设置on_deletemodels.SET_NULL或PROTECT对重要内容宁可保留也不能连带删除author models.ForeignKey(User, on_deletemodels.PROTECT)批量删除的坑更隐蔽Article.objects.filter(statusdraft).delete()会走ORM的collect cascades先把所有关联对象load出来再逐个删数据量大时速度感人而且不容易看清到底删了多少关联表数据。慎用批量delete真要清理垃圾数据建议在Django shell里先检查关联数量确认无误再动手。4.3 Flask开发中的调试技巧与数据类型检查Flask命令行跑起来后如果需要查看客户端传来的参数到底是什么类型很多人不会调试。热词里那条flask查看从客户端获取的变量数据类型其实就是个老手也知道的问题request.args.get()返回的是字符串即使你的URL里写的是数字比如?age28拿到的也是字符串28不会自动转int。如果忘了转换拿它和整数比较或用age 1会直接爆TypeError。我在Flask服务里遇到需要判断来源变量类型时会直接在接口里加一行日志app.route(/debug, methods[GET, POST]) def debug(): app.logger.info(args type: %s, type(request.args.get(id))) app.logger.info(json: %s, request.get_json(silentTrue)) return jsonify({code: 0})Flask的request对象下面挂了很多属性args是QueryStringform是表单体json是JSON请求体files是上传文件。各取各的不要把form里的东西用args去拿否则永远拿到None。另一个常见问题是flask如何绑定到网页元素这其实是模板层的概念——Flask的render_template渲染Jinja2模板时把Python变量直接塞进HTML里的插值区域比如{{ product.name }}。如果发现页面元素上不显示数据先看视图函数是否传了对应变量再看模板插值名拼得对不对多数是这两个原因。4.4 WebSocket连接不稳定的排查清单WebSocket连接不稳定的干扰因素很多我按频率排序整理成一份速查表现象可能原因排查方法连接立即断开用户认证失败或channel_layer未配置检查Consumer connect逻辑确认scope.user连接偶尔断Redis channel_layer未配置多进程丢消息安装channels_redis并配置CHANNEL_LAYERS代理环境断连Nginx未配置Upgrade头检查location /ws/的proxy_set_header几分钟后断未处理心跳ping/pong前端定时发ping后端pong响应消息延迟严重Redis读取超时检查CHANNEL_LAYERS超时参数Redis和Web服务同内网生产环境WebSocket如果超过60秒不活跃服务器或代理会主动掐掉连接。前端需要实现心跳机制每30秒发一个ping消息Consumer收到后回一个pong连接就保持活跃了。前端JavaScript用一个setInterval就能实现记得在组件卸载时清掉定时器否则会有内存泄漏。4.5 其他实战中必备的小技巧敏感操作一定要记录操作日志。我在商城里每笔订单状态变更都会写一条log包括操作人、时间、旧状态、新状态、变更原因。后来运营排查纠纷时全靠这些日志还原现场。搜索功能不要一上来就上Elasticsearch。数据量在几十万条以内Django ORM的icontains查询够用了顶多再配合一个简单的全文索引字段。ES引入后运维成本直线上升对个人项目不划算。数据备份定时做。我已经养成习惯每天晚上用crontab跑一次mysqldump备份文件保留7天滚动覆盖。有一次不小心删了线上订单表全靠备份恢复否则就是事故。写在最后的个人经验做这类内容电商的孕婴平台技术层面的挑战反而不是最大的真正难的是对业务的理解。我后来复盘最大的心得是用户搜索词和浏览日志本身就是宝藏比任何专家意见都更真实地反映了新手父母的焦虑。我在平台上线一个月后翻搜索日志发现有大量孕晚期 睡姿 左卧还是右卧哺乳期 能吃辣吗这类高频词于是调整了内容优先级和商品选品方向当月内容点击率提升了30%以上。最后再分享一个已经被验证有效的小技巧电商系统上线前把订单状态机所有合法和非法跳转列表打印出来逐个走一遍测试用例。我当时写了一个单元测试把每个状态能跳转到哪些目标状态都测了一遍一共几十个用例用时几分钟跑完但至少拦住了三个未来上线后必爆的隐藏bug。这个习惯建议大家直接抄走。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →