Tech

grpc-go源码分析之logger

从上个月开始梳理grpc-go的源码,希望从中学习到一些来自谷歌“原汁原味”的代码设计及风格。第一个开始分析的包是encoding,这个包下的代码行数不多,主要就是如下两个部分 encoding/decoding compress/decompress encoding/decoding是直接使用了第三方的包「protobuf规范的Go实现」,笔者没有继续深入梳理第三方包的代码。 compress/decompress是使用了Go SDK的compress包,笔者也并没继续往官方包的方向看代码。 所以对于grpc-go的encoding这个包,grpc-go本身并没有自己实现编码/解码,压缩/解压缩的代码,而是调用其他包。所以这个包也没什么代码值得去分析。不过值得一提的是笔者在看这个包的注释时候发现了一个错误,后来提了PR,reviewer当时跟我争辩了几句(他认为没有错)。然而,最终我的PR还是被合并啦! 接下来进入正题,开始分析第二个包grpclog。在梳理这个包的过程中,恰巧我准备从0开始为一个开源项目贡献Go-SDK。截止文章分享时,这个Go-SDK的logger部分我已经编写完成,设计的风格几乎与grpc的logger无异。毕竟,学以是为了致用 😀 通过源码可以知道loggerWrapper已经弃用,loggerT和tLogger是为了单元测试和基准测试用的,所以本文暂不讨论这三种struct(为行文流畅易读,struct在后面统称结构体)。 因此下文主要从以下三点分析: glgger结构体 componentData结构体 初始化流程 glogger结构体 梳理所有grpc-go打印日志的方法(除了测试用的实现方法)会发现:尽管一些方法所属的结构体并不是glogger(一些是下面的componentData),但调用链最终还是会到glogger结构体所属的方法。最后,glogger结构体的方法使用了第三方包“glog”输出日志。 glog是谷歌在github上开源的日志类项目 通过梳理这些结构体的实现方法,还能发现duck-typing这种设计思想在Go语言中的使用,深深体验到这种简洁的设计风格所带来的便利性。简单来说就是当一个结构体的实现了一个接口的所有方法,那么这个结构体就实现了这个接口。以grpc-go举例说明: componentData结构体 首先,可以从componentData结构体实现的方法看出:它同样了LoggerV2接口,如下图: 以componentData结构体的InfoDepth方法举例,该方法作用主要有两点: 在每行日志前拼接调用该方法的微服务名称; 将指定的日志打印栈深度+1。 实际上大部分微服务的都是通过调用Info方法(指定了日志打印栈深度为1),来调用InfoDepth: 最后internal包里的方法会判断是否初始化了变量DepthLogger去执行真正输出日志的方法。至于变量DepthLogger是如何被初始化的,会在第三部分“初始化流程”中分析。先提前说明:这里被初始化进去的正是glogger结构体,所以最终由第三方包“glog”输出日志。 初始化流程...

Continue reading...

在阳春三月,开启一段新的学习之旅

在今年春节结束之际,给自己订了学习计划:包括阅读一些书籍和在线课程,其目的是为了提高Go的技术水平。昨天,学习进度到了这项计划的里程碑——50%,而我毅然决然地放弃了之前的计划,花了约一天的时间说服自己制定新的计划并开启一段新的学习之旅。 文章接下来的内容会记录昨天思想斗争的片段,供未来回首。若对正在阅读此篇文章的你有帮助/启发,那真是笔者莫大的荣幸。若跟你的观点相悖,忽略以下内容即可。 从Java工程师转到Go工程师已经过去五个月(对于非程序员读者可以这样理解:从英语翻译员转到法语翻译员),现在笔者自认为处在初/中Go工程师的水平。如果按照之前订下的计划继续学习,再花几个月的时间也仅是横向扩展了知识面,对于Go语言的深度认知还会是欠缺的状态,这跟我想达到的目标不一致。 笔者不想再踩下以前学习Java的坑:“对于一个编程语言本身的设计思想,官方标准库的方法以及其它等等基础知识还没熟练掌握,就开始学习各种框架,第三方中间件的使用“。这虽然有益于快速上手企业的业务代码开发,可无益于做一个编程风格优秀的程序员,也很难在各大论坛/社区与其他优秀的程序员“对线”。 “愿意花时间横向扩展,而不愿意花时间纵向深究知识“这种现象的产生我认为一部分来自于各大企业的招聘需求,希望求职者什么技能都掌握。其实能猜到企业会将愿意将大部分投入放到招聘业务开发的程序员,毕竟业务开发直接与收入挂钩。现在还真没有勇气在简历上用“精通A”替换“掌握A, B, C”,因为在各招聘网站上发布的职位还是以业务开发的多,负责框架/中间件/容器等这类专项研发的职位相对少些。 也许很多人(至少我以前就是)就会用这些招聘需求来决定自己的学习方向,花了很多精力做知识面的横向扩展,希望在和别人聊到某项技术的时候,自己多多少少能接得上话题。这也为接下来我要聊的内容做个铺垫: “面向企业编程”还是“面向兴趣编程” 目标 做好自己的兴趣,总会有欣赏你的人/企业? 自己的未来应该由自己决定 “面向企业编程“还是“面向兴趣编程” 这个问题放在三年前刚毕业的时候,毫无疑问我会选择“面向企业编程”,因为当时还不明确自己的目标。说实话,我现在选择“面向兴趣编程”还是会有一丝担心,毕竟当大部分人还是选择“面向企业编程”,对于那些在人潮中逆行的人来说应该都会有怀疑自己的时候。 企业的职位需求可以作为参考之一,但不应该为你的学习/发展方向做决定。这是我现在践行的学习/发展方式,至于我的选择是不是最优解,就留给时间来证明吧。 目标 人的时间都是有限的,所以得根据目标对时间进行取舍。如果你的目标是成为首富,那可能要将更多的时间留给赚钱;如果你的目标是成为大多数企业都青睐的对象,那可能要将更多的时间花在学习企业的需求。 对于完成我自己的目标,可以允许我把更多的时间放在我的兴趣上(我的兴趣现在就是精通Go,包括设计思想,标准库方法等)。我认为在IT行业中,细分到某一专业领域,如果你对这一领域很感兴趣,只要你的水平在第一梯队中。我觉得收入也不会比其他热门专业领域少很多,至少应该能过上相对自在的生活。虽然收入相对没那么多,但是过得自在、快活。 显然,我不是要做赚最多钱的程序员,是想做个喜欢编程的程序员。 做好自己的兴趣,总会有欣赏你的人/企业? 其实这个小标题我的答案也不确定,但很多文章/故事给出来的答案总是积极的。我想,在IT行业中,做好自己的兴趣,应该不会失业,即使失业也不会为一日三餐发愁吧? 自己的未来应该由自己决定 现在有很多IT行业的大佬为分享自己的经历,不妨一看,但无法也不能照抄。可以作为参考,然后制定一个自己的目标和一份成长规划。即便以后没能实现自己的目标,也不会埋怨自己照抄了别人的人生规划。: -D 其实我觉得,只要是一个态度积极的人并且认真的做了分析和计划,即便没实现目标,也不会差到哪里去。 最后,分享一下我新的学习之旅将从《The...

Continue reading...

使用map降低算法的时间复杂度

在前两周在开发新接口时,遇到了今天要介绍的两种场景,我都通过map降低了整个算法的时间复杂度。我认为有必要记录一下思考过程,也顺便分享给各位读者。虽然简单,但确实很好用。 1. 群组中的好友 背景 各位读者应该都知道在微信聊天框中输入@之后,会出现各群员的列表。新接口功能上差不多,只是在这基础上还要加上一个限制条件:“列表中的群成员必须是好友”。我可以从其他微服务已经有的“好友接口”获取某一个用户的好友列表(list),那么我只需要找出和群成员列表的交集即可。 实现 当时想到有两种方法可以实现上面说的效果(设群有N个群成员,M个好友): 采用两层遍历查询方式,遍历群成员list + 二分查找好友list(查询的时间复杂度:O(N * logM)) 采用map,将群成员id作为map的key,role作为value(查询的时间复杂度:O(1)) 哪种方式更好?通过时间复杂度来看,答案就不言而喻了。部分代码如下: // 获取群内成员(我的源码有用到role做别的业务逻辑处理) func GetMemberInGroup(groupID int64) (map[int64]int8, error) dataSet := make(map[int64]int8) strSql :=...

Continue reading...

结束Java工程师生涯,往新蓝海出发

一周前我入职了新公司,不再以Java工程师的身份。做出这个决定的难度可比写下这篇“看似吸引”的标题的难度大多了。除了想借此篇文章对上一份工作做一次总结,也想为自己留一份“记录”,用以回首这个职业生涯,甚至可能是人生的转折点。

Continue reading...

Java并发包工具类使用范式

用“等待-通知”机制优化循环等待 锁的获取与释放 无锁工具类 ThreadLocal 与内存泄露 终止线程 上周看完极客时间的《Java并发编程》课程,发现知识讲的通俗易懂,没有很多晦涩的用词,个人认为适合Java并发编程入门的读者。对于技术大牛,就别花这一百元去购买课程了,还是建议看回经典的“圣书”。此篇文章不会写过多关于课程的具体内容,笔者希望有兴趣的读者花钱去购买课程,创作不易,“花钱购买别人的知识”是个良性循环。 以下篇幅仅记录课程中提到的关于并发编程在实际工程中推荐使用的编程范式。范式,意味着是经典做法,所以没有特殊理由不要尝试换个写法。

Continue reading...

经典且简单的企业级生产环境系统架构

系统架构图 总体请求流程图 详细请求流向图 组件部署搭建步骤与配置 1. 服务器基础环境搭建 1.1 所有服务器创建robin用户 1.2 所有服务器授权robin用户 1.3 修复服务器主机名 2. Nginx安装及配置 2.1 安装Nginx 2.2 配置Nginx 2.3 启动Nginx 2.4 创建HTML存放目录 3. Redis集群安装及配置(哨兵模式) 3.1 安装Redis...

Continue reading...

使用抓包工具看网络分层

在学习小册《深入理解TCP协议:从原理到实战》的时候发现一个不错的抓包工具“wireshark”,借此篇文章做一下简介,顺便记录学习过程。 我将分层和一些主要参数的解释都表达在图片上了,就不再另作文字说明。通过抓包分析出来的信息,引用小册里的一段话: 纵观计算机和分布式系统,你会发现「计算机的问题都可以通过增加一个虚拟层来解决,如果不行,那就两个」 PS:以上是我在掘金写的文章,所以图片带水印。

Continue reading...

OAuth2

今天是清明假期最后一天,跟以往一样下起了细雨。天气越舒适,人的思绪就好像会越乱。年轻人和长辈的想法总会有出入,早上家人提出的话题被我草草结束。虽表面上结束了这个话题,但其实关于这个话题的联想一直脑海萦绕。还是写一篇技术博文冷静一下吧,生活上事情不提太多,毕竟这里是技术频道。 😀

Continue reading...