Golang 在十二赞的深度应用

Golang 在十二赞的深度应用php

咱们是“十二赞”,一个致力于帮助电商卖家进入小程序的小团队,咱们的主页是http://www.12zan.cn/。在实际运行中,咱们使用了大量由golang写就的小工具,几乎每个工具代码量都超短,通常在200行左右就完成了一个独立的功能,同时担当了至关重要的角色;像代理服务器,代码量一共500行多一点点,倒是咱们的核心支柱,压测时QPS也直追nginx,表现优异。java

基于Docker的基础结构node

作为基础架构,我介绍一下咱们的机器架构。python

咱们的整个业务构建于阿里云之上,有5台server,每一对都有独立的外网IP,同时也在同一个内网之中。在每一台机器上都跑了一个咱们本身用golang写的守护进程,这个进程负责监听一些业务重启、新增域名等相似的指令并执行(这些指令最后都传递给了docker)。同时,每台机器上都有一个consul进程,这些consul都join到了一块儿。另外,咱们每一台机器上,都用docker跑了一个nginx来作80端口的服务,同时跑了一个用golang本身写的HTTP代理。nginx作作日志啊基础的功能以后就把请求丢给这个http代理 ,HTTP代理会到consul里去查应该将请求转发到哪一个IP的哪一个端口上。mysql

400行Golang代码写的HTTP Proxylinux

在架构选型的第一天,咱们就决定,咱们会服务化,会大量使用http 接口来提供服务,并使用本身的http proxy来分发请求、添加自有的一些业务逻辑好比API的权限验证等逻辑。咱们限定,全部业务,域名都是*.app.12zan.net,好比咱们要上一个聊天服务,请求的接口就会是chat.app.12zan.net,哪天再上个评论服务,请求的接口就是comment.app.12zan.net。nginx

肯定域名后我第一件事情,就是拿golang本身写了一个很是简单的基于consul的http proxy server;感谢Golang这完善的HTTP库,咱们只用了几百行代码就完成了全部功能。每当有http请求过来时,这个proxy server就会根据HTTP请求中HTTP_HOST 字段去consul去查,有哪些后端是用这个域名名称来注册服务的,并根据指定的算法,取出一台后端来,把这个HTTP请求Proxy过去。每一个具体的业务,可能运行在咱们5台机器中的任何一台之中的docker上,也多是多个docker实例上。因此这里有一个机制,选择哪一个实际的docker实例来服务这个请求的问题。咱们如今支持随机选取、按客户端IP地址作hash以后选取、按URL作Hash选取、按负载选取几种方式。laravel

WEB服务的服务注册git

基于php+laralel和nodejs+koajs两种场景,咱们制做了本身的docker镜像。这个镜像除开能够将php+nginx和nodejs构建的web服务运行起来以外,还包含一个golang写的consul客户端。在docker容器里,这个客户端随着php+nginx或是nodejs的web服务一块儿启动,启动以后会向宿主机的consul 进程注册本身这个服务,注册的时候会通知说,某某应用,在某某IP某某端口提供服务啦,若是前面有到**.app.12zan.net的请求你能够转发给我;同时会每隔一秒上报本身的进程数、当前机器CPU占用、内存占用状况。也是同样的简单,几百行golang代码,就鼓捣出了这个consul客户端。为何使用golang呢?第一个缘由固然是由于consul天生是golang阵营,第二个,是由于咱们的docker容器种类较多,因此这个客户端直接就是在Mac上跨平台编译出来的在linux64平台上运行的,无论docker容器是python为基准的仍是ruby为基准的,仍是nodejs的,只要把这个二进制文件拷贝进去就能正确运行,不像别的语言须要解决依赖问题。github

咱们还开发了一个web console界面,在这里,咱们能够注册app,也能够为app新增实例。注册app时,咱们要指定代码仓库的地址(对了,咱们的代码管理是用的golang写的gogs),指定对外服务的域名,指定是nodejs应用仍是php+laravel应用。添加应用以后,能够在这个应用下新建实例,让系统在指定的IP上去跑这个实例。实例运行的过程实际就是下发一个通知到某个机器上,去执行一个docker实例启动的过程。docker启动的时候带了一些环境变量,好比当前内网IP、docker监听的端口、对外提供服务时是用何域名提供服务。

日志和存储

前面这种架构有一个问题,就是后端多是在任何一台机器上运行的,今天多是A,明天多是B,那我要是把文件存在A上了是否是让B来提供服务的时候就挂掉了?因此咱们想了这么一个办法(也是由于穷。。。。),咱们把全部的文件都挪到阿里云的OSS服务上。同时为了避免管是Nodejs应用仍是php应用 仍是python写的应用都能作到把用户上传的文件或是系统生成的文件存到oss上面,咱们很省事地写了一个ossUploader,编译好的可执行文件发布,只须要执行它,传进来本地路径和oss上的目标路径,就保证给你上传到oss上去就完整,不须要再在nodejs、php、python、ruby、java各类平台下都琢磨一遍oss的SDK。

对日志的处理是同样的, 全部的日志文件的内容,都会被一个golang写的工具gtail监听着(就像linux 的tail -f命令同样),全部新产生的内容都会被gtail挪到oss上去存储。固然,也是可执行文件发布的。

这个实现以后, 咱们的实际业务就真正能够在5台机器上之间任意腾挪了。

消息广播

得益于golang的一些开源仓库,咱们还作了一些好玩的东西。

好比,看到https://github.com/gorilla/we...,咱们忍不住撸了一个websocket server,或是说叫群聊服务器更好一点。

接下来,咱们看到有一个golang的库叫go-mysql-elasticsearch,假装了一个mysql的slave,去MySQL的master机器上去读binlog,读到binlog之后就将MySQL里的数据发送给ElasticSearch去索引数据。

咱们就结合了一个,把这两个结合起来,修改了一下go-mysql-elastichsearch,让它监听到MySQL的数据变动以后,在WebSocket server的某个群聊里推送出来,造成一个数据变动的广播。

再接下来咱们就能够用nodejs写一个应用,连上这个websocket server,加入特定的某个群聊,就源源不断地收听到数据变动的消息。这个nodejs端的代码就很是简洁了,只须要不到100行代码能够作各类好玩的事情,好比监听到用户留言表有新增,能够发邮件让运营立刻去审核。还有好比说,每当订单表有成交的时候,咱们某个小小的nodejs应用由于监听了数据库消息,第一时间就知道了,立刻就去追溯用户来源,来计算返利;同时这个nodejs的代码更新是和订单主逻辑彻底不相关的,写这个业务的开发人员只须要知道订单表的结构,不须要了解订单应用后台代码。
【原文连接】

相关文章
相关标签/搜索