前言目前我主攻golang。golang将作为主要的服务编写代码,所以会涵盖我所能接触的的绝大多数后端技术。另外,有两类问题我认为是超越语言的,不会在这里提及,一是关于代码设计模式和服务架构方面的问题,二是业务相关(包括通用的业务),比如token登录这种问题。大类上分为以下类别:
测试:单元测试,mock测试,request测试,性能测试 CI/CD: 主要是CI 常用框架五件套:web,数据库连接,配置,log,监控 文档编写工具 0. 从功能角度看需要什么工具总结下来发现内容有点多,所以只做简单介绍。针对其中的某些简单叙述不够或者文档未说明的点,后面单开文章描述。
测试: 单元测试,mock测试 CI: 持续集成工具 go-client: 适用于开发k8s operator的库 viper: config配置 gin: web框架 go-svc: golang包装器 gorm: mysql redis kafka etcd和zookeeper go routine和channel klog,glog: log库 sentry: 在线debug工具 swger,puml: 文档工具 测试我觉得相比开发来说,测试是更加重要的。
单元测试: 在一个多人开发项目中,我们有时很难知道别人的改动是否对我们这块的功能有影响,所以对于关键节点编写单元测试,并且把自动运行单测写入到CI中是至关重要的。看似增加了工作量,可从长期来看,是可以减少大量的功能测试时间,减少潜在风险的。
API测试:这个之前我用postman, 后来看到别的同事直接把测试案例用http里面,感觉是一种更好的办法。
1 2 3 ### cluster sync PUT {{host}} api/v1/cluster/sync/ Authorization: Bearer {{auth_token}} Mock测试: mock测试对于接口测试非常重要。设想一个场景:我需要获取一份数据,但是数据来源有多个,这种情况下我们可能会先编写一个接口用来隔离具体获取数据源的struct。我们如何在不编写实际数据源获取的struct的情况下测试方发是否有效呢,就可以用mock了。 CICI太重要了,第一是跟上面说的一样,可以很好的实现自动测试。此外,还可以配置一系列静态代码检查,格式化,检查函数复杂度等等。可以让我们的代码质量提升一个数量级。在多人开发系统中是必不可少的。
gitlab-ci 可以根据stage来编写流水线,当然,实际使用要复杂的多。多数情况会结合makefile来使用。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 build-job: stage: build script: - echo "Hello, $GITLAB_USER_LOGIN!
当年读书的时候,妈妈跟我说‘你这小子不好好读书,以后超市去收垃圾’。我心想收垃圾太辛苦了呀,‘我要好好读书,我要好好读书,我要好好读书’,心里想了三遍,奋而图强了一分钟,然后拿起旁边的橡皮,玩了一下午……所以很长时间,我怀疑自己脑子有问题。人家说的清清楚楚,自己理解的也是明明白白,不好好读书就要收垃圾,自己不想收垃圾,所以要好好读书,这不是很清楚吗?怎么就一点动力都没有呢?
于是我高中毕业那一年,放弃了考驾照(极度懊悔),主动应聘到超市收垃圾。第一天我就深深的怀疑了老母亲的说法,因为暑假想去超市收垃圾的不止我一个,以至于还要排队面试。我比马云幸运,第一次工作面试就很成功。我的职位是蔬菜水果收垃圾岗,主要负责把顾客挑剩下的烂菜烂水果收回到后面的垃圾桶。两个星期后,我再次质疑起了母亲,我感觉这个工作很有意思,至少比在教室里刷题有趣太多了。但我心想话不能说太早,可能是新鲜感。一个月后,我发现我是对的,这工作确实很有意思的。尤其是‘打称’,我工作的超市里的水果蔬菜都是没有贴标签的,需要有个人站在一个电子秤旁边,通过人眼来区分不同的蔬菜水果,然后,给这个蔬菜水果称重。比如,小黄瓜的编号是‘11365’,绿甘蓝的编号是‘23134’这样,在称上输入编号之后,会有一个标签条,我需要把标签条贴到蔬菜水果袋子上。你可别小瞧了这个事。难点有三,一是蔬菜水果种类太多,光是黄瓜根据产地不同就有六七种,有的黄瓜长得怪,你看着是A,其实它是个B,属实难分。二是顾客不好惹,打的速度慢了要骂人。三是有监督,收银柜的大妈每抓住一个错的就能领10块奖金,奖金哪里来呢,就是扣打称的。所以老员工都不愿意打称,我就成了倒霉蛋。
开始的时候,我特别难受。看着喜不自胜的大妈拿着打错标签的菜来到我面前,‘小伙子,你看看是不是打错了?’,气煞我也,于是我发奋图强。仅仅几天我就把所有的菜倒背如流,又过几天越打越快。一个月之后,我主动承担了所有的打称任务。倒不是因为我有受虐倾向,而是我发现其实全心全意‘打称’其实是一件特别爽的事情。我之前跟很多人说过这个体验,有的人完全无法理解。但我不知道你是否体验过心无旁骛,忘记时间做某一件事情时候的感觉,比如全心全意画画,弹奏乐器,写作,冥想或者写代码的感觉,当时的感觉就类似于这样。这是我人生中第一次做事情特别有动力。
三个月之后,我结束了这份工作,去上大学。我开始有了一种危险的想法,我不想读书了,我感觉浪费时间。尤其学校的老师在那念ppt的时候,我分外怀念在超市‘打称’的时光,我没有开玩笑。另一件麻烦事,伴随而来,我发现我长期以来的价值观被击碎了。过去的价值观是爸妈给的‘坐办公室体面幸福,超市收垃圾的人生很糟糕’,可现在我发现我竟然不反感在超市‘收垃圾’。我最无法接受的一点是,我隐隐觉得即使没上这个破大学,我去超市打工,我依然可能会过得很开心。即使是上了大学,我也很可能难以获得想象中的幸福。可如果这样的话,我前三年没日没夜的刷题考大学又图个啥,那我在大学教室里听秃头念经又图个啥?人生第一次,我体会到了虚无主义。
几年后,我还有点学生气,所以不吝于找人分享我在虚无主义上的体验和理解。渐渐的,我发现当年身为青年的我们,或多或少的都体会到了虚无的感觉。只是处理方式不同,方法有三,一是坚守,坚守老一辈价值观,坚持某种信念。二是遗忘,假装这个问题不存在。三就是很少的人了,坚持找个能自圆其说的答案。第三条路可真是不好走,这意味着要全面的重新审视自己过去的认知,挑战从小到大接受的三观,重新构建一套。面对虚无主义,有一个核心问题,那就是,人生到底有没有意义呀?
有人说,钱就是意义,可有钱未必开心。有人说开心就是意义,可当下的开心不代表长久地开心。有人较真说长久的开心呢?可长久的开心又如何去定义。有人说建功立业就是意义,可古今多少事,成败转头空。有人说人类的延续就是意义,可人类短短几十亿年的历史,出现是幸运,维系也可能只是幸运。任何的事情,总是咋一看很有意义,却经不起拉长看放大看。或许吧,没意义才是根本。佛家不早讲了,凡事‘缘起性空’。
时至今日,我深深感受到了世界的本质有’虚无’特质。我认为当代人更容易体会到这一点了,很难说这是一种幸运,还是不幸。幸运的是解决了饥饿温饱的问题之后,人才有了更多的可能理解这一点。我的父辈们多是60-70年出生的,经历过饥饿年代的他们很难理解这一点。当年我还曾试图让长辈理解我们这一辈的想法。比如去玩剧本杀,我跟长辈描述过这是个角色扮演游戏,目标是找出凶手云云。得到的回复是‘有什么毛病要玩这个?’。对于大多数60后,70后,我觉得是很难理解90后,00后的,他们有他们青年时候的意义。不幸的是解决了温饱的90,00后是很容易’虚无’一代人。而’虚无’真是一个很难对付的东西,所以时至今日我越发意识到有一个稳定的三观是多么的重要。我有时在想’虚无’的本质在哪里,我想是死亡,人总是要死的,时间总是有限的。从‘人总是要死的’这个角度讲,做任何事自然是没意义的。不是任何时代的青年都得受一遭虚无的考验。而我们这一代开始可能越来越多的人会意识到这个之前很多人忽视的东西。
我也曾意识到这并不是我们这代人才会发现的问题。空闲时,我有时会想,青年时候的释迦摩尼在树下冥思苦想的时候,是不是也想过‘怎么就是这么没意思?’,‘我这么费劲做这个事情有意思吗?’,‘躺着啥也不干是不是就有意思了?’ 。而同样的问题,圣人们,先知们,哲人们可能也在星空下苦苦纠结过。
前言在我的工作语言场景里,python主要扮演三种角色:
增强shell脚本的功能: 比如如果需要在机器上跑定时任务,这个任务是需要处理api调用的,python就比shell要好写 胶水命令工具: 简化手动操作命令。公司里面的系统通常会有很多协同问题,手动操作很繁琐,把命令打包可以缩短事故响应时间 算法题: python写算法题很方便,尤其是涉及到stack和queue,如果你对这个话题有兴趣可以看我的算法gitbook 本文将主讲第一和第二点,分解一下的话,主要有以下几个主题:
poetry构建 click 命令封装 subprocess多线程 requst api发送和处理 单元测试 git-ci的编写 poetry极力推荐用poetry来构建项目,poetry并没有搞出新的概念,但是很好的集成了过去的功能。主要是三个功能:
虚拟环境 python各种不兼容的情况太多,是离不开虚拟环境的。poetry有类似于conda的功能, 可以隔离不同的开发环境,好处是不用额外安装别的虚拟环境工具。 1 2 poetry env use python poetry shell 依赖管理 相比requirements.txt。更加的规范,并且可以通过lock来锁定配置。 1 2 3 poetry add 包名称 poetry remove poetry update 打包发布 1 2 poetry build poetry publish 工作流:
创建新的项目:
poetry创建虚拟环境—> poetry init初始化—>通过poetry管理依赖,导入包—>通过poetry build—->通过poetry上传到pypi
引入旧项目:
通过poetry install安装依赖—>poetry shell进入虚拟环境—>开发
和vscode整合
安装对应的插件: Python Poetry, Poetry Monorepo 在inerpreter中选中虚拟环境下的python Demo:
官方文档案例 clickclick是一个命令行工具,可以用装饰器来创建命令行,并且可以很好的支持子命令的嵌套。 Demo: 官方文档案例
前言刚开始工作时,看到同事们娴熟地输入各种Linux命令,有些人一条命令可以轻松输入三四行,流畅自如,让我觉得非常神奇。可是当轮到我自己时,总是记不住这个命令、那个参数。向他人请教,他们总是说多敲几次就熟悉了,但我总是不知道何时才能有那个“多”的机会。因此,我翻阅了各种Linux书籍,甚至看了好几本,但似乎仍然无法掌握。于是,我开始反思,直到有一天豁然开朗,开始轻松驾驭各种命令。我认识到的核心关键是:不要将Linux命令看作系统化的知识,而是要像背单词一样学习。
为何这样说呢?我和许多初学者交流过,由于大家在学校主要学习编程语言,很容易将学习编程语言的思维方式带入到Linux命令学习中,努力理解各种语法糖,试图构建一个完整的编码体系。但实际上,编程语言对应的应该是Linux脚本编程,而对于Linux命令来说,我们无法像写代码那样进行调试。而且由于历史原因,许多Linux命令功能重叠,使得整个体系变得复杂而庞大。在这种情况下,我们应该找出其中最实用的命令,刻意背诵常用的,然后学会查阅Linux文档(特别是man文档的专用格式),遇到不常见的命令要有查阅的能力。因此,一份真正的一线实战Linux命令手册变得至关重要,我在这里进行了总结。
掌握灵活的Log提取技巧由于现代监控系统和日志系统的存在,理论还是那个时候我们可以借由平台来查看日志和一些基本问题。但是日志平台通常不够灵活,所以常常需要我们手动提取一下日志来判断。那么问题来了日志格式有很多种,要怎么用一些常用的命令保证不论什么日志我们都可以快速提取我们想要的内容呢?
我总结两大使用场景:
提取 查找 提取根据我的经验,绝大多数的提取场景逃不过这7个命令的排列组合
wc head cut grep sort uniq awk tr wc
-l 是行数 -d 是字数 head
head -n 就是前几行 tail -n 是最后几行,和head相对应的 cut
cut -d ‘:’ -f 2-
-d就是以什么作为分割,-f就是field,要显示哪些分割后的部分, 2-就是第二个后面都显示 特殊情况,制表符分割要用$:
cut -d $’\t’ grep
grep 过滤出关键词 grep -v 不要这个关键词 sort 部分排序
sort -k5,5n
-k 5,5: 这部分指定了要排序的字段范围。在这个例子中,2,2 表示只考虑第二个字段,n代表看成数字 sort -S 500M –parallel=4 -T
–paraller是多线程,有时候文件太大了,可以用这个加速分割速度 sort -t ‘,’ -k2,2nr
-t的作用是分分隔符 uniq
sort| uniq -c 统计相同行,通常用于查出ip之后统计高频的, 常常跟sort一起用 awk
简介
client-go 架构图 本章可以在listwatch的基础上加入reflector, 并且把得到的值写入到第一章的deltafifo中,从而研究一把reflector。
demo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 func main() { //create config config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile) if err != nil { panic(err) } //create client clientset, err := kubernetes.NewForConfig(config) if err != nil { panic(err) } df := cache.NewDeltaFIFOWithOptions(cache.DeltaFIFOOptions{KeyFunction: cache.
简介
client-go 架构图
github client-go项目:
https://github.com/kubernetes/client-go
上文谈到了DeltaFIFO,通过demo实现了基本功能和进行了源码分析。接下来我来分析一把DeltaFIFO的上游Reflector。从架构图上我们可以看到Reflector通过List&Watch 来和k8s API进行沟通,然后把得到的数据写入DeltaFIFO。
搭建实验环境由于这次的需要和k8s api进行交流,我们首先要搭建一个简单的k8s master来进行实验测试。由于我是mac, 我只写mac命令,别的环境大同小异。
使用colima(docker-desktop也可以) 来搭建docker
安装kind
brew install kind
用kind搭一个k8s
kind create cluster –name your-fav-name
安装kubectl
brew install kubectl
构造demo还是上一篇的思路,先把组件拆出来构造一个demo了解功能。github 地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 func main() { //create config config, err := clientcmd.