运行时能否将HTTP请求重定向至不同服务器?AdonisJS读写分离场景
实现方案
核心结论
完全可以在运行时动态切换数据库请求指向的服务器,无需修改.env文件。.env配置仅在项目启动时加载,运行时修改既不生效也不适合多实例部署场景,你之前排除该方案的判断是正确的。
具体实现步骤
步骤1:预先配置双数据库连接
在config/database.ts中提前配置主库(处理写请求)和读副本(处理读请求)两个连接,参数从.env中提前读取,无需运行时修改:
// config/database.ts 核心配置示例 import { defineConfig } from '@adonisjs/lucid' import env from '#start/env' const dbConfig = defineConfig({ connections: { // 主库:处理所有写请求 mysql_master: { client: 'mysql2', connection: { host: env.get('DB_MASTER_HOST'), port: env.get('DB_PORT'), user: env.get('DB_USER'), password: env.get('DB_PASSWORD'), database: env.get('DB_DATABASE'), }, pool: { min: 2, max: 20 }, }, // 读副本:处理所有读请求 mysql_replica: { client: 'mysql2', connection: { host: env.get('DB_REPLICA_HOST'), port: env.get('DB_PORT'), user: env.get('DB_USER'), password: env.get('DB_PASSWORD'), database: env.get('DB_DATABASE'), }, pool: { min: 2, max: 20 }, } } }) export default dbConfig
对应的.env文件提前写入两个数据库的地址即可:
DB_MASTER_HOST=你的主库地址 DB_REPLICA_HOST=你的Amazon Read Replica地址 # 其余共用配置保持正常填写
步骤2:在中间件中动态切换连接
基于你已经实现的请求方法识别逻辑,在中间件中为当前请求绑定对应数据库连接即可:
// app/middleware/db_route_middleware.ts import type { HttpContext } from '@adonisjs/core/http' import db from '@adonisjs/lucid/services/db' export default class DbRouteMiddleware { async handle({ request }: HttpContext, next: () => Promise<void>) { const readMethodList = ['GET', 'HEAD', 'OPTIONS'] const isReadRequest = readMethodList.includes(request.method()) // 为当前请求挂载对应连接,后续业务逻辑直接使用request.db操作数据库即可 request.db = isReadRequest ? db.connection('mysql_replica') : db.connection('mysql_master') await next() } }
别忘了在start/kernel.ts中注册该全局中间件,对所有请求生效。
步骤3:业务逻辑适配
如果使用原生数据库操作,直接调用上下文中挂载的db实例即可:
// 路由逻辑示例,无需再判断请求方法 router.get('/users', async ({ request }) => { return await request.db.from('users').select('*') })
如果使用Lucid ORM,在查询时指定连接即可:
// 读请求查询示例 const users = await User.query({ connection: 'mysql_replica' }).where('status', 1) // 写请求操作示例 const newUser = await User.create({ name: '张三' }, { connection: 'mysql_master' })
注意事项
- 所有事务操作必须统一走主库,Amazon RDS读副本不支持写入和事务提交
- 对于部分特殊GET接口(如包含日志写入、统计上报逻辑的接口),可在中间件中添加白名单强制走主库
- 主从同步存在延迟,对数据一致性要求极高的读请求建议直接走主库
- AdonisJS会自动管理两个连接的连接池,无需额外处理性能问题
内容的提问来源于stack exchange,提问作者PlayHardGoPro
相关产品推荐
相关产品推荐

