代码与注释

代码应该拥有良好的注释一直是业界共识,毕竟,在可预见的未来里,阅读代码的主要还是人。所有的语言都支持注释,有的拥有额外的注释提取工具及格式规范。但总体来说,大部分语言在这块做的都比较一般。Python有一些约定俗称的规范以及 Sphinx 这样的工具, Golang 的规范比较简单,但内置了 godoc 工具。Lisp 算是做的比较好的,示例如下: (defun small-prime-number-p (n) "Return T if N, an integer, is a prime number. Otherwise, return NIL." (cond ((or (< n 2)) nil) ((= n 2) t) ((divisorp 2 n) nil) (t (loop for i from 3 upto (sqrt n) by 2 never (divisorp i n))))) 其独特之处在于,不同于一般语言注释位于函数体之外,而是将其放置于函数 body 开始处。这样开发者更容易将其当作函数定义的一部分,也有助于养成良好的注释习惯。 Golang 虽然 在注释方面做的普通,但是在官方 library 以及最佳实践方面成功地鼓励了人们尽可能地写非常详细的注释,具体到一个 struct 的各个字段上。尤其是在 kubernetes 社区里面, 其Space Shuttle style 的 Code 对于社区的蓬勃发展可以说是一个极大的背后功臣,从如下的代码便可一窥其风格: // Adapts a ConfigMap into a projected volume. // // The contents of the target ConfigMap's Data field will be presented in a // projected volume as files using the keys in the Data field as the file names, // unless the items element is populated with specific mappings of keys to paths. // Note that this is identical to a configmap volume source without the default // mode. type ConfigMapProjection struct { LocalObjectReference // If unspecified, each key-value pair in the Data field of the referenced // ConfigMap will be projected into the volume as a file whose name is the // key and content is the value. If specified, the listed keys will be // projected into the specified paths, and unlisted keys will not be // present. If a key is specified which is not present in the ConfigMap, // the volume setup will error unless it is marked optional. Paths must be // relative and may not contain the '..' path or start with '..'. // +optional Items []KeyToPath // Specify whether the ConfigMap or it's keys must be defined // +optional Optional *bool } 可读性越好的代码越容易流行。Golang 在这方面做的很好。 ...

2019-07-14 · 2 分钟 · 356 字 · 涯余

Golang 1.9 Release Note

今天在翻存在 Pocket 里的文章,翻到一篇 Golang 1.9 的 Release Note。不得不说,Golang 在文档化上做的相当不错。对比其他语言来说,人们关注于每个版本的更新也会更多。不过这样的对比样本比较少,可能也不是很公正。Python 因为 2/3 版本的分离,可能很多人都不太关心 3 版本的更新。C/CPP 的文档一直比较欠缺,差距太大,而且版本之间迭代的也比较慢(历史包袱也多)。 现在 Golang 的版本已经到 1.13 了大概,2 的 design 也应该有不少文档。这样追下去应该有不少发现。利用语言的新特性来优化代码也是一件很有乐趣的事情。 1.9 新特性介绍 sync.Map 之前知道有这么个东西,但是自己在写代码的时候仍然没有将他作为一个默认的选项来考虑,仍然是自己加了 lock 手工实现,不得不说是一件很拙劣的事情。 type a struct { lock sync.RWMutex data map[string]interface{} } 再加上一些自己实现的get/set函数。现在用一个普通的sync.Map即可。注释上说了它有自己的适用场景: value 只写一次但是多次读 不同 goroutines 读写的数据不重合 即使这样,适用的场景还是挺多的。更少的代码,更好的性能,值得考虑。 Test Golang 的 Test 包也包含了很多比较少见的的功能。借助 1.9 的 Release Note 看了下,也都是很实用的。 test.Helper() 在测试中我们经常需要写一些 helper function,这些函数是服务于真正的测试函数。如果它们出错并且打印出来,只能显示到 helper function 的文件名和行号。比如我们自己实现一个 assert 函数,查看错误就很不方便。而test.Helper()就是为了解决这个问题,当在 helper function 中打印具体的错误时,会显示的是调用者的文件名和行号,如下面例子所示: ...

2019-05-27 · 1 分钟 · 206 字 · 涯余

作为公共组件的 apiserver

PDF 文件在此: apiserver 起因是因为一个要做一个新的项目,在综合考量 kubernetes 的各个库之后,发现 kubernetes 已经从主项目中把很多可以复用的项目都单独移出来了。而且包含了很多通用性很强的代码。作为以 Golang + Kubernetes 为核心的架构,这些代码基本上可以充当公司内部的公共组件,省去了很多重复工作。 大部分公司都很少有这个意识,去尽量做好公共组件这块。业务需求本身占用了太多时间,这种属于内部架构的问题基本都是靠零星时间来改善。Kubernetes 这些项目不是说多好,而是它作为一个极其其庞大的项目,在开发的过程中自己造的轮子一般的公司都会有类似的需求。研究,拆解,复用这些公共代码,能够很大程度弥补上公司里公共技术这块的缺失。 公共代码越多,项目的相似程度也越高,维护及使用也越简单方便。

2019-05-24 · 1 分钟 · 15 字 · 涯余

在 Kubernetes 中安装 Gitlab

现在很少写这种安装类的博客了。之前在公司部署了一个 Gitlab 作为日常使用,因为步骤比较繁琐。在此把零零散散的资料汇聚一下,记录一个比较完整的安装过程 环境 Kubernetes 1.13.1 三个高可用节点 每个节点上一个空余磁盘 步骤 安装 Rook Rook 提供了基于 Ceph 的分布式存储,我们利用每个节点上的空余磁盘来支撑 Kubernetes 里的 PV/StorageClass 等 Helm 安装 首先,初始化磁盘 mkfs.ext4 /dev/vdb mount /dev/vdb /var/lib/rook mkdir /var/lib/rook # TODO: add to /etc/fstab 然后通过 Helm 安装 Rook helm repo add rook-stable https://charts.rook.io/stable helm install --namespace rook-ceph-system rook-stable/rook-ceph 部署完成后可以看到rook-ceph-system Namespace 下运行的 Resource: 创建 CephCluster ################################################################################# # This example first defines some necessary namespace and RBAC security objects. # The actual Ceph Cluster CRD example can be found at the bottom of this example. ################################################################################# apiVersion: v1 kind: Namespace metadata: name: rook-ceph --- apiVersion: v1 kind: ServiceAccount metadata: name: rook-ceph-osd namespace: rook-ceph --- apiVersion: v1 kind: ServiceAccount metadata: name: rook-ceph-mgr namespace: rook-ceph --- kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: rook-ceph-osd namespace: rook-ceph rules: - apiGroups: [""] resources: ["configmaps"] verbs: [ "get", "list", "watch", "create", "update", "delete" ] --- # Aspects of ceph-mgr that require access to the system namespace kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: rook-ceph-mgr-system namespace: rook-ceph rules: - apiGroups: - "" resources: - configmaps verbs: - get - list - watch --- # Aspects of ceph-mgr that operate within the cluster's namespace kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: rook-ceph-mgr namespace: rook-ceph rules: - apiGroups: - "" resources: - pods - services verbs: - get - list - watch - apiGroups: - batch resources: - jobs verbs: - get - list - watch - create - update - delete - apiGroups: - ceph.rook.io resources: - "*" verbs: - "*" --- # Allow the operator to create resources in this cluster's namespace kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: rook-ceph-cluster-mgmt namespace: rook-ceph roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: rook-ceph-cluster-mgmt subjects: - kind: ServiceAccount name: rook-ceph-system namespace: rook-ceph-system --- # Allow the osd pods in this namespace to work with configmaps kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: rook-ceph-osd namespace: rook-ceph roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: rook-ceph-osd subjects: - kind: ServiceAccount name: rook-ceph-osd namespace: rook-ceph --- # Allow the ceph mgr to access the cluster-specific resources necessary for the mgr modules kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: rook-ceph-mgr namespace: rook-ceph roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: rook-ceph-mgr subjects: - kind: ServiceAccount name: rook-ceph-mgr namespace: rook-ceph --- # Allow the ceph mgr to access the rook system resources necessary for the mgr modules kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: rook-ceph-mgr-system namespace: rook-ceph-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: rook-ceph-mgr-system subjects: - kind: ServiceAccount name: rook-ceph-mgr namespace: rook-ceph --- # Allow the ceph mgr to access cluster-wide resources necessary for the mgr modules kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: rook-ceph-mgr-cluster namespace: rook-ceph roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: rook-ceph-mgr-cluster subjects: - kind: ServiceAccount name: rook-ceph-mgr namespace: rook-ceph --- ################################################################################# # The Ceph Cluster CRD example ################################################################################# apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: name: rook-ceph namespace: rook-ceph spec: cephVersion: # For the latest ceph images, see https://hub.docker.com/r/ceph/ceph/tags image: ceph/ceph:v13.2.2-20181023 dataDirHostPath: /var/lib/rook mon: count: 3 allowMultiplePerNode: true dashboard: enabled: true storage: useAllNodes: true useAllDevices: false config: databaseSizeMB: "1024" journalSizeMB: "1024" 这个 yaml 列表包含了如下的 Resource: ...

2019-05-08 · 8 分钟 · 1542 字 · 涯余

在 Gitlab 中使用 Danger

Gitlab 社区版的 CI 功能非常好用,能够很方便的地做到代码的 lint/build/test/等等。不过社区版在多人协作上(比如 Merge Request)上阉割了不少功能, 比如将 MR assign 给多人等。通常来说,在代码合并这块,CI/CD 一般包括两部分: 代码本身以及 MR/PR 本身。Danger 这个工具正好可以补足 Gitlab 在后者的不足。 功能 Gitlab CI 的关注点在于提交的代码本身,而 Danger 的关注点在于 Merge Request 本身,当然也可以做到很多 Gitlab CI 能做到的事情,各种第三方插件也能极大地扩种 Danger 自身的能力。目前我觉得几个非常有用的功能是: 检查 Commit Message 的格式。这个功能是很基本的,但是很多 CI 系统本身都不支持。 检查与 jira 的关联。强制让每一个 MR 都关联一个 jira,方便项目管理 检查 MR 是否打标签。在 MR 非常多的时候用于给 MR 归类,在 Github 上的大项目上我们经常见到 检查 MR 的大小。改动太大的 MR 是不推荐的,因为 Review 起来难度太大,推荐分裂成比较小的 MR 检查是否 rebase 过了目标分支,保持一个干净的提交记录。 安装 因为 MR 本身属于 Git 系统的一个功能,所以 Danger 的一个主要能力在于与各大平台的集成性上,目前主流的 Gitlab/Github/都支持。也很容易部署。下面简要介绍与 Gitlab 的集成方法 ...

2019-05-07 · 2 分钟 · 262 字 · 涯余

少有人用的 debugger

不知道别人是怎么认为的,我之前一直认为,Debugger 应该是一个正统的解决软件问题的方式。我们应该尽力地去多用这种方式,通过各种其他的 print 等方式是一种原始的,偷懒的,笨拙的方法。 我也总是去尝试学习各种 debugger 以及在工作中去使用它们,但都是很难进行下去。真实的工作场景中也鲜有人用 debugger。是大家都在逃避问题,投机取巧吗? 今天看的几篇文章让我明白了,debugger 并不是什么正统,而是一种适用范围非常狭窄,应该尽量少用的方式。用 print 之类的笨办法是应该的,值得推荐的。 Linux 在邮件列表里表达的对于在内核开发中使用 debugger 的看法也很适用于通用软件的场景: It's partly "source vs binary", but it's more than that. It's not that you have to look at the sources (of course you have to - and any good debugger will make that _easy_). It's that you have to look at the level _above_ sources. At the meaning of things. Without a debugger, you basically have to go the next step: understand what the program does. Not just that particular line. 相对来说,debugger 本身更像是对问题的逃避,我们放弃对于问题以及代码更为细致的观察与思索,直接交给程序来一行一行校验代码的正确性。而在没有 debugger 的场景下,我们需要花费更多的时间来思考整个程序的设计,自上而下地考量整个问题以及解决的方式对不对,最终的困惑可以通过 print/system tools 等工具结合起来去校验。通过这种方式,最终对问题的解决可能并不是对于现有某些代码的修改,而是对于代码整体的重构与调整。 ...

2019-05-06 · 1 分钟 · 143 字 · 涯余

jekyll 的问题

考虑良久,决定将 Blog 迁移到 hexo。整个过程比想象的简单很多,也看了下二者的异同。相对于来讲,我觉得 hexo 在设计上比 jekyll 更为优良一些,更适合作为一个静态博客生成器。 那么,jekyll 的问题在哪? 目录结构 jekyll 的目录结构是 posts/themes/settings 等杂糅在一起,初看起来更好理解,但使用起来是很痛苦的。尤其是在更换 theme 的时候,需要小心翼翼地甄别哪些目录需要更换而哪些不需要。而 hexo 的目录结构更加清晰,每个 themes 的内容都包含在一个单独的目录中,与其他部分互不干扰。想要更换 theme 直接 clone 一个新的改一个配置参数即可。 更换 theme 的次数越多,jekyll 的目录结构会越来越乱,分不清哪些文件是当前必须的。而 hexo 没这个问题。 默认主题 jekyll 没有默认主题。或者说有,但大家不这样用。通常的用法都是找一个现成的第三方 blog clone 下来,然后按自己的需求改。这样有个问题就是,总会有一种不适配的感觉。因为主题都是别人为自己的使用配置的。而 hexo 提供了默认的主题,它是这个软件自带的一部分,是理所应当的属于我们自身的。而且这个默认的主题已经足够好用,同时第三方的next主题也占据了相当大的份额。不是说选择少,而是在 hexo 上能够更快地完成theme配置这一环而专注于内容。 功能 jekyll 各个 theme 的功能丰富程度差别很大,分页、评论、TAG 等等。不同主题想要添加新功能的方式不同,遇到问题处理的简易程度也不一样。而这种情况也往往导致用户会选择更换主题,然后继续恶性循环。hexo 的默认主题提供了对大多数常用功能的支持,而扩充起来也比较方便,不同主题在这块的差别也比较小。 内容发布 这块 jekyll 完全没做,必须得自己手动创建 md,添加头部的 attribute,之前还借鉴了其他人的 shell 脚本来根据模板自动生成这些内容。而 hexo 提供了new命令来创建新的 post,自动补上头部的内容,这样学习成本基本上就只剩 markdown 了。 目前静态博客软件的内容发布还是太偏程序员化了,可以参考 wordpress 的地方还有很多。目前已经有一些 admin 页面的项目流行起来,但还没有达到能让普通用户无学习成本使用的程度。 其他 目前静态博客的分化是好事,但有点像 linux distros 那样,最终也带来了很多恶性循环。大家不关注易用性去普及用户,而更关注彼此设计理念的不同。一堆程序员圈地自嗨,最终可能只是落得自娱自乐罢了。

2019-05-05 · 1 分钟 · 71 字 · 涯余

如何防止代码变成 SHIT

最近发现之前写过的很多项目,不管是 python/go/cpp 的,最终回看起来代码都变的很难看,尤其是多人合作的时候。 这是一个很头疼的问题。自己平时很在意这个,但是代码最终确都变成了 shit。 问题 当一个人开发的时候,问题主要在于一个人的自律性不够强,不管是代码注释等都是随意写的,即使偶尔意识到了问题,但也难以保证能一直坚持下去。 而当人多的时候,问题经常处在多人风格的不同上。如果没有工具来强制大家遵守一定的规则,那么大家每个人自己的风格放在一起的时候,就成了垃圾代码。 避免代码变成 shit 的唯一方法,就是让大家写的代码看起来都一个样。而这个工作除了由开发人员的 Code Review 之外,还需要工具来约束。 解决方法 CI/CD 最开始接触 CI/CD,我只是认为它主要是用于部署方面的一个工具。现在发现,它对于代码质量的改进也是意义巨大的。所有代码通用规范上的约束,静态分析,复杂度分析等都可以通过自动化工具来执行。 一方面,我们可以组合尽可能多的代码静态分析工具,来约束提交代码的错误,提供代码改进的建议,形成统一的代码风格。另一方面,最于 Code Review 来说,不再需要关注基本的代码风格以及基础部分,而只用关注于具体的业务以及代码架构层面的问题。 静态分析 Python 这样的代码,在多人合作的大型项目上,如果没有非常严格的代码约束,最终出来的项目时非常难以维护的。可能经常部署出来的代码连跑都跑不起来。相对来说,静态类型语言在这方面的优势是巨大的,编译器在编译代码阶段能发现大多数比较明显的问题,最终线上的问题一般都是需要人来参与分析的。 代码的静态分析是一个非常古老但是重视程度不够的技术。静态类型语言的代码分析技术能够极大地减少代码中可能存在的 bug,并给出很多的建议。以 Golang 为例,目前已经有几十款静态分析工具。 而像golangci-lint这样的工具,可以将多种分析工具结合起来,在各个层面给出代码改进的建议。比如: 代码的简化写法 可能的 bug Dead Code 未使用的或者被覆盖的变量 … SonarQube 其实是类似的产品,只不过是 Client/Server 的架构,提供了诸如复杂度分析,单元测试覆盖率等指标。良好的 UI,以及插件式的架构,与普通的 cli 工具结合起来之后,对于代码质量的提高是非常有益的。 总之,工具能处理的事情越多,人的精力就更多的能去关注更上的层面和业务层面。 Code Review Code Review 虽然成为一个共识,但真正的效率确实难以保证的。莫名其妙的改动,形式化的 approve,现有工具的局限等等问题都造成了参与的人在这方面的低效率。所以总是需要有各种规范来指导人们如何进行 Code Review。一般来讲,我们可以将代码的改动拆分为三个问题 Why? 为什么要做这个改动 How? 怎么做这个改动 What? 具体做了哪些改动。 这几个问题,工具能参与的只是What的一部分。其他的部分都需要人来 review。一般的 Code Review 提交的模板也都要求提交 PR 的人尽量说清楚 Why,通过文档 link 或者文字等形式。具体的 How 以及 What,则需要具体的人来参与 review。 ...

2019-05-01 · 1 分钟 · 94 字 · 涯余

JFFS3 文件系统

闪存对文件系统的影响 闪存转换层 JFFS3 JFFS2 的问题 Index 的存储 The Journal Garbage collection Superblock Links 看完了闪存,继续看文件系统。网上搜了一圈,发现都是讲 Andriod 的目录结构的,讲文件系统本身的少。目前能确认的是历史上曾经用过 ext4,yaffs,yaffs2 等。 估计目前主流的应该是 ext4。不过在搜索的时候先发现了一篇讲 jffs3 的,它在嵌入式系统上应用比较广泛,也是针对 Flash 存储特定设计的文件系统。不太确定现在的使用范围,但是拿出来研究下还是不错的。 闪存对文件系统的影响 闪存跟磁盘有很多不同的地方,在设计文件系统的时候,二者有很多不同的考量。简单的对比表格如下 闪存 磁盘 最小寻址单位(读) 字节 扇区 最小寻址单位(写) NOR FLASH 是字节,NAND FLASH 是页,擦除是块 扇区 寿命 由擦写块的最大可擦写次数 机械故障 闪存的这些特性,导致我们在设计文件系统的时候,必须考虑以下的问题: out of place update: 对于磁盘来讲,我们更新数据可以直接原地更新。但是闪存不行,因为无法将 bit 位从 0 -> 1。所以对于闪存的数据更新只能是在另外一个地方写入数据,然后将原数据标记为 dirty,再通过 GC 来定期回收. wear leveling: 磨损平衡。闪存的使用寿命是由擦写块的最大可擦写次数来决定的。超过了最大可擦写次数,这个擦写块就成为坏块(bad block)了。因此为了避免某个擦写块被过度擦写,以至于它先于其他的擦写块达到最大可擦写次数,我们应该在尽量小的影响性能的前提下,使擦写操作均匀的分布在每个擦写块上 闪存转换层 为了能让普通的文件系统(磁盘上的)能够在闪存上正常运行,需要有一个转换层:Flash Translation Layer(FTL)。它的功能就是将底层的闪存模拟成一个具有 512 字节扇区大小的标准块设备(block device)。对于文件系统来说,就像工作在一个普通的块设备上一样,没有任何的差别。 ...

2019-04-20 · 2 分钟 · 360 字 · 涯余

闪存

基本定义 NOR / NAND 写/擦除 eMMC / UFS Links 本来看华为新弄了 FS 和编译器,想学习下。但是目前似乎放出来的技术资料并不多,就先做下技术储备。先研究下他们做这个优化的历史背景。一路看下来发现链路太长,EXT4、更早的文件系统、最后到了闪存。 大学课堂上学过,但到现在真要考我,估计也说不出个所以然,所以先记录下闪存相关的笔记。 基本定义 ROM 的一种,虽然看着是read only,但是闪存属于的细分类别已经可以允许重写数据(EEPROM)。比较接近的两种细分类别对比来看: EPROM: 需要用紫外线照射才能重写数据(注定要被淘汰的技术) EEPROM: 多的一个E便是Electrically,可以用电擦除数据 自然 EEPROM 的应用更加广泛。目前手机上的存储主要就是闪存(EEPROM)。闪存用于手机等移动设备的一些原因如下: 动态抗震性好(没有机械部件) 极端环境下也比较可靠(手机三防) 在擦除数据时比一般的 EEPROM 效率更高(区块对字节) NOR / NAND 两种 flash 的类型,直接上一个比较简单的表格对比: NOR NAND 抹写速度 慢 快 抹写次数 低 高 (10x) 存取方式 随机 区块 成本 高 低 面积 大 小 适用场景 微处理器 普通存储 实际使用 BIOS/机顶盒 U 盘/SSD 写/擦除 这也是一个容易忽略但是细究起来很容易让人迷惑的东西。为什么闪存有擦除的概念? 简单来讲,由于闪存特殊的物理构造,可以理解为写操作只能写入0,擦除操作相当于写入1。手机闪存和固态硬盘为什么擦除多了会损坏?这篇文章提供了具体的电路图示意: ...

2019-04-18 · 1 分钟 · 131 字 · 涯余

视频测试

2019-04-15 · 0 分钟 · 0 字 · 涯余

Google 的经验

看了一篇讲谷歌公司内部的软件管理的论文,虽然对很多东西已经很熟悉了,但还是觉得有了一些新的启发。 业内对 Google 其实大多数都是一种追随者的态度。单说最近这些年的几大热门产业,大数据由 Google 的三篇论文起始,云计算由 Kubernetes 引领热潮, Alphago 在 AI 领域让人震撼。Google 比其他公司更早面临了很多技术发展的瓶颈之处,解决之后在某个时机将部分成果开源出来共享给业内。技术问题大家很容易采纳学习,但能解决这些问题的软件工程模式, 则不是那么容易学习的。 Single Repo Google 在公开这种模式之后,大部分人的态度是震惊的。因为这跟大部分人的使用模式差别很大。不管是大公司小公司,不同功能的 Repo 对应不同的功能,非常便于维护,便于划清职责。Google 的单一 Repo 模式,尤其在其规模之上,初看起来是非常难以理解的。上 Tb 的仓库数据,每天上万次的 Commit,它是如何管理的呢? 问题的答案自然是一套更为复杂的 CI/CD 系统,每一次的提交,自动化的构建、自动化的测试、自动化的 Review Check 等等,有了这些之后,代码的基本质量就有了保证,其他的就靠更为严格,精确的 Code Review 流程了。之所以大部分公司无法这样做,因为基础的 CI/CD 系统从来都不是一个公司在成长过程中优先考虑的问题,功能 -> 性能 -> Bug, 这些问题解决的差不多了,才有考虑其他的空闲。而往往此时,开发模式已经固定下来,没有了往 Single Repo 迁移的动力。 另一方面,Single Repo 带来的优势初看起来也是比较模糊的。它更多的不是一个技术上的问题,而是一个管理模式,或者企业文化上的问题。 是否能允许员工查看几乎所有的源码 Repo 如何在 Single Repo 中划分各个项目的职责边界 对 Google 来讲,去掉这个边界是必须的。他希望员工能够熟悉整个系统,不受限于自己所主要维护的组件的束缚,保持一个开放的心态。每个人都有创造的天性,当他发现有一个其他项目的问题或者优化他很想修复,或者有更好的解决方式,没有了项目的边界,他很自然地认为可以这样做也应该这样做。这种开放的模式保证了 Google 的所有项目能受惠于公司所有人的才智,也造就了 Google 在技术和商业上的成功。 Personal Time 这也是人人熟知,但几乎没有任何经常自称有 Google 背景的管理人员愿意尝试的模式。给员工留一些时间,让他做自己想做他任何想做的事。对于 Google 来说,有很多项目和改善都是来自于员工在这个时间的 Side Project。 ...

2019-04-14 · 1 分钟 · 78 字 · 涯余

Github 与编程语言

一个语言的流行程度与多种因素相关,语法的简易性,package 的数量,性能,适用的场景等等。Perl 因为语法的怪异而逐渐无人问津,ROR因性能等问题也用的人越来越少。 一向处于主流地位的 C/CPP 在这几年也比不上 JavaScript 以及 Golang 的热度。在 Github 上,我们可以看到热门的项目中,JS 以及 Golang 等热门语言占据了相当瞩目的位置。 语言之间的较量从来就不是在单纯的语言层面本身,而是整个生态系统的对比。而不知不觉间,Github 也成了每个语言生态体系的一部分。 当代的主流程序员中,大多数都有 C/CPP 的语言背景。但在大部分的工作选择上,python 与 Golang 的数量越来越多,也越来越占主流。究其原因,一方面是在语法层面上,采用了与 C 相似而更简单的表达方式。但更重要的是,从一开始,他们就考虑到了包管理系统的重要性,因为它是语言生态系统的发动机,而 C/CPP 等语言到现在仍未有一个内建的实现。 对 Python 而言,在 Github 流行之前,pip 已经非常成熟。这让他成为了一个在任何需求面前都是被优先选择的语言之一。http 请求、web 框架、爬虫、图片解析等等,只要你想要的任何功能,都可以在 pip 里找到已经有的实现。有了 Github 之后,python 的 package 的数量的扩充进一步加快。代码在 github,二进制包在 pip,文档在 readthedocs,这是一个非常完善而让人信任的体系。 对于 Golang 来说,它就是生于 Github,流行于 Github 的。从一开始 docker/kubernetes 项目的流行,以及整个容器生态的成熟,给了 golang 一个良好的开端。go 内置的对于 github 上代码仓库的支持,即使有很多小问题,但总体来讲,这让 golang 以极快的速度建立起来了超越于 c/cpp 甚至能赶上 python/pip 的生态体系。在常规的开发场景以及业务需求上,golang 以及没有短板了。 而反观 c/cpp,在 github 之前,假设我们想要去找一个 package,只能借助于搜索引擎。也许在某些奇怪的网站上,能找到一个实现方案。但是相比于 golang/github 模式,这样的方式有明显的缺陷: ...

2019-04-12 · 1 分钟 · 112 字 · 涯余

The useless web

早期互联网的美妙之处在于,它真的是万维网,由无数的由个人或者公司搭建的互联网。没有如此大公司固定平台的限制,这些网站充满了无数的可能性。 之前工作无聊时发现的一个the useless web, 它给了我们一个magit button,每次点击都可以打开一个新的神奇的无聊网站: 有最神奇的可以随鼠标晃动的东西: 一个向下拉有无限长的腿的马: 一个不知道什么的隐喻: 被偷了 bucket 的海象… 这是一个几乎无限长的例子。几乎也是自由互联网的意义所在。很像<Rick and Morty>里他们看的宇宙电台一样,无穷无尽的稀奇古怪的电视节目。 无尽的无趣,比有限的伪装要好太多了。

2019-04-10 · 1 分钟 · 16 字 · 涯余

Docker BuildKit 介绍

为什么需要 BuildKit BuildKit 长什么样子 LLB 有用的新功能 Links 对于 Docker 和 Kubernetes 来说,在自身发展的壮大过程中,都会经历一个因为功能不断增加导致的软件结构庞杂的问题。对于 Kubernetes 来说,出于架构上的考量,kubectl 等项目的代码都会逐渐从主项目中移除。对于 Docker 来说,事情更为复杂,它既要考虑开源,又要考虑自己的商业化,所以有了 moby 以及 *kit 等一系列项目。 下图清晰地展示出了 Docker 对于相关项目的一个架构规划: 总体来说,Docker 希望将容器技术与容器产品分离开,核心技术是开源的,可扩展的,这样允许有其他人来基于同样的技术来构建类似于 Docker CE/Docker EE 这样的产品。 BuildKit 自 2017 年年底便已经实现,但似乎关注度不是很高(在国内),在 CI/CD 系统中的应用也不是很广泛。本文是关于 BuildKit 的一个相关介绍。 为什么需要 BuildKit 除了上面说的商业以及架构上的考量,本身在构建这一块,Dockerfile 以及相应的机制也面临着一些问题 并发程度不够好 很多步骤都是可以并行执行的,比如两部构建中的两次 pull 镜像,以及各种 run 命令 对 cache 的支持不好 像 golang 这样的语言,每次构建都要从头开始,没法复用缓存 对 secret 的支持不好 难以支持在 dockerfile 中通过 username-password/ssl key 等方式获取一些加密信息 ...

2019-04-08 · 2 分钟 · 250 字 · 涯余

更安全的 DNS

主要问题 解决方法 使用受信任的 DNS 解析服务器 DoH QNAME minimization 其他问题 Links HTTPS 已经越来越普及了,包括 Github Pages 都可以很方便的集成。浏览器也开始通过各种手段来促进网站都尽量使用 HTTPS。相比来说, DNS 的安全性受重视的程度就没那么高。Firefox 写了一个一篇非常好的介绍文章(见最后 Links),系统性地介绍了当前的问题以及解决方案。在这里整理一下。 主要问题 DNS 协议主要交流的信息就两个:ip 和 domain, 这两个东西一般来说,很不起眼,但是漏洞(非安全协议)摆在这,总会有各种不法分子来作恶。目前我能想到的比较明显的两个就是 运营商劫持: 一个不靠谱的运营商,在各个网站插入各种恶心的广告, 重定向网址等 不安全的公共网络: 比如公共场所的 wifi, 可以伪造各种网站,收集用户的上网记录等等 火狐也在文章中写出了 dns 查询过程中可能出现的安全漏洞: 主要有三个 不可靠的本地 dns 服务器 中间人攻击 一些根域名服务器能追踪你的解析记录。 解决方法 这几个问题,火狐都列出了解决方法。 使用受信任的 DNS 解析服务器 一般用户,包括互联网从业者,都不太关心本地配置的 dns 服务器是什么,一般都是运营商默认的。一般人也没有精力(能力)在出问题的时候去根运营商协调解决。火狐的思路是在用户使用浏览器的时候(不干涉其他程序),选择火狐信任的 dns 服务器来进行 dns 查询(可配置为失败时 fallback 到机器默认的)。目前火狐是和 cloudflare 合作,由 cloudflare 来提供域名解析服务,未来应该会有更多的提供商。 目前的 Firefox 66 版本已经支持了此选项(不一定是最早支持版本),可以在 about:config 里面搜索 trr 查询到: ...

2019-04-04 · 2 分钟 · 231 字 · 涯余

Emacs is drugs

每个程序员都会遇到这一天,他要做一个决定,vim 还是 emacs,还是 IDE。 近来一直主要用 Golang, 早已不再年轻的我自然是选择功能强大的 Goland, 日常工作无压力。即使没有免费的注册码了,我也毫不犹豫地买了正版。只是,它太慢了,太卡了,16GB 内存的 Mac 跑起来都不轻松。 在无数次的痛苦的等待中,我终于决定换一个 Editor 试一试。Atom 也慢,Code 看起来都很不错,插件多,界面舒服,速度也快,但我面对它总有一种无所适从的感觉。我偶尔会用它来做些零碎的工作,但从来没法把它当作 一个主要的开发工具。 这几天偶然翻起来一直装在电脑里确很久没有打开的 Emacs, 才明白了 Code 的问题在哪。 Code 是一个优秀的 Editor, 但也仅此而以。我们用它来写代码,代码和 Editor 是两个东西。我们要学习怎么去使用这个软件,这个学习的过程和写代码是两套系统。它像 PS,像 Word,是一个精巧的软件,是编程的产物。 而 Emacs 不同,它是一个 Editor, 但又和任何的 Editor 不同。它即是一个精巧的软件,也是一个操作系统,也是编程本身。 首先,它基于 Elisp 编写,是 lisp 到今天少有的面向大众的软件产品。他的所有扩展也都是 lisp 代码。lisp 良好的可读性能让人很容易理解一个扩展是怎么写出来的,你可以如何修改它,照着它写一个新的。你在用它的时候,能明确地感觉到你在写的代码和编辑器不是分离的两个东西。它不是一个服务于你的黑盒子,而是一个对你透明的软体。你可以随时打开它看看他的内在,修改它,调整它,让他的形态更适用于你的需求。在很多人使用 emacs 的时候,会经常发现,你打开的文件列表经常会有 lisp 代码。好像他们属于一个项目似的。 elisp 主要的功能都是面向文本编辑的,所以它比普通的 editor 有更多的概念: 缓冲区/ring buffer/minibuf/mode-line 等等。这些概念加起来,造就了最为精准丰富的文本处理和表现系统。无数在其他 editor 无法实现或者很难实现的功能,在这里都可以很容地用代码写出来。是的,就是用 elisp 代码。最终,是 elisp 代码组成了 emacs, 而对其他的 editor 来说,组成他们的是基本功能 + 扩展。 Editor/IDE 的分化,是因为用常规的软件设计思路,无法作出一个满足以下功能的开发工具: ...

2019-03-28 · 1 分钟 · 150 字 · 涯余

istio

整个容器化浪潮诞生了三个胜利者,分别是 docker, kubernetes, istio。 一个额外的胜利者是 golang。 Docker docker 的作用是: 用标准语法描述出一个服务的静态/运行时环境,无关语言与操作系统 资源隔离 被打死的是 lxc, 它有资源隔离的功能,但是缺点太明显: 没有上面的 docker 提供的第一个功能 架构不如 docker 的 cli/server 的简洁明了,易于学习 受威胁的是 VM 太慢了 性能损耗大 无法 API 化 Kubernetes 真正的 DCOS,核心优势: 统一资源模型 统一 API 模型 (引导业务 API 向其靠拢) Node 横向扩展 插件化 被打死的是 Mesos/Marathon,缺点 两层架构的低效率 (仁慈独裁与低效民主) C++ C++ 导致的难以 debug 难以扩展以增加新功能 另一个被打死的是 swarm/compose, 缺点 架构不清晰 自下而上地缓慢地堆功能 受威胁的是 YARN, 不如 kubernetes 通用性强 Istio 微服务相比于单体服务的一切问题都应该在这层解决, trace, 限流, metrics 等等 不需要修改业务代码 比手工的实现更完善,功能更强 受影响的:微服务业务代码 ...

2019-03-25 · 1 分钟 · 73 字 · 涯余

Namecoin

互联网到今日已经越来越趋向于中心化,用户的隐私安全以及大公司的行为也日渐引起担忧。去中心化网络是一个应对此问题的重要思想,blockchian,bitcoin,tor 等都是一些具体的技术探索,很多已经有了越来越大的影响力。Namecoin 也是其中的一个。 Namecoin 想要解决的是目前 DNS 存在的一些问题。中央机构控制的 DNS 很容易因为各种原因受到干扰,用户的利益和隐私容易受到侵犯。Namecoin 借助于 bitcoin 的思想,构建了一个去中心化的 DNS 系统。 Zooko’s triangle 类似于分布式系统中的 CAP 理论。类似 DNS 这样的协议,我们期望它具有的三个特性很难满足: 安全,可读性好,去中心化。目前的最常用的 DNS 系统不满足去中心化。DNSSec 对现有的 DNS 做了一些安全性的增强,但仍然是中心化的。.onion和bitcoin是去中心化的和安全的,但是可读性很差等等。 Namecoin 是满足上面要求的一个系统。(Aaron Swartz曾经提出过这样的设计思路) Namecoin Namecoin 基于 BitCoin,本身就是在 Bitcoin 的代码上实现的(大概做了 400 多行改动)。挖矿的方式跟 bitcoin 一样,只是用的是不同的 block chain.二者的目的不同,bitcoin 主要还是为了成为一种货币系统,Namecoin 是为了成为一种命名系统。所以二者的关注点不同,blockchain 分开也是最合理的。二者有一些不同的规则: namecoin 要求名字的唯一性(域名),而 bitcoin 不要求 经济交易以及域名注册使用的货币大小不一样,block size 设的不一样更好 通货膨胀对 bitcoin 的影响很大,namecoin 则不一样。 namcoin 中,注册域名需要花钱,但这些货币会被销毁(0.01NMC).因为是去中心化的系统,没有收费的中央系统。 Namecoin 里的数据主要分为两种 domain name 和 NameID Domain Domain 的格式类似于: ...

2017-08-22 · 1 分钟 · 187 字 · 涯余

Kubernetes 笔记

API 声明式的 API API Response 错误处理 Resource Version Version API Group Runtime config REGEX 字段格式 PATCH 与 PUT Events 交互 输出 输入 API 声明式的 API 声明式: 结果是什么 命令式: 做什么 声明式的操作,相对于命令式操作,对于重复操作的效果是稳定的,这对于容易出现数据丢失或重复的分布式环境来说是很重要的。另外,声明式操作更容易被用户使用,可以使系统向用户隐藏实现的细节,隐藏实现的细节的同时,也就保留了系统未来持续优化的可能性 kubernetes 里的 API 都是声明式,我们描述好自己想要的 resource object,kubernetes 就会不断尝试去保证这个 resource object 按我们期望的方式存在. API Response 一般包含三部分 metadata: 元数据 annotations: 一些元信息.给第工具用来存储和解析原信息用的. labels: act as filter namespace: resource 所处的 namespace name: resource 名字 uuid: 唯一标识 creationTimestamp: 创建时间 deletionTimestamp: 计划删除的时间(graceful deletion) resourceVersion: 每个 resource 的内部版本,可以用来确定是否发生了变化.也用于做并发控制 generation spec: 具体描述,不同 resource 的属性不同。spec 里通过声明式的方式表明了期望的目标状态 status: resource 的当前状态 下面以展示一下 kubernetes node api 的 metadata 作为样例: ...

2017-08-18 · 3 分钟 · 452 字 · 涯余

Blockchain

介绍 区块结构 头结构 区块结构 创世区块 分叉 Proof-of-work(工作量证明) 邮件 Header Bitcoin REF 介绍 区块链是由一串使用密码学方法产生的数据块组成的,每一个区块都包含了上一个区块的哈希值(hash),从创始区块(genesis block)开始连接到当前区块,形成块链(类似数据结构中的链表).每一个区块都确保按照时间顺序在上一个区块之后产生,否则前一个区块的哈希值是未知的。 其优势在于: 完全分布式的,无中心节点(单点故障) 任何节点都可以创建交易。在经过一段时间的确认之后,就可以合理地确认该交易是否有效。 修改交易记录的成本非常高 区块链也是比特币等技术的基础。它也是一种非常重要的新思想,促使人们对现有的网络,社会,经济等进行重新思考。 区块结构 头结构 大小(bytes) 字段 描述 4 版本 版本号 32 父区块哈希值 引用区块链中父区块的哈希值 32 merkle 根 该区块交易的 merkle 树根的哈希值 4 时间戳 该区块产生的近似时间(精确到秒的 unix 时间戳) 4 难度目标 该区块工作量证明算法的难度目标 4 Nonce 用于工作量证明算法的计数器 区块结构 大小(bytes) 字段 描述 4 区块大小 该字段之后的区块大小 80 区块头 区块头结构 (上面的大小之和) 1-9 可变整交易计数器 交易的数量 可变 交易 记录在区块里的交易信息 创世区块 比特币区块链的第一个区块,创建于 2009 年,我们称之为创世区块。它是比特币区块链里所有区块的共同祖先,这意味着你从任一区块,循链向后回溯,最终都将到达创世区块。每一个节点都“知道”创世区块的哈希值、结构、被创建的时间和里面的一个交易。因此,每个节点都把该区块作为区块链的首区块,从而构建了一个安全的、可信的区块链的根。 ...

2017-08-12 · 2 分钟 · 232 字 · 涯余

Shard

介绍 分片策略 The Lookup strategy The Range strategy The Hash strategy 相关技术 BRIN 介绍 Shard 指对数据的水平切分,每一个切分的部分都可以叫做一个shard,它们拥有相同的 schema,但却拥有不同的数据集。对数据库来说,是指对数据库的表按行进行切分(与按列的垂直切分对应),不同的 shard 可能位于不同的数据库服务器或者物理机器上。它的优势体现在以下几点: 表的大小减少,索引体积减小,提升查询性能(某些方面) 如果数据本身有比较明显的分区(比如国家,地区等),那么做 shard 很容易并且查询很大程度上都能落在一个 shard 上。 水平扩展性好,可以通过添加新节点来扩充 劣势有以下几点: 查询需要跨多个 shard 时会增加 latency 因为 shard 经常只能做到某一位维度。所以在这一维度的查询的性能可能提高,但其他维度的查询的性能则可能会下降。 跨 shard 的数据一致性和可用性也更加复杂和难以保障 shard 本身的问题让他成为一个迫不得已的选择。尽量在没有其他优化方式的情况下选择 shard.理想情况下,应该有底层框架来处理 shard 而让应用层做到对 shard 无感知,不然还不如不用。 分片策略 如果将数据集进行 shard,有很多策略可以选择,常见的有 The Lookup strategy 用 shard key 做一个映射表,包含不同 shard key 的请求会转发到相应的 shard 上。这种情况下,不同 shard key 的数据可能会落在同一个 shard 上,但相同 shard key 的数据则一定在同一个 shard 上.shard 与物理地址的映射也不能是一对一的,可以用类似于 consistent hashing 里面的那种 virtual node 的方式,设置一些virtual shard,几个 virtual shard 可以对应于同样的物理位置(reblancing 的时候对上层代码的影响很小)。 ...

2017-08-11 · 1 分钟 · 158 字 · 涯余

一点 python 的经验

可能已经过时了。

2015-11-10 · 3 分钟 · 432 字 · 涯余

Scala 笔记: 函数和闭包

Local functions 在函数式语言里,函数是最基本的功能块。通常为了模块清晰起见,我们需要很多 Help Function,但是这些辅助函数很容易有名字冲突,暴露给外部的时候也容易引起很多问题。 Java 的主要解决方式是通过private method,scala 也支持这种。但是 scala 也提供了函数 式风格的解决方式: 在函数内部定义函数(Local functions.),就像局部变量一样,其作用 域仅限于外部函数内部。 import scala.io.Source object LongLines { def processFile(filename: String, width: Int) { def processLine(line: String) { if (line.length > width) print(filename +": "+ line) } val source = Source.fromFile(filename) for (line <- source.getLines) processLine(line) } } 内部函数的一个便利之处就是它可以直接访问外部函数的变量(参数)。 First-class functions 函数式语言与命令式语言之间最大的区别之一便是其数据和代码的一致性。在 C/JAVA 这样 的语言里,变量、类、函数、语句等时候严格区分的,但在 Lisp 这样的语言里,所有的表 达式都有值,都是数据,都可以当做变量传给函数。 scala 里有function literal和function value两个概念,有点像是class和 object之间的区别,前者都是在代码层级上而言,后者是运行时的概念。例如: (x: Int) => x + 1 这是一个fucntion literal。你可以把它赋给一个变量并且调用它: var increase = (x: Int) => x + 1 increase(10) increase = (x: Int) => x + 9999 increase(10) 简单的函数一行即可描述,多行的用{}包起来即可。 ...

2015-08-31 · 3 分钟 · 433 字 · 涯余

Docker 1.7 介绍

实验特性 很多软件在发布的时候都会分为开发板和稳定版,稳定版可以供生产环境使用,开发版是让 感兴趣的用户使用,体验新特性,并报告 BUG 以助于官方改进。现在 Docker 在提供稳定版的 同时,也提供了集成了很多新特性的开发版供下载使用。 正式版的安装方式是用 https://get.docker.com/上的脚本, 开发版的安装类似,只不过用的脚本不一样 : https://experimental.docker.com/,二者最终会 启用不一样的软件源。目前开发版的版本是:1.8.0-dev,如下图所示: 注意其中的Experimental字段为TRUE。 下面我就先来看看开发版里的比较重要的更新,以便了解 Docker 后续的发展状况: 插件支持 在介绍插件之前,我们首先回顾一下 Docker 本身的架构发展。Docker 从一开始就是 REST API + JSON 的架构,这是整个 Docker 生态体系能迅速壮大的原因之一。但就 Docker Server 端的后台 Engine 来说,仍然是好多功能交织在一块,过于复杂。所以在 Docker 的后续版本中, 对 Engine 进行模块化重构一直是重中之重。从最初分离出来的 libcontainer,到 libtrust,然后现在的libnetwork,libkv,越来越多的子模块被独立出来,既简化了架 构,也增强了 Docker 对各个异构系统的适应能力。很多模块在使用上都有点类似于最早的 GraphDriver这一块,Docker 只提供一个通用的 Driver接口,各个文件系统 (aufs,overlay等)自己实现这些接口即可。如今的插件机制便是对这一功能的扩充。 如今的插件机制只支持 volume plugin和network driver plugins,后续肯定也会支持其他的 插件。如果你想现在自己尝试编写一个插件,请参考以下文档: Experimental: Docker Plugin API 官方文档里也列出了几个现存的插件,如下所示: Flocker plugin volume plugin,是数据卷可在多个主机间无缝迁移。 Weave plugin netwrok driver plugin,提供虚拟的多主机间的容器网络环境 Calico plugin network driver plugin, 提供多主机间基于 BGP 的虚拟网络 网络和服务 大家期待已久的关于网络和服务的特性终于在这一版里有了重大更新。如今network和 server都已经成了Docker里面的一等公民,像Image和Container一样,在命令行 里试一下: ...

2015-07-12 · 1 分钟 · 165 字 · 涯余

docker 容器内多进程的管理方案

容器生来适合的是以单进程为主的独立的微服务架构,而很多传统的组件则是体积庞大,多个进程(组件)之间难以拆分到不同的容器中,所以在单个容器内部署多个组件便成了一种 暂时的折衷方案。这便引入了一个问题:如何在容器内管理多个进程? ...

2015-05-08 · 1 分钟 · 87 字 · 涯余

docker 容器的一些概念辨析

本篇的主要内容是为了澄清 docker 容器的一些容易混淆的概念,主要分两部分, 一是容器端口的publish和expose,二是 Dockerfile 中ENTRYPOINT和CMD的区分。 ...

2015-04-16 · 1 分钟 · 199 字 · 涯余

docker 源码分析(6) -- 镜像删除

本篇的主要内容是关于如何删除镜像的.听起来是挺简单的一件事,但是docker本身的删除 策略定义并不清除,而且在实际的使用过程中,似乎总是与我们预计的结果不符,比如磁盘空间并没有被释放.所以在此单列一篇,详细解析镜 像删除的过程. ...

2015-04-03 · 5 分钟 · 1029 字 · 涯余

docker 源码分析(5) -- 镜像拉取及存储

本篇的内容主要是关于docker镜像的。在我们安装好docker之后,要想使用它,第 一步就是要下载一些镜像。本文将依据此流程分析docker中镜像的拉取、存储等相关内容。 ...

2015-03-30 · 10 分钟 · 1951 字 · 涯余

docker 源码分析(4) -- 网络设置

本篇的主要内容是关于docker daemon启动时网络设置的相关部分,在上一篇中已经简要 提到(Docker daemon 启动流程) 。主要内容集中在InitDriver函数的解析上。 ...

2015-02-16 · 3 分钟 · 575 字 · 涯余

docker 源码分析(3) -- daemon 启动流程

本篇的主要内容是关于docker daemon的启动流程。其主要内容均包含在 github.com/docker/docker/docker/daemon.go文件中的mainDaemon函数中,本文即按 其执行流程分析源码。因为所涉源码较多,所以所涉部分多是点到为止,详细分析会在后续 分专篇讲述。 ...

2015-02-05 · 8 分钟 · 1531 字 · 涯余

IOPS 介绍

依旧是自己不甚清楚的一个概念,希望通过自己的整理来加深印象,也希望这篇介绍能帮助 到其他人。 ...

2015-02-04 · 1 分钟 · 170 字 · 涯余

docker 源码分析(2) -- 主程序及命令行参数解析

研究一个大项目的源码,最好是从main函数入口,一步一步与实际程序相结合,将实际代 码与相应相印证。所以本篇的主要内容就是 docker 主程序的启动流程以及命令行参数解析的 过程。 ...

2015-01-30 · 6 分钟 · 1071 字 · 涯余

现代化的开发人员实用工具

常年混迹于 linux,对命令行程序情有独钟,平时也喜欢搜集各种实用的小工具。github流行以来,越来越多的新的实用的开 发工具开源出来,有的可以用来替代一些老的工具,有的则是全新的。本文整理一些实用的 工具,希望大家能在实际开发中用到。 ...

2015-01-30 · 1 分钟 · 167 字 · 涯余

docker 源码分析(1) -- 开发环境准备

之前看过一遍docker的代码,但比较粗略。第二遍准备详细过一遍并且用博客的方式将其 整理一下。目前为止docker的稳定版本为1.4.1,所以就以此版本的代码为基础进行阅读,分 析。 ...

2015-01-29 · 2 分钟 · 257 字 · 涯余

RAID 介绍

RAID 是一个我们经常能见到的名词。但却因为很少能在实际环境中体验,所以很难对其原理 能有很清楚的认识和掌握。本文将对 RAID 技术进行介绍和总结,以期能尽量阐明其概念。 RAID 全称为独立磁盘冗余阵列(Redundant Array of Independent Disks),基本思想就是把 多个相对便宜的硬盘组合起来,成为一个硬盘阵列组,使性能达到甚至超过一个价格昂贵、 容量巨大的硬盘。RAID 通常被用在服务器电脑上,使用完全相同的硬盘组成一个逻辑扇区, 因此操作系统只会把它当做一个硬盘。 RAID 分为不同的等级,各个不同的等级均在数据可靠性及读写性能上做了不同的权衡。 在实际应用中,可以依据自己的实际需求选择不同的 RAID 方案。 ...

2015-01-25 · 3 分钟 · 440 字 · 涯余

bash 各配置文件浅析

与 bash 相关的配置文件非常之多,用户目录下的.bashrc,.profile,.bash_profile, 系统级的/etc/profile等。我们也经常会发现,在某个文件里设置好了环境变量之后,并 不能总是能在使用 bash 时正确加载。下面将对这个问题进行深入剖析,以解除疑惑。 ...

2015-01-23 · 1 分钟 · 152 字 · 涯余

CoreOS 安装及配置

本文所遵照的步骤是官网的 Installing to disk 方法,即刻录 ISO 镜像 -> 启动 Coreos Live CD -> 安装到硬盘的步骤,与一般的桌面 Linux 安装非常类似。但 coreos 安装时也有一些需要注意的地方: cloud-config.yml 这是 coreos 用来统一配置系统的地方,系统在每次启动时都会加载这个文件的配置,比 如系统服务、网络设定、文件修改、用户设定等。这样做的好处是在部署集群的时候可 以方便地使用相同的配置。在安装 coreos 时,需要指定好这个配置文件。实际操作时, 可以提前将这个文件写好放在别的机器上,然后用 scp / wget (利用下面的 web server) 下载到 coreos 的 Live CD 即可,或者直接存在 Live CD 里更方便。 GFW coreos 安装时需要从官网下载镜像,但网站被墙,所以实际安装的时候可能需要用代理来解决,缺点是速度慢。更方便的方法是提前下载好需要的文件并放在局域网内并搭建一个 web server,然后修改安装脚本的 server 即可。具体方法在后面详述。 ...

2015-01-22 · 2 分钟 · 295 字 · 涯余