k8s笔记
k8s 笔记 这里记录一些常用但容易忘记的内容。
存储相关 ConfigMap 热更新 更新configmap后:
使用该configmap的环境变量和命令行参数不会触发更新。 使用该configmap挂载的数据卷会触发更新。 如果使用子路径(Subpah)方式挂载的数据卷,将不会触发更新。 PV(PersistentVolume) 与 PVC(PersistentVolumeClaim) 类似 Pod 与 Node 的关系,每个 PVC 可以与一个 PV 绑定。它们之间需要满足以下条件:
请求大小相同 StorageClass 相同 但是与 Pod 的不同处在于:一个 PVC 只能与 PV 一一对应(因为要求资源大小相等)。 使用 PV 我们让一个 POD 的存储得以持久化,通常来说我们都会配合 StatefulSet 来使用。当然,你完全可以通过 PV 让一个 Deployment 持有状态,但 StatefulSet 会更适合有状态的场景。 同时 StatefulSet 中还提供了 VolumeClaimTemplates 这样的字段来方便自动创建 PVC,配合 动态PV 可以轻松驾驭持久存储的体系。
一些 Tips:
预先创建 PV 再创建 PVC 绑定它们的这种方式被称为 静态PV,在 1.12 出现了 StorageClass 来完成自动创建 PV 的过程,被称为 动态PV。 StorageClass 是一个 CRD( 自定义资源 ), 它包含了如何访问数据源的一些细节,如参数,类型等等,为 动态PV 提供了支撑。在之前,这些信息都保存在 PV 中。 StatefulSet 删除时不会自动删除 PVC,需要用户手动删除,这是为了让用户能够恢复数据。其他资源则不会,如 Deployment。 杂项 client-go 中提供了很多有用的库:workerqueue(包含限速和延迟队列,多对多且并发安全), leaderelection, resourcelock(类似分布式锁) ServiceAccount 已弃用,ServiceAccountName 是最新项 每个 ServiceAccount 创建时都会自动生成一个 ServiceAccoutSecret,并且挂载到使用了 ServiceAccount 的 Pod 中 可以使用以下命令查看容器中的网络 docker inspect -f {{.
http和tcp连接小记
http和tcp连接小记 TCP 短连接与长连接 短连接与长连接的关键区分在于,是否复用TCP连接,短连接每次使用完毕都会释放连接,长连接则会将连接放入池中,等待下次使用。 所以实现长连接一般都会有几个关键参数:
最大连接数: 其实就是连接池中保存连接数上限 过期时间: 当请求数下降时,我们没有必要再维护这么多连接,所以我们需要给每条连接设置过期时间,当过期后及时从池中移除 在 http1.0 协议中,需要指定 Connection: keep-alive 来启用 TCP 长连接,http1.1 中已经成为默认值,无需指定,但是很多浏览器依旧会发送这个字段来兼容一些遗留的 web 服务。
这里可能需要区分另一个用于 watch 结果的实现方式,我们知道一般有三种方式: 短轮询, 长轮询, websockt,长轮询当中会把请求 hold 住一段时间,让其也变成了 http 协议上的长连接,但是并不是我们 讨论的 tcp 协议上的长连接
长连接消息的传输 传输编码:Transfer-Encoding, 内容编码: Content-Encoding 在长连接当中,由于连接不会断开,所以客户端无法知道消息是否已发送完毕,所以出现了 Content-Length 字段来告诉浏览器消息已传输完毕。但是很多情况下要计算出完整的响应体都是一件不容易的事情,为了计算出这个字段,我们需要把内容全部加载到内存中,这种实现非常不友好。所以出现了 Transfer-Encoding,一般为 chunked 代表分块传输。它不但解决动态内容长度的问题,同时还可以配合内容编码 (一般为 gzip or deflate or br,其中 br 是google 2013 产出的,具有更好的压缩效果,但是兼容性较差,很多库都尚未实现 ) 进行边压缩边发送而无需预先知道压缩之前的内容大小。
分块格式 如果一个HTTP消息(包括客户端发送的请求消息或服务器返回的应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。 每一个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),然后是数据本身,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有白空格(0x20)。 最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块不再包含任何数据,但是可以发送可选的尾部,包括消息头字段。 消息最后以CRLF结尾, 例子:
25 This is the data in the first chunk 1C and this is the second one 3 con 8 sequence 0 更详细内容参考:分块传输编码, HTTP 协议中的 Transfer-Encoding
Go语言笔记
go语言笔记 这里记录一些与 go 相关的点
GODBUEG 可以通过环境GODEBUG 来输出 go 程序的相关信息,可选命令如下:
allocfreetrace clobberfree cgocheck efence gccheckmark gcpacertrace gcshrinkstackoff gctrace madvdontneed memprofilerate invalidptr sbrk scavenge scheddetail schedtrace tracebackancestors asyncpreemptoff 完整命令参考 这里 值得一提得是,可以通过name=val,name=val来启用多个命令,如:
`` http库的 ServeHttp 不能修改 request 的内容 很有意思的一点,在 ServeHttp 代码注释中写着
Except for reading the body, handlers should not modify the provided Request.
稍微调查了下原因,是因为大量的现存代码会受到影响,所以在 http.StripPrefix 函数中,对 Request 进行了深拷贝。
func StripPrefix(prefix string, h Handler) Handler { if prefix == "" { return h } return HandlerFunc(func(w ResponseWriter, r *Request) { if p := strings.
git 小结
git 小结 常用命令
git remote -v: 查看绑定了哪些上游 git remote add {remoteName} {url}: 添加上游 git clone {url} [{newName}]: 克隆项目到本地,克隆后的仓库url会默认设置为 origin remote git stash push: 将修改存储暂存区,然后用 stash pop 取出,用于在不同分支间同步目录 git push [--delete] [--tags] [remote][/branch]: 推送到目标分支,加上 --delete 标记可以删除远端分支, --tags 标记表示推送 tag git fetch [remote]: 拉取远端更改到版本库,但不会同步到工作区 git merge [remote][/branch]: 合并到工作区,会形成一个merge的 commit 记录 git rebase [remote][/branch]: 合并到工作区,不会幸成 merge 记录,更干净 git pull [remote]: 拉取远端变更到版本库,同时 merge 到工作区,相当于 fetch + merge 子模块( Submodule ) 适用于想要同时修改两个有依赖仓库的场景。
git submodule add [url] [name]: 添加仓库作为子模块 需要注意的点:
CORS(Cross-Origin resource sharing) 踩坑笔记
CORS(Cross-Origin resource sharing) 踩坑笔记 CORS是一种为了解决跨域请求而诞生的规范,详细规范参见 MDN
这里只介绍下一些需要注意的点:
跨域问题只存在于客户端有安全策略限制的情况,典型的如:浏览器,此时安全策略会阻止你进行跨域访问。如果是自己编写的程序,没有安全策略的限制,则不需要考虑跨域,所以CORS通常是前端考虑的问题。 CORS有简单请求和需预检的请求区分,只有需预检的请求才会发起OPTIONS,两者的区分参考上面的MDN。 如果需要对凭据进行操作时,比如 携带了Cookie,此时需要设置Access-Control-Allow-Credentials: true,否则请求将会被浏览器拒绝。 在Access-Control-Allow-Credentials: true时,无法设置字段为通配符*。其他情况下任意字段都可以设置为通配符。这是因为允许携带凭据会带来安全隐患,浏览默认会拒绝 Ajax 的跨域请求,通常 CSRF 攻击只能通过 script 标签、form 表单 或者 有副作用的 GET 来完成,但是一旦开启了 Access-Control-Allow-Credentials: true,且不限制 Origin 等,那么会有更大的风险遭受 CSRF 攻击。 Access-Control-Max-Age各个浏览器的最大时长不一样, Firefox caps this at 24 hours (86400 seconds). Chromium (prior to v76) caps at 10 minutes (600 seconds). Chromium (starting in v76) caps at 2 hours (7200 seconds). Chromium also specifies a default value of 5 seconds.
自从核心工作转到后台以来,我就一直在摸索如何去构建更优雅,更容易维护的代码。在这几年的摸索中也渐渐沉淀了一些心得,进入现在的团队后又结合我厂的大环境和持续的思考,逐渐形成了现在较为成熟的一套理论,特此与各位同学分享,也作为一种知识记录。 本文会涉及到多方面的知识,所以我将其拆分了多个子文章,方便以后专项回顾和更,另外文章内容更偏向 Dev 的方向,Ops 内容较少,这是因为很多 Ops 的实践依赖于具体的部署平台,所以这里没有展开讨论
简述 在我们正式开始之前,我想先向大家展示我们已经做到了怎样的地步,又是如何帮助我们保证项目的质量的。
首先每个项目都配置了流水线,流水线触发条件有两个:commit push 和 tag push
两个动作都会触发流水线工作,但是会导致不同的行为,具体来说如下:
commit push:
验证代码是否能够编译通过 执行单元测试,验证单元测试率是否达标然后归档报告 执行 CodeCC 代码检查,验证代码是否符合规范( 安全性、性能、可维护性等 ),归档报告 输出消息到群机器人 tag push:
验证代码是否能够编译通过 执行单元测试,验证单元测试率是否达标然后归档报告 执行 CodeCC 代码检查,验证代码是否符合规范( 安全性、性能、可维护性等 ),归档报告 输出消息到群机器人 构建镜像且推送到镜像仓库 根据配置判断是否自动部署到 k8s 集群 (如果需要部署) 部署完成后输出消息到群机器人 对比下两者,可以发现 tag push 其实就是在 commit push 的基础上多出了 构建并推送镜像 和 自动部署 的步骤,其实它们之间的区别,正是 DevOps 中 CI 和 CD的区别,对 DevOps 不太了解的同学可能不知道什么是 CI 和 CD,不过没关系,正文里我会一一解释。
接下来我要解释以上这些步骤是如何帮助我们提高项目质量的。
验证代码是否能够编译通过
这是第一步,我们必须要确保推送到仓库的代码都是能够编译通过的,也是最基本的,相信谁都不愿意因为拉取了最新代码结果导致项目编译不了,而且还是由于别人的代码引起的,如果你要修复,那么你不得不去了解其他人工作的上下文。如果编译失败,那么会通知代码的迁入者。如下图:
执行单元测试,验证单元测试率是否达标然后归档报告
单元测试的重要性这里不过多解释,可以参考我在码客上的回答: 单元测试的必要性?由谁来写。 流水线会自动运行项目中的单元测试且统计覆盖率,如果覆盖率没有达到项目要求或者单元测试执行失败,都会在群里面通知代码迁入者进行检查,如下图: