原文作者:闫大伯
遇到的问题
连接池。由于PHP没有连接池,当高并发时就会有大量的数据库连接直接冲击到MySQL上,最终导致数据库挂掉。虽然Swoole有连接池,但是Swoole只是PHP的一个扩展,之前使用Swoole过程中就踩过很多的坑。经过我们的讨论还是觉得使用Golang更加可控一些。
框架的选择
在PHP中一直用的是Yaf,所以在Go中自然而言就选择了Gin。因为我们一直以来的原则是:尽量接近底层代码。
封装过于完善的框架不利于对整个系统的掌控及理解。我不需要你告诉我这个目录是干嘛的,这个配置怎么写,这个函数怎么用等等。
Gin是一个轻路由框架,很符合我们的需求。为了更好地开发,我们也做了几个中间件。
中间件——input
每个接口都需要获取GET或POST的参数,但是gin自带的方法只能返回string,所以我们进行了简单的封装。封装过后我们就可以根据所需直接转换成想要的数据类型。
封装之前
封装之后
中间件——logger
gin自身的logger比较简单,一般我们都需要将日志按日期分文件写到某个目录下。所以我们自己重写了一个logger,这个logger可以实现将日志按日期分文件并将错误信息发送给Sentry。
由于Gin是一个轻路由框架,所以类似数据库操作和Redis操作并没有相应的包。这就需要我们自己去选择好用的包。
Package - 数据库操作
最初学习阶段使用了datbase/sql,但是这个包有个用起来很不爽的问题。
上述代码,如果select的不是title,而是*,这时就需要提前把表结构中的所有字段都定义成一个变量,然后传给Scan方法。
这样,如果一张表中有十个以上字段的话,开发过程就会异常麻烦。那么我们期望的是什么呢。提前定义字段是必须的,但是正常来说应该是定义成一个结构体吧? 我们期望的是查询后可以直接将查询结果转换成结构化数据。
花了点时间寻找,终于找到了这么一个包——github.com/jmoiron/sqlx。
sqlx其实是对database/sql的扩展,这样一来开发起来是不是就爽多了,嘎嘎~
为什么不用ORM? 还是上一节说过的,尽量不用过度封装的包。
Package - Redis操作
最初我们使用了redigo【github.com/garyburd/redigo/redis】,使用上倒是没有什么不爽的,但是在压测的时候发现一个问题,即连接池的使用。
以上是定义了一个连接池,这里就产生了一个问题,在redigo中执行redis命令时是需要自行从连接池中获取连接,而在使用后还需要自己将连接放回连接池。最初我们就是没有将连接放回去,导致压测的时候一直压不上去。
那么有没有更好的包呢,答案当然是肯定的 —— gopkg.in/redis.v5
可以看到,这个包就是直接返回需要的连接了。
那么我们去看一下他的源码,连接有没有放回去呢。
可以看到,在这个包中的底层操作会先去connPool中Get一个连接,用完之后又执行了putConn方法将连接放回connPool。
结束语
3月21日开始写main,现在已经上线一个星期了,暂时还没发现什么问题。
经过压测对比,在性能上提升了大概四倍左右。原先响应时间在70毫秒左右,现在是10毫秒左右。原先的吞吐量大概在1200左右,现在是3300左右。
虽然Go很棒,但是我还是想说:PHP是最好的语言!(这句虽是原话,但小编持保留意见哈哈哈哈~)
版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。
Golang语言社区
游戏服务器架构丨分布式技术丨大数据丨游戏算法学习
领取专属 10元无门槛券
私享最新 技术干货