一个最佳实践分享:减少获取不变信息时可能会发生错误的影响

拟有一需求场景如下:为了监控服务器主机的运行状况,程序会定期采集主机上一些信息,例如磁盘、CPU使用情况等,同时获取主机名作为endpoint,以此标识采集的主机对象,最后将采集数据上传至监控平台。

明确一个前提,服务器主机名在采集程序运行期间是不变的。对于以上场景,本文只讨论一个点,如何获取主机名。问题似乎很简单,直接执行Go封装的系统调用函数os.Hostname()即可,so easy。但是,我们需要注意到os.Hostname()函数的返回值是两个,第二个返回值是error。这意味着,会存在获取主机名失败的情况。

讨论

1. 主机名是不变的,是否可以以初次调用os.Hostname()函数获取的主机值为准,存入全局变量hostname,后续均取此值。但是该方案存在问题:如果初次调用时,存在错误,endpoint就会为空,那岂不是此后所有的endpoint都为空了?

2. 既然主机名存在获取失败的情况,那么程序在需要主机名时,是否需要每次去调用os.Hostname()函数。但是这样频繁系统调用,有性能损耗,也没必要。

根据以上两种考量,最佳实践如下

 1package common
 2
 3import "os"
 4
 5var hostname string
 6
 7func Hostname() string {
 8    if hostname != "" {
 9        return hostname
10    }
11    h, err := os.Hostname()
12    if err != nil {
13        return ""
14    }
15    hostname = h
16    return hostname
17}

以上的核心思想就是,取第一次无错误返回的hostname作为全局变量。调用common.Hostname()时判断hostname是否已经被赋值,若已赋值,直接返回hostname,否则执行os.Hostname()函数,并判断是否给hostname赋值。

“我们往往不知道错误什么时候发生,也并不能保证程序永远正确”。但是,却可以用最小的代价(最开始执行os.Hostname()可能发生错误,造成hostname值为空)换取程序最稳定的运行(后续隐式取hostname值)。

总结

本文中的解决方案其实和单例模式很接近,比较好理解。

当程序获取某信息的过程中会发生错误,且该信息是不变项,则可以参照本文的处理方案。例如,读取不变的文件信息。

当然,细心思考的读者可能会提出重试方案:当获取信息时发生错误,就重新尝试获取。上述场景中,当然可以加上重试机制,但是一定要控制好重传超时和次数,不能因为当前时间段内的失败而阻塞在重传处,进而影响到整体的程序运行。

往期精彩推荐

Golang技术分享

长按识别二维码关注我们

更多golang学习资料

回复关键词1024

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值