golang 用golang处理Github webhooks

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 用golang处理Github webhooks相关的知识,希望对你有一定的参考价值。

// Now available in package form at https://github.com/rjz/githubhook

package handler

// https://developer.github.com/webhooks/
import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

// Replace with your hook's secret
const secret = "shhhhh!!"

func signBody(secret, body []byte) []byte {
	computed := hmac.New(sha1.New, secret)
	computed.Write(body)
	return []byte(computed.Sum(nil))
}

func verifySignature(secret []byte, signature string, body []byte) bool {

	const signaturePrefix = "sha1="
	const signatureLength = 45 // len(SignaturePrefix) + len(hex(sha1))

	if len(signature) != signatureLength || !strings.HasPrefix(signature, signaturePrefix) {
		return false
	}

	actual := make([]byte, 20)
	hex.Decode(actual, []byte(signature[5:]))

	return hmac.Equal(signBody(secret, body), actual)
}

type HookContext struct {
	Signature string
	Event     string
	Id        string
	Payload   []byte
}

func ParseHook(secret []byte, req *http.Request) (*HookContext, error) {
	hc := HookContext{}

	if hc.Signature = req.Header.Get("x-hub-signature"); len(hc.Signature) == 0 {
		return nil, errors.New("No signature!")
	}

	if hc.Event = req.Header.Get("x-github-event"); len(hc.Event) == 0 {
		return nil, errors.New("No event!")
	}

	if hc.Id = req.Header.Get("x-github-delivery"); len(hc.Id) == 0 {
		return nil, errors.New("No event Id!")
	}

	body, err := ioutil.ReadAll(req.Body)

	if err != nil {
		return nil, err
	}

	if !verifySignature(secret, hc.Signature, body) {
		return nil, errors.New("Invalid signature")
	}

	hc.Payload = body

	return &hc, nil
}

func Handler(w http.ResponseWriter, r *http.Request) {

	hc, err := ParseHook([]byte(secret), r)

	w.Header().Set("Content-type", "application/json")

	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		log.Printf("Failed processing hook! ('%s')", err)
		io.WriteString(w, "{}")
		return
	}

	log.Printf("Received %s", hc.Event)

  // parse `hc.Payload` or do additional processing here

	w.WriteHeader(http.StatusOK)
	io.WriteString(w, "{}")
	return
}

Golang实战群:日志的处理机制

日志的处理机制


1   golang日志库可以考虑 tmlog    https://github.com/heiyeluren/go-tmlog  --黑夜路人@北京

    

2   老谢,你这个是异步库,一旦log gr 出问题不就坑爹了  可以考虑加上阻塞方式的,效率低点,但是安全  log库不必也没必要追求效率   --于雨@北京

    

3   行啊,回头再考虑实时写入临时日志  --黑夜路人@北京

    

4   一般的逻辑处理,瓶颈不可能在log上,务求不丢不乱就行了 --于雨@北京

    

5   前阵子看过一篇文章,一个老外做的分析,系统性能消耗有不少的部分浪费在同步log上   --郭军@360

    

6   主要是磁盘io慢啊慢  --黑夜路人@北京

    

9   确实,我们client的log都出于效率原因从同步实时改成异步分批写入了    --类库@上海-意励

    

8   log太多了吧,会对io造成压力  --kyle@成都-风际游戏

    

9   异步的本质都是为了不阻塞当前执行协程  --黑夜路人@北京

    

10  瓶颈还真有可能在log上  --Xargin@北京-didi

    

11  可以开启raid卡wb,对比下,如果差异巨大,可能是log导致的  --谭俊青@途牛

    

12  去年写proxy 日志info级别性能下降蛮多的 还是要少打日志的。业务对性能要求不苛刻就无所谓了  --董泽润@北京-nice

    

13  不要用文本日志,改成二进制代号  --kingsword@广州-kg

    

14  采用文本大多是还是为了日志可读,排查问题方便,快吧  --郭军@360

    

15  有运维朋友原来在微信的,说他们为了解决这个问题,强制要求所有业务都改成代号,解释器啊  --kingsword@广州-kg

    

16  日志阻塞很严重  --金灶沐@北京-康复中心

    

17  qq邮箱时期的事情,后来微信也沿用了  异步解决不了io问题,系统io阻塞一样会影响业务线程  --kingsword@广州-kg

    

18  瓶颈出现在log上是很常见的  鞋日志不能同步写啊    --神仙@上海|杭州-有赞

    

19  buf啊 批量刷 不行再分桶 批量。。尽量做大不影响flush --金灶沐@北京-康复中心

    

20  必须有buf  --神仙@上海|杭州-有赞

    

21  buf只能缓冲写   --郭军@360

    

22  鹅厂日志量大的系统都通过网络发到专门的日志系统  日志量大为啥还要扔给磁盘?   --于雨@北京

    

23  网络io优于磁盘io?  --类库@上海-意励

    

24  我们的系统日志很容易成为瓶颈。所以日志系统有一个逻辑,日志如果太频繁,会折叠成一条  --Tiger张虎@深圳-云巴

    

25  有个想法是,程序里继续写,做个扫描器在编译的时候把所有日志汇总生成日志解释库,然后代码替换了  --kingsword@广州-kg

    

26  如果不是不能丢的日志,网络上有udp发  --神仙@上海|杭州-有赞

    

27  我们现在开了三条通道,http,udp,tcp --Tiger张虎@深圳-云巴

    

28  强制要求所有业务都改成代号,有点不解,求解释下。  --飞蓬@杭州

    

29  打成代号,是不是像http的200 404这种?  把错误归类?  --于雨@北京

    

30  udp会不会像我们做多终端消费那样。 打上唯一递增消息。 服务端接受看信息完整不完整,如果完整就继续接受,不完整就回馈消息。  --金灶沐@北京-康复中心

    

31  可以这么干  这种就是udp上做可靠传输了  --神仙@上海|杭州-有赞

    

32  Io带来的开销和延迟,在调用密集型影响巨大  最优是异步加udp,同时考虑上层交换延迟和流量,控制pipeline避免丢包  而且大部分日志库都是同步加锁,异步也有队列争用    --毛剑@上海-bilibili

    

33  360的视频云就是udt  udx fast udx好像 --周洋@北京-360

    

34  非关键日志,udp直接扔  --谭俊青@途牛

    

35  写磁盘,靠异步这神油不可能解决根本问题  --于雨@北京

    

36  是啊,异步加个队列只是缓解峰值写造成的堵塞  --神仙@上海|杭州-有赞

    

37  udp->udp server(开大点的buffer,也可以做负载均衡)->mq->…  --谭俊青@途牛

    

38  udp->udp server->kafka->es  --于雨@北京

    

39  udp扔过去注意下Incast Congestion  --毛剑@上海-bilibili

    

40  不行的,需要udp server 可以极大程度降低丢包率  --谭俊青@途牛

    

41  upd最大的问题就是buf要开大  否则就丢包。  --金灶沐@北京-康复中心

    

42  uber那个log库不错,就是写法太别扭  --于雨@北京

    

43  可以在发送端做winodow size,类似tcp流控  --毛剑@上海-bilibili

    

44  我这边有用udp server,几乎不丢包,buffer够大   udp packet -> udp server -> nsq -> ...   --谭俊青@途牛  

    

45  tcp的华东窗口就是保证数据可靠性。retry  --金灶沐@北京-康复中心

    

46  暂时还在用毛老师拉的log4go的分支   --于雨@北京

    

47  做window size 性能就下去了,还不如直接用tcp  --谭俊青@途牛  

    

48  udp搞好了,内网情况下10000个包丢三四个正常,不可能有啥影响 正常情况下,不加大buf   --于雨@北京

    

49  但是他们的信息要求准确度非常高也没办法  --金灶沐@北京-康复中心

    

50  10000 丢3-4个还不高啊?  --谭俊青@途牛 

    

51  @谭俊青@途牛 看场景如果仅仅是accesslog,算pv,uv丢几个无所谓  --郭军@360

    

52  sndbuf和rcvfuf开成2m,基本上就100%了 不过延迟会比较大  --于雨@北京

    

53  github.com/thinkboy/log4go   --Ryder@厦门-玩美

    

54  推荐个我的https://github.com/blackbeans/log4go  -- Beta版厨子3.0

    

55  log4go现在源代码都有问题啊  --宋慧庆@北京

     

56  不是有问题,是我按我的需求加了些东西  -- Beta版厨子3.0

    

57  Debug实现极其烂  整体总结下就是辣鸡 没有条件分支优化 Debug,模块日志都成本极其高   我们都不用本地日志了  --毛剑@上海-bilibili


58  我们也不用  最早长连接   去写异步kafka 后来udp server   短连接不行就长连接。。长连接不行就upd  fmt 到 kafka    kafka消费   你信不信我们都这么做了  --金灶沐@北京-康复中心


59  那日志不落盘了?  --Xargin@北京-didi


60  log4go不好用,我们公司自己写了一个https://github.com/antlinker/alog 一直在用  --于鹏飞@济南-蚁动


61  我们日志分种类 落啊 我们有几种日志。这是其中一种。。 --金灶沐@北京-康复中心


62  毛老师,你家的log4go,输出到term的没有receiver提示,debug日志有,能不能改改 貌似行号也没有 --于雨@北京


63  我们内部有版本  早不维护了 我们不用本地日志  目前udp kafka也不用  flume直接sink给需要的hdfs,或者es啥的  除非需要分析,才给Kafka   --毛剑@上海-bilibili


64  我们游戏里面的所有玩家行为日志都是扔到Kafka里面  --kyle@成都-风际游戏


65  消费不代表没有后续工作啊。。 任何不都要跟业务需求挂钩吗? 我们真正的日志落地的  而且到hdfs上   定时落进去。我们kafka也是做核心数据跟踪    --金灶沐@北京-康复中心


66  恩 这样还是挺好 但是看过普通的系统日志什么的 怎么方便?  比如debug log  --宋慧庆@北京


67  现在也不是直接用Kafka了,基于Kafka开发了数据总线,把Kafka协议屏蔽咯,提供了redis pub/sub实现,方便其他需要接入,同时做鉴权   --毛剑@上海-bilibili


68  debug log不会大到影响io性能吧  --kyle@成都-风际游戏、


69  不用kafka后端flume的sink如果挂了,就可能撑爆flume了。。  -- Beta版厨子3.0


70  从没挂过 flume有fallback  可以打本机 然后再用我们自己开发的Retail追踪收集 多flume节点  或者/dev/shm --毛剑@上海-bilibili


71  我们搞过 恩fallback配置了 就是先内存通道再到文件。到文件就已经说明sink慢了。。   主要还是用kafka起到缓冲的作用。。 -- Beta版厨子3.0


72  你们是thrift协议连的flume么  -- Beta版厨子3.0


73  syslog logview以后越来越少用才对,应该用链路追踪系统  --毛剑@上海-bilibili  


74  现在用go进行hdfs hbase之类的都是通过thrift协议连的吧  --宋慧庆@北京


75  我们维护了一个hbase client分支  原生实现,各种搞zk,meta 缓存,region迁移啥的代码写了挺多。细节让yonka讲讲  --毛剑@上海-bilibili


76  醉了……只有统计类的日志走Kafka,其他的是写到磁盘上备份而已。为啥要搞这么复杂?  而且前面说微信的…我现在就在生产机上,没有见到代号啊……   --蒙卓@深圳


77  想有集中的日志平台做查询吧 --Xargin@北京-didi


78  腾讯我在的时候确实是一台一台上去捞日志  -- Beta版厨子3.0


79  如果日志量太大的话,做收集不会影响到网络IO么 --Xargin@北京-didi


80  @蒙卓@深圳 互娱的外网游戏运营收集也是udp  --毛剑@上海-bilibili


81  我们是都放在hadoop上了  自己开发的分布式日志收集组件,最后都打到hdfs上  --郭军@360


82  实时收集对网络影响有限,定时收集影响才大。如果实时收集对网络都有影响了,只说明日志打太多了。  --王渊命-bj-Qingcloud


以上是关于golang 用golang处理Github webhooks的主要内容,如果未能解决你的问题,请参考以下文章

golang处理json

Go 每日一库之 go-carbon,优雅的golang日期时间处理库

json库在golang中的使用

用golang 实现一个代理池

Golang操作mysqlx库处理MySQL数据库

golang rbac框架