项目中使用的场景:
账户扫码登录,微信扫码授权,消息实时提醒,配置结果响应,客户端同步数据。。。
之前项目里做即时通信都是用的轮循,轮询的效率低,非常浪费资源,后面好几个项目都开始用的websocket配合koa和redis来实现,现在整理整理深入了解下整个即时通信实现的过程。
前提:需要安装的包
- koa 由 Express 幕后的原班人马打造,使用起来比Node更优雅简洁 https://koa.bootcss.com/
- koa-router 是路由导航,实际应用中可以认为node接口https://www.npmjs.com/package/koa-router
- koa-websocket koa的中间件对websocket的封装 https://www.npmjs.com/package/koa-websocket
- redis 我们这里用到的是redis的订阅发布功能https://www.npmjs.com/package/redis
- dotenv 获取项目文件的环境变量也可以前端在config.js里写死 https://www.npmjs.com/package/dotenv
一、搭建基础的socket服务
搭建方法跟node服务差不多,多了koa-websocket中间件
const Koa = require('koa')
const router = require('koa-router')()
const websockify = require('koa-websocket')
const app = websockify(new Koa())
//创建socket接口
router.all('/kapi/socket/init', async ctx => {
const {
channel } = ctx.query //客户端调接口会传频道id
console.log(channel)
ctx.websocket.send('message')
})
// 注册路由允许使用中间件
app.ws.use(router.routes()).use(router.allowedMethods())
//端口号后面可采用动态的
app.listen(3131, () =>
console.log(`socket listening on port ${
Config.socket.port}`)
)
二、链接订阅redis频道
在socket的接口基础上,添加的了redis链接,频道的订阅,这里只展示关键的代码,后面会再做拆分整理
const Koa = require('koa')
const router = require('koa-router')()
const websockify = require('koa-websocket')
const app = websockify(new Koa())
const redis = require('redis')
//跟链接数据库一样,想链接redis频道需要这些参数
//先写死,后面整理使用dotenv动态获取
const redisConfig = {
host: '18.8.1.3',
port: '32',
password: '1232343',
db: 4
}
//创建socket接口
router.all('/kapi/socket/init', async ctx => {
const {
channel } = ctx.query //接受客户端传的频道id,并订阅redis
console.log(channel)
//链接redis https://www.npmjs.com/package/redis
let client = redis.createClient(redisConfig)
// 订阅redis频道
client.subscribe(channel)
// 接收消息
client.on('message', async (channel, message) => {
console.log(
'Received subscribe message, channel [%s] message [%s]',
channel,
message
)
//接收到消息,通过接口返回到客户端
await ctx.websocket.send(message)
})
})
// 注册路由允许使用中间件
app.ws.use(router.routes()).use(router.allowedMethods())
//端口号后面可采用动态的
app.listen(3131, () =>
console.log(`socket listening on port ${
Config.socket.port}`