首页 > go > GO 简易中间件开发

GO 简易中间件开发

需求

特定用户登录关键系统时,下发通知到特定管理员微信客户端。

痛点

由于php是非异步的,用户点击登录按钮,到返回登录后跳转必须经过下列步骤

1,从用户输入账号密码,到mysql里查询,校验身份通过,

2,到微信服务端换取access_token,缓存access_token,

3、向mysql查询微信openid,

4、向微信api发起CURL数据,微信再下发到open客户端,

5、最后把登录结果返回到前端

这一趟下来,用户会觉得很卡,至少2秒左右才有反馈

思路

用go+redis做中间件来实现异步推送通知,提升用户响应

1、用户输入账号密码,去mysql查询,校验身份通过后,写入redis,返回登录给客户端

2、go定时器监听redis key状态,命中后,curl到推送接口

这样,无论推送进程耗时多久,对用户来说都是无感知的,同时又实现了需求

代码

 

package main

import (
	"github.com/gomodule/redigo/redis"
	"fmt"
	"time"
	"crypto/md5"
	"github.com/mikemintang/go-curl"
)

//推送函数
func sendmsg(msg string) {

	data := []byte("*****")
	sign := fmt.Sprintf("%x", md5.Sum(data))

	url := "https://xxxx/api/wxmsg/apimsg"
	postData := map[string]interface{}{
		"sign":  sign,
		"title": "xxx用户登录",
		"msg":   msg,
	}

	req := curl.NewRequest()
	resp, err := req.
		SetUrl(url).
		SetPostData(postData).
		Post()
	if err != nil {
		fmt.Println(err)
	}

	if resp.IsOk() {
		fmt.Print(resp.Body)

	} else {

		//return "err"
		fmt.Println(resp.Raw)
	}

}

func main() {

	//连接redis
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Close()

	//3秒定时器
	timer := time.NewTicker(3 * time.Second)
	for {
		//写入内存
		<-timer.C
		v, e := redis.String(c.Do("GET", "login"))
		if e != nil {

		}

		//读取缓存命中
		if (v != "") {

			fmt.Println(v)
			//防止重复通知,先清理redis 再推送
			c.Do("SET", "login", "")
			sendmsg(v)

		}
	}

}