后端¶
架构设计¶

设计原则¶
- 缓存加速:数据库中的数据量与访问速度负相关。由于
新闻数据库数据量大(千万量级),因此需要加入缓存系统。为保证缓存命中率,将近期更新的新闻、近期与用户交互(搜索、收藏、阅读等)的新闻加入缓存。 - 业务分离:后端与AI摘要分别是IO密集型与计算密集型任务。因此为二者建立独立服务,避免两者争抢运算资源。
功能设计¶
新闻缓存¶
- 定时从新闻数据库获取最新新闻并缓存至内存
- 缓存搜索内容至内存
- 维护新闻首页展示内容
- 向其它内部模块快速提供新闻内容
- 启动(退出)时加载(保存)本地缓存
- 维护缓存大小
用户新闻管理器¶
- 记录与用户交互的新闻及交互信息
- 缓存加速
- 维护AI摘要内容
token校验¶
- 用户登陆时生成
token(7天时效) - 用户退出登录时注销
token - 维护
token白名单 - 校验请求中
token是否有效
用户管理¶
- 创建用户
- 用户登录(登出)
- 更新(获取)用户标签
- 修改(获取)用户信息
- 修改(获取)用户头像
视图模块¶
- 根据数据库中信息,响应前端请求
- 根据前端请求,更新数据库
实现¶
项目结构¶
│ .pycodestyle # pycodestyle配置文件
│ .pylintrc # pylint配置文件
│ pytest.ini # pytest配置文件
│ db.sqlite3 # 默认数据库(未使用)
│ manage.py # Django项目管理
│
├─asyNc # 默认项目文件夹
│ asgi.py
│ settings.py # 项目设置
│ urls.py # 项目主路由
│ wsgi.py
│ __init__.py
│
├─certificate # 数据库证书
│ ca-bundle.pem
│ ca.pem
│
├─config # 后端配置文件
│ config.json # 后端数据库配置
│ es.json # es搜索配置
│ lucene.json # lucene搜索配置
│
├─data # 数据文件
│ default_avatar.base64 # 默认头像
│ news_cache.pkl # 新闻缓存(本地存储部分)
│ news_template.pkl # 新闻模板
│
└─main # 后端主应用
│ admin.py
│ apps.py # apps设置
│ config.py # 参数设置
│ models.py # 数据模型
│ responses.py # responses模板
│ tests.py # 单元测试
│ tools.py # 工具
│ urls.py # 应用路由
│ views.py # 视图
│ __init__.py
│
├─managers
│ DBScanner.py # 新闻缓存定时更新器
│ NewsCache.py # 新闻缓存管理器
│ LocalNewsManager.py # 用户新闻管理器
│
└─migrations # 数据库模型迁移
新闻获取函数: get_data_from_db¶
实现函数:main.tools.get_data_from_db(news_id)
按优先顺序根据news_id从新闻缓存管理器、用户新闻管理器、新闻数据库中获取新闻并返回。
新闻缓存定时更新器¶
实现类:main.managers.DBScanner.DBScanner(db_connection, news_cache, get_data_from_db, testing_mode=False, front_page_news_num=10, db_check_interval=8, db_news_look_back=65536, db_update_minimum_interval=8)
| 参数 | 含义 |
|---|---|
db_connection |
新闻数据库连接 |
news_cache |
新闻缓存管理器 |
get_data_from_db |
新闻获取函数 |
testing_mode |
测试模式 |
front_page_news_num |
首页新闻数 |
db_check_interval |
数据库扫描间隔 |
db_news_look_back |
数据库扫描窗口 |
db_update_minimum_interval |
缓存更新间隔下限 |
启动: self.run()¶
在子线程中启动。启动时根据首页新闻数调用新闻获取函数从新闻数据库中快速获取满足新闻首页展示数量的最新新闻。启动后扫描数据库变更。
扫描: self.check_db_update()¶
根据数据库扫描间隔定期获取数据库新闻数。若新闻数据库中新闻数目更新,则根据缓存更新间隔下限判断是否更新缓存并执行。
获取数据库新闻数: self.get_db_news_num()¶
从新闻数据库中获取数据库新闻总数。
更新缓存: self.update_cache()¶
调用新闻缓存管理器的更新缓存方法。
测试模式: self.testing_mode=True¶
根据数据库扫描窗口从新闻数据库获取新加入的新闻,并添加至新闻缓存管理器。
新闻缓存管理器¶
实现类:main.managers.NewsCache.NewsCache()
添加新闻至缓存: self.update_cache(news_list)¶
将news_list中的新闻加入缓存,并维护缓存大小(删除旧新闻)。
获取首页分类新闻: self.get_cache(category)¶
获取缓存中类别为category的新闻。
用户新闻管理器¶
实现类:main.managers.LocalNewsManager.LocalNewsManager()
管理与用户产生过交互的新闻。
添加新闻至缓存: self.add_to_cache(news)¶
将news新闻加入缓存,并维护缓存大小(删除旧新闻)。
存贮至用户新闻数据库: self.save_one_local_news(news)¶
将news新闻加入用户新闻数据库,并添加新闻至缓存:。
从用户新闻数据库获取: self.get_one_local_news(news_id)¶
按优先顺序根据news_id从缓存和用户新闻数据库中获取新闻。
token校验¶
白名单¶
样式:
TOKEN_WHITE_LIST={
"user_id 1": ["encoded_token 1","encoded_token 2",...],
"user_id 2": ["encoded_token 1","encoded_token 2",...],
...
}
创建token¶
实现函数: main.tools.create_token(user_name, user_id=0)
根据user_name,user_id,当前时间创建token。
解码token¶
实现函数: main.tools.decode_token(encoded_token)
根据encoded_token,解码得到user_name,user_id并返回。
检验token过期¶
实现函数: main.tools.token_expired(token)
检查token是否过期。
将token加入白名单¶
实现函数: main.tools.add_token_to_white_list(encoded_token)
将encoded_token加入白名单。
检验token有效¶
实现函数: main.tools.check_token_in_white_list(encoded_token)
先检查encoded_token是否在白名单,之后检验token过期。
将token移除¶
实现函数: main.tools.del_token_from_white_list(encoded_token)
将encoded_token移除白名单。