内容简介:前言:平滑上线的问题
前言:
换了份新工作,又是一个新的开始。正题开始, 最近在折腾golang的部署及平滑上线,写了几年的golang项目了,按道理来说很简单平常的事情,但在我们这有些小麻烦了
平滑上线的问题
先说下平滑上线的问题,阿里云的slb想来大家应该都用过。aliyun slb跟nginx upstream最大的区别在于不支持next_upstream方法。nginx next_upstream的参数控制当某节点不可用时,nginx会调度到下一个可用节点,不停尝试直到访问成功或者next_upstream_timeout超时中断。
换句话说,nginx upstream默认不加插件是被动检测api可用的过程,而像阿里云的slb是主动探测,这个跟haproxy是一样的,检测完了后,才会刷新可用节点列表。
如果slb的检测间隔是5s,某节点当前是可用的,距离下次探测之前节点突然不可用,那么这段时间窗口期内,slb还是会把请求转发到该节点,那么请求肯定是异常了。 当然你可以把检测间隔调成1s,顶多就失败1s。
如何在现有的条件下,进行平滑上线启动,优雅上线,尽量减少异常? 因为是个新业务,后面会频繁上下线,如果不解决该问题会导致丢失任务,虽然有多方的重试,不会真的丢失数据,但时不时的微信告警让人厌烦。所以,我们要做的只是 尽量减少失败 罢了 !!!
以前怎么解决平滑上线?
直接操作阿里云的slb api,删停节点,后面的请求自然就不走被删停的节点,我们就可以升级该节点了(当然,你的服务本身也要做好优雅退出,不能kill就退出)。如果不选择用slb api删除节点,而是把权重配置为0,那么新请求新连接就不会去该节点,但是老请求还是会过来,直到连接的关闭,所以单纯配置权重不是很稳。
那么现在怎么玩?
上海的ops不会给提供slb的api。我想到的方法很简单,我们知道阿里云的slb需要节点提供一个/ping接口,主要http code是2xx就可用。那么我们可以这样,升级一个服务之前,先触发一个信号,把/ping的返回状态重置异常,然后等待slb的探测间隔的时间,这个期间slb会下发一波探测,你的/ping不可用,自然就标记为异常,下次不会再转发,这时候你就可以升级了。升级后,ping为正常的200。
下面是控制服务的 shell 脚本,这提取了stop部门。逻辑很简单,先发送sigusr2信号,等待5秒,然后再去kill信号,如果20秒内还没有优雅退出,就强制kill -9干掉。
// xiaorui.cc ... function stop() { check_pid running=$? if [[ $running -eq 0 ]];then echo_info "$PROJECT is not running, don't need stop" return fi pid=`cat $PIDFILE` if [[ "$pid" -gt 0 ]]; then echo_info "$PROJECT will close ping api..." kill -USR2 $pid # 关闭ping接口 sleep 5 kill $pid echo_info "$PROJECT will stop srv..." else echo_panic "not found ${PROJECT} pid" return fi c=0 while true do if [ $c -gt 20 ];then echo_info "ensure force kill -9" kill -9 $pid >> $STDOUT 2>&1 break fi echo_info "get status since $c seconds" check_pid running=$? if [ $running -gt 0 ];then sleep 1 let c++ continue .... } ...
下面是 Golang的监听信号及修改 /ping 返回的逻辑。代码很简单,就是注册sigusr2信号及回调方法。回调方法就是修改一个对象,表示是否要关停ping接口。如果关停,返回非200状态。
// xiaorui.cc // kill -USR2 ${pid} func ClosePingAPI() { c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGUSR2) go func() { for range c { router.ClosePingAPI() tool.Log.Info("recv signal sigusr2 for close ping api") } }() } func (r Router) ping(q *gin.Context) { if PingStatus { q.JSON(http.StatusOK, types.Common{Code: 0, Message: "success"}) } else { q.JSON(http.StatusNotImplemented, types.Common{Code: -1, Message: "active ping api is already closed"}) } } func ClosePingAPI() { PingStatus = false }
jenkins上线部署问题
说下,我以前公司golang上线打包方式的三种方式。
第 一种:
基础架构组件,使用rpm打包,推送到yum仓库,然后进行部署。
第二种:
使用 docker 容器打包,继而推送到docker私有仓库,然后进行部署。
第三种:
根据你的项目的不同,如果你是golang的项目,他会帮你构建GOPATH路径,很方便就可以完成打包上线。
由于网络区域问题,暂时不能使用docker的方法上线。 rpm打包适合基础组件,我这类偏业务的系统肯定不能用rpm了。那么就剩下第三种了,问题来了。。。
大家的golang项目中的import路径多是全路径, 第三方的包我们可以通过dep扔到vendor目录里。但是jenkins的部署逻辑是这样,你先在页面选择项目及分支,jenkins会异步的把你的git代码pull到jenkins机器的一个目录里,比如 /data/jenkins/。你的项目名是 featrue_gateway,那么在jenkins目录就是 /data/jenkins/ featrue_gateway 。你怎么指定GOPATH来build代码?
以前公司的运维们针对golang项目在一个路径排列,比如你的项目是 http://git.xiaorui.cc/machine/featrue_gateway, 那么 在编译机也就是jenkins里路径是这样的 /data/jenkins/go/src/git.xiaorui.cc/machine/featrue_gateway, 对于我们来说,只需要相对路径的指定gopath就可以了。
// xiaorui.cc import ( "git.xiaorui.cc/machine/featrue_gateway/libs/pidfile" "git.xiaorui.cc/machine/featrue_gateway/libs/primary_ctl" "git.xiaorui.cc/machine/featrue_gateway/libs/connect_pool" .... )
就这个问题跟上海的ops来回扯了好几次。后来想想,为毛非要依赖他的路径?干脆我在当前路径下,设立一组路径,./tmp/go/src/git.xiaorui.cc/machine/feature_gateway/…,我makefile只需要gopath到当前路径的tmp就可以了。
// xiaorui.cc rm -rf tmp tmp_path=tmp/src/git.xiaorui.cc/feature-gateway/machine mkdir -p $tmp_path cp -rf `ls . | grep -E -v "^(tmp)$"` $tmp_path cp -rf scripts/deploy/control.sh ${PROJECT_PATH}/ cp -rf scripts/deploy/init.sh ${PROJECT_PATH}/ cp -rf scripts/deploy/feature_gateway_logrotate.conf ${PROJECT_PATH}/ # real build export GOPATH=`pwd`/tmp; go build -ldflags "-X main.BuildTime=${BUILD_TIME}" -o ${PROJECT_PATH}/feature_gateway cmd/feature_gateway.go
总结:
遇到的这两个问题,看起来是由于运维同学支持不给力导致的,但细想下大家都有难处,运维也有自己的职责规范,所以互相谅解吧。这样也促进我们去思考更多的解题思路。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Next.js脚手架进阶 —— 部署上线
- gitlab+jenkins自动化上线部署持续集成
- walle 2.0 预览版惊艳亮相,上线部署系统
- walle 2.0 预览版惊艳亮相,上线部署系统
- 利用rpm打包上线部署golang代码的方法教程
- 新星开源上线部署平台 walle 2.0 Alpha 更新大量
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Spark SQL内核剖析
朱锋、张韶全、黄明 / 电子工业出版社 / 2018-8 / 69.00元
Spark SQL 是 Spark 技术体系中较有影响力的应用(Killer application),也是 SQL-on-Hadoop 解决方案 中举足轻重的产品。《Spark SQL内核剖析》由 11 章构成,从源码层面深入介绍 Spark SQL 内部实现机制,以及在实际业务场 景中的开发实践,其中包括 SQL 编译实现、逻辑计划的生成与优化、物理计划的生成与优化、Aggregation 算......一起来看看 《Spark SQL内核剖析》 这本书的介绍吧!