本文目录一览:
- 1、LiteIDE使用
- 2、Golang项目部署3,容器部署
- 3、Go 1.8使用Protocol Buffer
- 4、阿里云 CentOS 7.6 yum 安装 go(golang) 语言环境
- 5、Supervisor与Logrotate
- 6、WebSocket+SLB(负载均衡)会话保持解决重连问题
LiteIDE使用
LiteIDE是一款开源,跨平台的轻量级Go语言集成开发环境。操作简单,提示迅速!当然不足之处也有很多,不过除了golad之外,个人觉得比vscode,eclipse等用的更舒心一点(ps:指的是编写golang,每个人的感受不一样,勿喷)
目前本人使用的LiteIDE版本号是:x36.1
其中让我感受不是很好的两个点是:1.没有自动go lint检测,需要手动。2.更改键盘映射不能捕获按键的内容,需要自己粘贴复制比方说Ctrl+C之类的上去,如果不能接受这两点需要考虑考虑。当然也有可能是我玩的不够透彻,如果有人知道,请评论告知,感激不敬:)。
那么,接下来就让我们来学习一下LiteIDE这款国人开发的编辑器的简单用法:
当我们使用一款IDE的时候,首先当然是配置一下环境,其次是快捷键,界面布局之类的了。所以,我们先来
1.配置环境:
LiteIDE给我们提供了多种的环境,目的是为了让我们能将程序编译成不同的系统所能执行的文件,例如我目前使用的是windows64系统,而且我的服务器也是windows64,那我只需要选择system的环境就可以,这样在我执行编译执行后,编译器将会自动生成windows中可执行的.exe文件。
1.1配置管理GOPATH/Modules/GOPROXY
在我们项目是需要使用GOPATH或者是Modules的时候可以点击旁边的倒三角选项,on表示使用mod,off表示不使用,auto表示根据检测,有的话使用。
底下的GOPROXY可以设置代理,毕竟我们大中华的墙不设置代理还是很给力得。设置代理得另外一种方法是点击 工具-编辑当前环境,然后在里面输入代理,我一般用得是阿里云得代理:GOPROXY=,编辑当前环境得作用其实就跟我们在命令行中输入go env然后去设置是一个道理。
2.设置快捷键
点击查看-选项-LiteApp中点击键盘,然后就可以设置快捷键了,当然目前我这个版本需要粘贴复制进去
3.使用
3.1现在我们一般都是使用mod来管理,当然首先要设置GOPATH了。
将自己本地得GOPATH添加进去就可以了,如图所示可以添加多个。
3.2编辑器自动生成go.mod文件
点击M键,会弹出下拉菜单,选择go module init将会自动生成mod文件
3.3获取第三方包
可以使用M里面得go mod tidy也可以使用G键里面得Get按钮
目前记起来得就这么多,后续想起来后再添加。::)
Golang项目部署3,容器部署
容器部署即使用 docker 化部署 golang 应用程序,这是在云服务时代最流行的部署方式,也是最推荐的部署方式。
跨平台交叉编译是 golang 的特点之一,可以非常方便地编译出我们需要的目标服务器平台的版本,而且是静态编译,非常容易地解决了运行依赖问题。
使用以下指令可以静态编译 Linux 平台 amd64 架构的可执行文件:
生成的 main 便是我们静态编译的,可部署于 Linux amd64 上的可执行文件。
我们需要将该可执行文件 main 编译生成 docker 镜像,以便于分发及部署。 Golang 的运行环境推荐使用 alpine 基础系统镜像,编译出的容器镜像约为 20MB 左右。
一个参考的 Dockerfile 文件如下:
其中,我们的基础镜像使用了 loads/alpine:3.8 ,中国国内的用户推荐使用该基础镜像,基础镜像的 Dockerfile 地址: ,仓库地址:
随后使用 " docker build -t main . " 指令编译生成名为 main 的 docker 镜像。
需要注意的是,在某些项目的架构设计中, 静态文件 和 配置文件 可能不会随着镜像进行编译发布,而是分开进行管理和发布。
例如,使用 MVVM 模式的项目中(例如使用 vue 框架),往往是前后端非常独立的,因此在镜像中往往并不会包含 public 目录。而使用了 配置管理中心 (例如使用 consul / etcd / zookeeper )的项目中,也往往并不需要 config 目录。
因此对于以上示例的 Dockerfile 的使用,仅作参考,根据实际情况请进行必要的调整。
使用以下指令可直接运行刚才编译成的镜像:
容器的分发可以使用 docker 官方的平台: ,国内也可以考虑使用阿里云: 。
在企业级生产环境中, docker 容器往往需要结合 kubernetes 或者 docker swarm 容器编排工具一起使用。
容器编排涉及到的内容比较多,感兴趣的同学可以参考以下资料:
Go 1.8使用Protocol Buffer
最近在写一个在线客服模块,秉着简单,可控,可维护,可扩展,满足需求的原则,找了一个开源项目: 。
当然对于原始项目,肯定还是需要一些改动的,比如:鉴权,用户体系,文件类型消息的处理(存在阿里云OSS上)等等。
为了满足需求,修改了原始的基于protocol buffer的message,修改后在重新生成对应的go文件时候,遇到了一些问题,可以参考以下解决方法。
github上的protobuf( )已经说明,需要使用: google.golang.org/protobuf 。
安装官方文档 安装对应的插件模块,mac需要在.zshrc文件添加以下内容:
以下是message proto文件:
执行以下命令生产对应的go文件:
阿里云 CentOS 7.6 yum 安装 go(golang) 语言环境
前言:记录下安装过程以便下次有需要无需百度!
输入 yum search golang
Supervisor与Logrotate
在golang的gin项目中使用supervisor守护进程,用子进程配置将标准输出日志转移到指定目录下,然后使用阿里云的日志服务将标准输出日志转移到线上做一些分析和预警。
项目上线之后一切正常,可是周日夜里三点左右阿里云的日志服务采集不到日志,一顿pv为0的告警过来,赶紧打开电脑,线上服务正常,松一口气,supervisor状态也正常,观察了一会业务数据正常就安然入睡了,心想可能是因为配置项有缺陷吧,回头好好整整supervisor的配置再观察一波。
早上起来打开服务器,cd /var/log/supervisor/,发现存在两个日志文件,分别是xxxx.log-20201223和xxxx.log,xxxx.log的大小为0,xxxx.log-20201223还在继续写入请求日志,权限问题?chmod 777之后发现新的文件还是不写入日志,重启 supervisor之后发现日志能正常写入了。。。一开始怀疑是supervisor日志切割备份有问题,将配置stdout日志文件大小的stdout_logfile_maxbytes配置项,默认 50MB改成0,代表无限大,stdout日志文件备份数的stdout_logfile_backups配置项,默认10改为0,代表不备份,重启supervisor,心想不切割总不会再出现切割之后不往新文件写内容的问题了,真乃明智之选。:)
一周过去,0pv的告警如期而至,虽然不影响线上业务,如鲠在喉让我久久不能释怀。全网翻,百度谷歌,中文英文,去github上翻issue等等,看到一个历史issue1090,Better support for logrotate,感觉和日志转储相关,于是查了下logrotate相关资料,logrotate程序是一个日志文件管理工具。用于分割日志文件,删除旧的日志文件,并创建新的日志文件,起到“转储”作用。centos系统默认安装,于是找到对应的配置文件,果不其然里面就有supervisor,默认配置如下:
/var/log/supervisor/*.log {
missingok
weekly
notifempty
nocompress
},看到weekly感觉离这个问题的答案不远了,于是去查找linux的logrotate往旧文件写入的问题,在一篇logrotate writing to old app.log.1 instead of app.log的文章中找到需要配置参数copytruncate,是用于还在打开中的日志文件,把当前日志备份并截断;是先拷贝再清空的方式,拷贝和清空之间有一个时间差,可能会丢失部分日志数据。增加完配置之后,为了快速验证结果,修改weekly为daily,第二天日志正常切割了,新的文件也正常写入了标准日志。至此问题解决。
linux的logrotate对于运维来说可能是常识,作为开发刚接触运维,只能慢慢积累了,工作之余看看相关的运维知识,尽量少采坑。
WebSocket+SLB(负载均衡)会话保持解决重连问题
写在最前面:由于现在游戏基本上采用全球大区的模式,全球玩家在同一个大区进行游戏,传统的单服模式已经不能够满足当前的服务需求,所以现在游戏服务器都在往微服务架构发展。当前我们游戏也是利用微服务架构来实现全球玩家同服游戏。
玩家每次断线(包括切换网络/超时断线)后应该会重新连接服务器,重连成功的话可以继续当前情景继续游戏,但是之前写的底层重连机制一直不能生效,导致每次玩家断线后重连都失败,要从账号登陆开始重新登陆,该文章写在已经定位了重连问题是由SLB引起后,提出的解决方案。
每次重连后,客户端向SLB发送建立连接,SLB都会重新分配一个网关节点,导致客户端连接到其他网关,重连失败。
会话保持的作用是什么?
开启SLB会话保持功能后,SLB会记录客户端的IP地址,在一定时间内,自动将同一个IP的连接转发到上次连接的网关。
在网络不稳定的情况下,游戏容易心跳或者发包超时,开启会话保持,能解决大部分情况下的重连问题。
但是在切换网络的时候,手机网络从Wifi切换成4G,自身IP会变,这时候连接必定和服务器断开,需要重新建立连接。由于IP已经变化,SLB不能识别到是同一个客户端发出的请求,会将连接转发到其他网关节点。所以使用TCP连接的情况下,SLB开启会话保持并不能解决所有的重连问题。
另外某些时刻,手机频繁开启和断开WI-FI,有时候可能不会断开网络,这并不是因为4G切换WI-FI时网络没断开,从4G切换到Wi-Fi网络,因为IP变了,服务器不能识别到新的IP,连接肯定是断开的。这时候网络没断开,主要是因为现在智能手机会对4G和Wi-Fi网络做个权重判断,当Wi-Fi网络频繁打开关闭时,手机会判断Wi-Fi网络不稳定,所有流量都走4G。所以网络没断开是因为一直使用4G连接,才没有断开。想要验证,只需要切换Wi-Fi时,把4G网络关闭,这样流量就必定走Wi-Fi。
上面说过,四层的TCP协议主要是基于IP来实现会话保持。但是切换网络的时候客户端的IP会变。所以要解决切换网络时的重连问题,只有两个方法:1. 当客户端成功连接网关节点后,记录下网关节点的IP,下次重连后不经过SLB,直接向网关节点发送连接请求。2.使用 SLB的七层(HTTP)转发服务。
当客户端经过SLB将连接转发到网关时,二次握手验证成功后向客户端发送自己节点的IP,这样客户端下次连接的时候就能直接连接网关节点。但是这样会暴露网关的IP地址,为安全留下隐患。
如果不希望暴露网关的IP地址,就需要增加一层代理层,SLB将客户端请求转发到代理层,代理层再根据客户端带有的key,转发到正确的网关节点上。增加一层代理层,不仅会增加请求的响应时间,还会增加整体框架的复杂度。
阿里云的七层SLB会话保持服务,主要是基于cookie的会话保持。客户端在往服务器发送HTTP请求后,服务器会返回客户端一个Response,SLB会在这时候,将经过的Response插入或者重写cookie。客户端获取到这个cookie,下次请求时会带上cookie,SLB判断Request的Headers里面有cookie,就将连接转发到之前的网关节点。
HTTP是短链接,我们游戏是长连接,所以用HTTP肯定不合适。但是可以考虑基于HTTP的WebSocket。
什么是WebSocket?
WSS(Web Socket Secure)是WebSocket的加密版本。
SLB对WebSocket的支持
查看阿里云SLB文档对WS的支持,说明SLB是支持WS协议的,并且SLB对于WS无需配置,只需要选用HTTP监听时,就能够转发WS协议。说明WS协议在SLB这边看来就是一个HTTP,这样WS走的也是七层的转发服务。只要SLB能够正常识别WS握手协议里Request的cookie和正常识别服务器返回的Response并且往里面插入cookie,就可以利用会话保持解决重连问题。
Go语言实现WS服务器有两种方法,一种是利用golang.org/x/net下的websocket包,另外一种方法就是自己解读Websocket协议来实现,由于WS协议一样是基于TCP协议之上,完全可以通过监听TCP端口来实现。
客户端发送Request消息
服务器返回Response消息
其中服务器返回的Sec-WebSocket-Accept字段,主要是用于客户端需要验证服务器是否支持WS。RFC6455文档中规定,在WebSocket通信协议中服务端为了证实已经接收了握手,它需要把两部分的数据合并成一个响应。一部分信息来自客户端握手的Sec-WebSocket-Keyt头字段:Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==。对于这个字段,服务端必须得到这个值(头字段中经过base64编码的值减去前后的空格)并与GUID"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"组合成一个字符串,这个字符串对于不懂WebSocket协议的网络终端来说是不能使用的。这个组合经过SHA-1掩码,base64编码后在服务端的握手中返回。如果这个Sec-WebSocket-Accept计算错误浏览器会提示:Sec-WebSocket-Accept dismatch
如果返回成功,Websocket就会回调onopen事件
游戏服务器的使用的TCP协议,是在协议的包头使用4Byte来声明本协议长度,然后将协议一次性发送。但是在WS协议是通过Frame形式发送的,会将一条消息分为几个frame,按照先后顺序传输出去。这样做会有几个好处:
websocket的协议格式:
参数说明如下:
阿里云的SLB开启HTTP监听后,会检查过往的Request和Response请求,收到服务器返回的Response后,会往Response插入一个Cookie
客户端收到服务器的Response后,可以在Header中查到有个“Set-Cookie”字段,里面是SLB插入的Cookie值
客户端断开连接后,下次发送请求需要往Headers插入Cookie字段
分别在阿里云的两台ECS实例上部署WS服务器,打开8000端口,开启一个SLB服务,SLB服务选择HTTP方式监听,并且打开会话保持功能,Cookie处理方式选择植入Cookie。Demo服务器没有做HTTP健康监听的处理,健康检查这块可以先关掉。
在两台ECS上启动WS服务器,然后本地运行客户端,分别测试两台服务器是否能正常连接,测试完毕后,测试SLB能否正常工作。服务器和SLB都正常的情况下,运行客户端,客户端会得到以下结果
收到的三次Cookie都相同,说明Cookie是有正常植入工作的,并且三次都被SLB正确抓取了。
收到的三次serverId也都是同样的值,说明三次都是同一个ECS上的服务器响应。
至此,验证成功。
Websocket+SLB会话保持能够解决超时重连和切换网络时重连的问题。
参考:
阿里云会话保持
解答Wi-Fi与4G网络切换的困惑
WebSocket的实现原理
阿里云SLB对WebSocket的支持
HTTP Headers和Cookie