参考请注意: 该文档创建于 2022/3/29,请注意随时间流逝文档信息是否过时,是否还有可参考的价值。 该文档仅作为个人笔记记录。 该文档记录时,使用的软件等版本会列在文档中,请注意识别。
让它跑起来
后端的项目配置成本不是一般的高。
这里,我们的目标是,不但让这个项目能够跑起来,然后能够正常开发,测试,debug。
而且也要配置好数据库的访问。
docker
首先学习了一下docker的基本使用,然后按照文档,做了必要的操作,然后通过 docker compose 进行了生产环境部署,效果都很不错。
此外,开发环境它是只跑了 mongodb 和 redis,本地在自己的电脑上跑。但实际上我搞了一个部署在 docker 上的跑法。
package.json
该项目 egg 的 ts-helper 不起作用。
将 package.json 插入以下内容即可:
"egg": {"declarations": true},
数据库
mongodb
该项目原本使用 3.2 版本的 mongodb,可以跑。
但是使用 vscode 或 Mongo compass 连接时,会报错,提示需要 mongodb 3.6 以上版本才支持当前的 nodejs driver。
reports maximum wire version 4, but this version of the Node.js Driver requires at least 6 (MongoDB 3.6)
这样,该项目需要 3.6 以上的 mongodb,才能用 vscode 插件等方式连接数据库进行操作。而且 3.2 版本已经是处于 EOL 阶段了。
所以这里选择升级一个新的 mongodb 版本,我这里选择的版本是 5.0。尽量跑之前先升级。理由如下:
如果有了数据之后再去做数据库版本升级,非专业人士不敢做这个数据迁移。这个改动很大(生产环境中),容易出现升级之后数据库没法运行的情况。
redis
项目用 redis 干了这些事:
- rss 缓存,5 分钟
- top100 排行榜信息缓存,1 分钟
- 所有用户尚未回复的帖子缓存,1 分钟
- 访问论坛页的内容缓存,查询为键,1 分钟
- 统计一个用户一天发的话题数(并限制数量)
- 统计一个ip一天注册的用户数(并限制数量)
测试/使用环境数据库分离
有这些思路:
实际使用开发/测试使用一个容器,docker的初始化脚本连续建两个数据库和用户
- redis
redis在一个进程中,通过切换整数型的index来用不同的数据库。
在launch.json里面修改EGG_REDIS_DB环境变量为 1 就 ok 了 - mongodb
这个时候,不能使用原来的init.js创建了,而是另写一个sh文件init-mongodb.sh:
另附在这里执行mongo admin -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} << EOF# 切换到 测试数据库,并创建用户use ${MONGO_INITDB_DATABASE}_testdb.createUser({ user: '${MONGO_INITDB_DATABASE}_test', pwd: '${MONGO_INITDB_DATABASE}_password_test', roles: [{ role: 'readWrite',db: '${MONGO_INITDB_DATABASE}_test' }] })db.${MONGO_INITDB_DATABASE}.insert({ ${MONGO_INITDB_DATABASE}: 'egg-cnode' })# 切换到 开发数据库,并创建用户use ${MONGO_INITDB_DATABASE}db.createUser({ user: '${MONGO_INITDB_DATABASE}', pwd: '${MONGO_INITDB_DATABASE}_password', roles: [{ role: 'readWrite', db: '${MONGO_INITDB_DATABASE}' }] })db.${MONGO_INITDB_DATABASE}.insert({ ${MONGO_INITDB_DATABASE}: 'egg-cnode' })EOF
printenv的结果:
注:会写这个真得好好入门 shellmongo-trial-mongodb-1 | HOSTNAME=e5d000827a01mongo-trial-mongodb-1 | MONGO_INITDB_DATABASE=egg_cnodemongo-trial-mongodb-1 | PWD=/mongo-trial-mongodb-1 | MONGO_INITDB_ROOT_PASSWORD=root_passwordmongo-trial-mongodb-1 | MONGO_INITDB_ROOT_USERNAME=rootmongo-trial-mongodb-1 | HOME=/home/mongodbmongo-trial-mongodb-1 | MONGO_PACKAGE=mongodb-orgmongo-trial-mongodb-1 | JSYAML_VERSION=3.13.1mongo-trial-mongodb-1 | GOSU_VERSION=1.12mongo-trial-mongodb-1 | MONGO_REPO=repo.mongodb.orgmongo-trial-mongodb-1 | MONGO_VERSION=5.0.5mongo-trial-mongodb-1 | MONGO_MAJOR=5.0mongo-trial-mongodb-1 | SHLVL=1mongo-trial-mongodb-1 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binmongo-trial-mongodb-1 | _=/usr/bin/printenv
- redis
开发/测试使用同一镜像但不是同一容器,配备不同的数据卷
这个好办。写一个docker-compose.test.yml,将数据卷名字加_test就可
vscode launch.json
主要问题是带环境变量运行,需要在 vscode launch.json 中配置,不然直接写命令太长
这里就三种配置,egg默认给的:
- 本地运行+断点调试
- 单元测试
- 挂远程调试
注意:{// 使用 IntelliSense 了解相关属性。// 悬停以查看现有属性的描述。// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations": [{"type": "node","request": "launch","name": "Egg Debug","runtimeExecutable": "npm","runtimeArgs": ["run","debug","--","--inspect-brk"],"env": {"EGG_REDIS_DB": "0","EGG_REDIS_HOST": "localhost","EGG_REDIS_PORT": "6379","EGG_REDIS_PASSWORD": "your_redis_password","EGG_MONGODB_URL": "mongodb://egg_cnode:egg_cnode_password@localhost:27017/egg_cnode","EGG_PASSPORT_GITHUB_CLIENT_ID": "your_github_client_id","EGG_PASSPORT_GITHUB_CLIENT_SECRET": "your_github_client_secret"},"console": "integratedTerminal","restart": true,"protocol": "auto","port": 9229,"autoAttachChildProcesses": true},{"type": "node","request": "launch","name": "Egg Test","runtimeExecutable": "npm","runtimeArgs": ["run","test-local","--","--inspect-brk"],"env": {"EGG_REDIS_DB": "1","EGG_REDIS_HOST": "localhost","EGG_REDIS_PORT": "6379","EGG_REDIS_PASSWORD": "your_redis_password","EGG_MONGODB_URL": "mongodb://egg_cnode_test:egg_cnode_password_test@localhost:27017/egg_cnode_test","EGG_PASSPORT_GITHUB_CLIENT_ID": "your_github_client_id","EGG_PASSPORT_GITHUB_CLIENT_SECRET": "your_github_client_secret"},"console": "integratedTerminal","protocol": "auto","port": 9229,"autoAttachChildProcesses": true},{"type": "node","request": "attach","name": "Egg Attach to remote","localRoot": "${workspaceRoot}","remoteRoot": "/usr/src/app","address": "localhost","env": {"EGG_REDIS_DB": "0","EGG_REDIS_HOST": "localhost","EGG_REDIS_PORT": "6379","EGG_REDIS_PASSWORD": "your_redis_password","EGG_MONGODB_URL": "mongodb://egg_cnode:egg_cnode_password@localhost:27017/egg_cnode","EGG_PASSPORT_GITHUB_CLIENT_ID": "your_github_client_id","EGG_PASSPORT_GITHUB_CLIENT_SECRET": "your_github_client_secret"},"protocol": "auto","port": 9999}]}
邮箱注册登录
邮箱注册登录还是很麻烦的。
- 首先,从自己的邮箱中申请 SMTP 服务,保存好你自己的邮箱和授权码,在
config.default.js中填入:

注:host 你用啥邮箱就写啥邮箱对应的 smtp 服务器地址,
port 默认 465,没加密就是 25
- 将
controller/sign.js77 行处反注释,打开发邮件开关:

下面 150 行处还有一个重置密码的邮件开关,改一下:
- 修改
config.default.js中的config.host改成你的 socket debug 模式下会被代码截胡不发。把
service/mail.js这里注了:
github oauth 认证
这个还是很简单的,你在GitHub上面申请一个 oauth,配置如下:

注意的问题:clientid 和 Client secrets 保存好
- 在 dev 端测试,URL的 socket 改成自己的,上线时改成你的域名!
而且注意,callback URL 后面的路径不能错了。 - 修改
config.default.js中的config.host改成你的 socket
然后,启动 app,应该就可以正常使用了!
但是这样还没完,以下还有一些地方需要改:
业务逻辑
业务逻辑修改
首先目前注册登录有问题:
- 如果你的激活邮件没有到,那你的账户邮箱就无法登录,也无法重新注册,登录失败还不给错误提示。
- 邮箱和 github 难以绑定。你用邮箱注册了,再用 github 登录,会报错。
- github 用户登录,拿到的邮箱是在 github 里设置的公有邮箱,没设置的的可能米有邮箱。
所以这里得改:
- 如果激活邮件没到,但是登录,会返回到激活界面重新发激活
- 认为 github 等只是一个登录方式,你只要有这个登录方式就可以登录,不必担心多种方式登录时,邮箱等相关信息重合的问题(这种开发者社区又不是游戏,不用担心多平台同一人开小号问题)
首先想一下这个重新激活的问题(可以就这个议题和产品经理吵一架):
假设用户注册的时候需要点击注册邮件来确认激活,才能拥有作为一个注册用户的权利。 那么,假设,用户注册完的时候,服务器发的邮件接收不到,而且重发邮件的页面也关了。 用户需要怎样重新拿到这个激活邮件? 注册的时候肯定是不行的(再次重注册会用户名重复) 所以想让它登录的时候当作未注册用户登录进去,然后返回去立刻重新发送激活验证邮件。 但是经过再次讨论,认为重新发的时候需要重新验证一下之前注册的邮箱。 (涉及到如果)
单元测试
用户逻辑修改了,之前的单元测试是不可能跑通的,需要重新改单元测试。
目前的单元测试的问题:
- 很多测试中 mock 的 user 都是不带active的/修改了 active 测试后没改回来,新的 userRequired 中间件要求必须激活才有用户权限。
这个我去查了很多 controller 的单元测试,它们还都是一个it去mock一个用户且很多都是一样的。
加active还必须右侧大文本查找替换
