logan

logan是基于gin的web项目,集成了sentry、gorm、premetheus等工具,旨在高效快速的web开发。

编译部署

  1. clone本项目至GOPATH下,执行 git clone https://github.com/LiuRoy/logan.git $GOPATH/src

  2. 安装依赖库,此项目依赖包列写在requirements文件中,执行命令go get -u <依赖包>进行安装

  3. 执行go run main.go,启动server

gin

gin是基于go语言轻量级web开发框架(项目地址: https://github.com/gin-gonic/gin),不仅运行效率很高,而且提供了参数校验、模板渲染、定制化插件等十分有用的功能,极大简化了接口开发难度。为了提供一款快速上手的后台开发模板,logan就用到了gin。

添加接口

定义好函数类型为func(*gin.Context)的函数,然后添加到对应的路径下即可。

router := gin.New()
router.Use(gin.Logger(), tools.Recovery(sentryClient), tools.Prometheus())

// add endpoint
router.GET(tools.DefaultMetricPath, tools.LatestMetrics)
router.GET("/ping", func(c *gin.Context) {c.String(http.StatusOK, "pong")})
router.POST("/message", apis.AddMessage)
router.GET("/message", apis.GetMessage)
router.Run(address)

参数获取

  • 针对参数放在url中的请求,可以使用gin.Context.GetQuery或者gin.Context.DefaultQuery,获取需要的参数。
func GetMessage(c *gin.Context) {
    messageId, exist := c.GetQuery("message_id")
    if !exist {
        c.JSON(http.StatusBadRequest, gin.H{"result": "bad params"})
    } else {
        msgId, _ := strconv.ParseUint(messageId, 10, 0)
        message := model.GetMessage(uint(msgId))
        c.JSON(http.StatusOK, gin.H{"result": "ok", "message": *message})
    }
}
  • 针对参数放在body的请求,通过gin.Context.Bind解析验证参数(可以制定哪些参数是否必需)。
type message struct {
    Type string `json:"type" binding:"required"`
    InitiatorId uint `json:"initiator" binding:"required"`
    ConsumerId uint `json:"consumer" binding:"required"`
    ResourceId string `json:"resource_id"`
    IsFollow bool `json:"isfollow"`
    Gcid string `json:"gcid"`
    Cid uint `json:"cid"`
    Response string `json:"response"`
    reply string `json:"reply"`
}

func AddMessage(c *gin.Context) {
    var param message
    if c.BindJSON(&param) == nil {
        switch param.Type {
        case "follow":
            model.AddMessage(param.Type, param.InitiatorId,  "aaa", "bbb",  param.ConsumerId, "", "", "", "", "")
        default:
            panic("unknown type")
        }
        c.JSON(http.StatusOK, gin.H{"result": "ok"})
    } else {
        c.JSON(http.StatusBadRequest, gin.H{"result": "bad params"})
    }
}

模板渲染

后台常用的返回格式是json,gin.Context.JSON很方便的可以把结果序列化为json返回给调用放。

c.JSON(http.StatusOK, gin.H{"result": "ok", "message": *message})

配置获取

logan提供了两种从consul获取的方式:启动时获取和运行监听。

启动时获取

针对大部分不改变的配置,logan只会在启动进程的时候访问consul读取配置。

var SentryDsn string = tools.GetSingle("sentry_dsn")

运行监听

针对某些经常改变的配置参数,希望consul每次改动在不重启进程的情况下立即生效的场景。每次使用的时候访问consul肯定会增加接口耗时。logan使用了watch方式,每一个参数都有一个对应的goroutine阻塞地监听,一旦改动,马上更新(建议不要设置太多)。

var TestParam tools.WatchedParam
tools.WatchSingle("test_param", &TestParam)
var currentValue string = TestParam.Get()

监控

监控了各个接口的调用次数、出错次数、接口耗时。如果需要定制一些特定的监控,可以参考prometheus.go文件在业务代码中打点。监控数据通过/logan/metrics获取。

sentry

在sentry.go中,如果发现接口运行报错,会将错误栈信息发送给sentry,并更新相关接口的出错次数。

缓存

使用redis作为缓存,只需要将redis集群消息以["10.33.111.4:6379", "10.33.22.4:6380", "10.33.44.4:6381", "10.33.1.55:6382", "10.33.1.54:6383", "10.33.1.74:6384"]格式配置在consul中即可

数据库

为了简化业务代码,logan使用了gorm(文档链接: http://jinzhu.me/gorm/)。

// 对应的表结构见https://github.com/LiuRoy/logan/blob/master/model/mysql.sql
type Message struct {
    MsgId uint `gorm:"column:msgid;primary_key"`
    Type string `gorm:"column:type;type:varchar(32)"`
    InitiatorId uint `gorm:"column:initiatorid"`
    InitiatorName string `gorm:"column:initiatorname;type:varchar(255)"`
    InitiatorPortrait string `gorm:"column:initiatorportrait;type:varchar(255)"`
    ConsumerId uint `gorm:"column:consumerid"`
    ResourceId string `gorm:"column:resource_id;type:varchar(255)"`
    ExtraInfo1 string `gorm:"column:extra_info1;type:varchar(512)"`
    ExtraInfo2 string `gorm:"column:extra_info2;type:varchar(512)"`
    ExtraInfo3 string `gorm:"column:extra_info3;type:varchar(512)"`
    ExtraInfo4 string `gorm:"column:extra_info4;type:varchar(512)"`
    InsertTime time.Time `gorm:"column:insert_time" sql:"DEFAULT:current_timestamp"`
}

func (Message) TableName() string {
    return "msgcenter_innodb"
}

func AddMessage(msgType string, initiatorId uint, initiatorName string,
    initiatorPortrait string, consumerId uint, resourceId string,
    extraInfo1, extraInfo2, extraInfo3, extraInfo4 string) *Message {
    message := Message{
        Type: msgType,
        InitiatorId: initiatorId,
        InitiatorName: initiatorName,
        InitiatorPortrait: initiatorPortrait,
        ConsumerId: consumerId,
        ResourceId: resourceId,
        ExtraInfo1: extraInfo1,
        ExtraInfo2: extraInfo2,
        ExtraInfo3: extraInfo3,
        ExtraInfo4: extraInfo4,
    }
    DbConnection.Create(&message)
    DbConnection.NewRecord(message)

    RedisConnection.Set("aaaaaaa", message.MsgId, 0)
    return &message
}

func GetMessage(messageId uint) *Message {
    message := Message{}
    DbConnection.Where("msgid = ?", messageId).First(&message)
    return &message
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,966评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,170评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,909评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,959评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,851评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,583评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,956评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,590评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,878评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,892评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,719评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,501评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,957评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,124评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,440评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,003评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,211评论 2 339

推荐阅读更多精彩内容