(转)程序员如何把控自己的职业

这篇文章摘自陈皓(左耳朵耗子)的blog(2020/08/07上传),其中很多观点击中了我内心的想法,或许可以在我遇到方向性问题的时候给我提醒。 这篇文章的主要内容主要是我今年3月份在腾讯做的直播,主要是想让一些技术人员对世界有一个大体的认识,并且在这个认识下能够有一个好的方法成就自己。而不是在一脸蒙圈的状态下随波逐流,而日益迷茫和焦虑。直播完后,腾讯方面把我的直播形成文字的形式发了出来,我觉得我可以再做一个精编版。所以,有了这篇文章,希望对大家有帮助。 对我来说,在我二十多年的工作经历来看,期间经历了很多技术的更新换代,整个技术模式、业务模式也是一直变来变去,我们这群老程序员成长中所经历的技术比今天的程序员玩的还更杂更多。我罗列一下我学过的,而且还被淘汰掉的技术,大家先感受一下。 - MIS应用开发:FoxPro,PowerBuilder,Delphi - OA:Lotus Notes,VBScripts - 微软:ODBC/ADO,COM/DCOM,MFC/ATL,J++ - 服务器:AIX,HP-UX,SCO Unix - Web:CGI,ISAPI,SOAP - RPC:CICS,Tuxedo - J2EE:Websphere,Weblogic - DB:Sybase,Informix 我想说的是,无论过去还是今天,我们这些前浪和你们后浪所面对的技术的挑战和对技术的焦虑感是相似的,我们那个时候不但玩996,还玩封闭开发(就是一周只能回家一天)。当然,唯一好的东西,就是比起今天的程序员来说,我们那个年代没有像微信、微博、知乎,抖音这些巨大消耗你人生的东西,所以,我们的工作、生活和成长都有很效率,不会被打断、喜欢看书、Google还没有被封……当然,那时代没有StackOverlow和Github这样的东西,所以,能完成的东西或质量都一般。 当然,这里并不是想做一个比较,只是想让大家了解一下两代程序员间的一些问题各有千秋,大同小异。在整个成长过程中,其实有很多东西是相通的,其本上来说,就是下面的三件事—— 第一,如果想要把控技术,应对这个世界的一些变化,需要大致知道这个世界的一些规律和发展趋势,另外还得认识自己,自己到底适合做什么?在这个趋势和规律下属于自己的发挥领域到底是什么?这是我们每个人都需要了解的。 第二,打牢基础,以不变应万变,不管世界怎样变化,我都能很快适应它。基础的重要程度对于你能够飞多高是相当有影响的,懂原理的人比不懂原理的人能做出来的事情或是能解决的问题完全是两个层级的。 第三,提升成长的效率,因为现在社会的节奏实在太快了,比二十年前快得太多,技术层出不穷,所以我们的成长也要更有效率。效率并不单指的快,效率是怎么样更有效,是有用功除以总功(参看《加班与效率》),怎么学到更有效的东西,或者怎么更有效学习,是我们需要掌握的另一关键。 下面是我这多年来的一些认识,希望对你有帮助。 世界发展趋势 我个人经历的信息化革命应该分成三个阶段: 1990年代到2000年,这个时代MB时代,是雅虎、新浪、搜狐、网易门户网站的时代,这个时代就是ISP/ICP互联网提供商,把一些资讯数字化,然后发布到网络上。 2000年到2010年,这个时代叫GB时代,或是叫多媒体或UGC时代,上网开始变得普遍了,每个人手里的数码设备开始变得多了起来,可以上传照片,可以上传视频,甚至可以在网上做社交。 2010年到2020年,这个时代叫TB时代,这过去的十年是移动互联网时代,移动互联网只需要手机在线,不需要依靠电脑。因为手机随时在线,所以个人的各种各样的数据始终在被收集,只要用户上网就会产生数据,所以人的行为最终也被数字化了。 所有的硬件和软件都是跟着需要处理的数据而演进的,我们需要更大的带宽,更大的硬盘,更多的处理器……大到一定时候就只能进入分布式化的技术架构了,再大,数据中心也顶不住了,就会要引入更为分布式的边缘计算了。 另一方面,从业务上来看,我们可以看到整个世界就在不断地进行数字化,因为,只要数字化了,就可以进行复制传播和计算,只要可以进行计算了,就可以进行数学建模,就可以自动化,只要可以自动化了就可以规模化,只要可能规模化了,就可以改变整个行业。人类的近代史的大趋势基本上都是在解决能源和自动化的事,源源不断的能源是让机器不知疲倦的前提条件,用机器代替牲口,代替人类进行工作是规模化的前提条件。 所以,技术的演进规律基本是自动化加规模化,从而降低成本,提升效率。这就是为什么世界变得越来越快,人类都快跟不上节奏的原因,主要是整个社会不断被机器、数据所驱动。 人才需求 在这个过程中,需要什么样的人?下面是我的一些认识—— 技工,在机器和自动化面前,肯定是需要能够操作机器的技术工人了,这类人是有技术的劳动力。在编程的圈子里俗称“码农”,他们并不是真正的工程师,他们只是电脑程序的操作员,所以,随着技术门槛的下降或是技术形式的变更他可能就会变得越来越不值钱,直到被淘汰掉。 特种工,这种人是必须了解原理和解决难题的一类人,他们是解决比较难的、特定的一些技术问题。当一种技术被淘汰,他并不容易被淘汰,因为他懂原理,原理就是解决问题的能力,是解决问题的套路和方法。 工程师,不但是使用技术,还可以把活儿做好,他们认为代码更多的时间是在维护,这些人使用各种各样的手段和各种技术,精益求精地持续不断地提高代码的易读性、扩展性、可维护性和重用性,这个过程似乎永无止境。对于这些有“洁癖”,有“工匠精神”,有“修养”的技术人员,我们称他们为工程师。这种人做事又稳又快,而且可以做出很多称手的工具和方法论。 再往上是设计师和架构人员,这些人主要是开发一些工具,框架,模式,提升软件开发和维护效率,同时也提升用户体验,和提升稳定性、性能、代码重用等,总的来说就是为了降本增效。这类人的工作降低了技术得到门槛,他们把技术门槛降低了以后,就可以把这个技术普及开来,就可以由广大劳工、技工、特殊工人使用了。 还有一类人是经理,经理主要是组织团队、完成项目、创造利润。这类人中,即有身先士卒的leader,也有高高在上的boss,但无论怎么样,这些人只不过是为了让一个公司或是一个团队更好组织在一起的“粘合剂”,这类人只有在大公司中才会变成更有价值。 这就是我总结的世界需要哪些人才,我们了解这些东西以后大概就明白我们现在所处的位置有什么样的问题,我们应该去什么样的地方。 Google 评分卡 接下来,我们再来看看Google的SRE的自我评分卡: 0 – 对于相关的技术领域还不熟悉 1 – 可以读懂这个领域的基础知识 2 – 可以实现一些小的改动,清楚基本的原理,并能够在简单的指导下自己找到更多的细节。 3 – 基本精通这个技术领域,完全不需要别人的帮助 4 – 对这个技术领域非常的熟悉和舒适,可以应对和完成所有的日常工作。 对于软件领域 – 有能力开发中等规模的程序,能够熟练和掌握并使用所有的语言特性,而不是需要翻书,并且能够找到所有的冷知识。 对于系统领域 – 掌握网络和系统管理的很多基础知识,并能够掌握一些内核知识以运维一个小型的网络系统,包括恢复、调试和能解决一些不常见的故障。 5 – 对于该技术领域有非常底层的了解和深入的技能。 6 – 能够从零开发大规模的程序和系统,掌握底层和内在原理,能够设计和部署大规模的分布式系统架构 7 – 理解并能利用高级技术,以及相关的内在原理,并可以从根本上自动化大量的系统管理和运维工作。 8 – 对于一些边角和晦涩的技术、协议和系统工作原理有很深入的理解和经验。能够设计,部署并负责非常关键以及规模很大的基础设施,并能够构建相应的自动化设施 9 – 能够在该技术领域出一本经典的书。并和标准委员会的人一起工作制定相关的技术标准和方法。 10 – 在该领域写过一本书,被业内尊为专家,并是该技术的发明人。 SRE需要自评如下这些技术或技能。 ...

April 5, 2021 · 1 min · 178 words · Me

Docker Fundamentals: Cgroup

Linux Namespace的技术解决了环境隔离的问题,不过这是虚拟化最基本的一步,我们另外需要解决对计算机资源使用上的隔离。说人话,就是虽然Namespace把我关到一个特定的环境,但是里面进程使用的CPU、内存、磁盘等计算资源实际上没有被限制。这个问题的解决,就要用到CGroup技术。 Linux CGroup全称是Linux Control Group,也是其内核的一个功能,用于限制、控制和分离一个进程group的资源。最早这个项目是2006年由谷歌的工程师发起的,最开始名称是process containers(工程容器),后面觉得内核中容器这个名词被用烂了,就改名为cgroup。 CGroup可以让你对系统中运行的进程的用户组分配资源-CPU时间、系统内存、网络带宽亦或者是这些的组合。同时,也可以监控你配置的cgroup,拒绝cgroup访问某些资源。主要提供的功能如下: Resource Limitation: 限制资源使用 Prioritization: 优先级控制,例如CPU使用和磁盘IO吞吐 Accounting:审计统计,主要用于计费 Control:挂起进程,恢复执行进程 在真正的实践当中,system admin一般会利用CGroup做以下的事: 对进程集合进行隔离,限制他们所消费的资源,例如绑定CPU core 为这组进程分配足够使用的内存 为这组进程分配响应的网络带宽和磁盘存储限制 限制访问某些设备(白名单) Linux实际上把CGroup实现成了一个文件系统,你可以mount。在linux环境输入下面的可以看到cgroup已经为你mount好: 1 2 3 4 5 6 7 8 9 10 11 12 derios@ubuntu:~$ mount -t cgroup cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,relatime,cpuset) cgroup on /sys/fs/cgroup/cpu type cgroup (rw,relatime,cpu) cgroup on /sys/fs/cgroup/cpuacct type cgroup (rw,relatime,cpuacct) cgroup on /sys/fs/cgroup/memory type cgroup (rw,relatime,memory) cgroup on /sys/fs/cgroup/devices type cgroup (rw,relatime,devices) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,relatime,freezer) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,relatime,blkio) cgroup on /sys/fs/cgroup/net_prio type cgroup (rw,net_prio) cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,net_cls) cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,relatime,perf_event) cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,relatime,hugetlb) 可以看到,在/sys/fs下有cgroup目录,这个目录下面有各种子目录:cpu,cpuset,memory…。这些都是cgroup的子系统,分别用来干不同的事。 ...

April 5, 2021 · 4 min · 848 words · Me

Docker Fundamentals: Namespace

容器技术出现已经很久,只不过Docker容器平台的出现它变火了。Docker是第一个让容器能在不同机器之间移植的系统,它简化了打包应用的流程,也简化了打包应用的库和各种依赖。思考下整个OS的file system能直接被打包成一个简单的可移植的包,一开始的时候概念上还是很有趣的。 有时候我认为自己的阅读比较碎片化(short-term memory越来越少),所以我想把之前学习容器知识的一些基础技术再整理出来,也算是给自己学习的反馈。这个基础系列从Linux Namespace开始,后续会陆续介绍比如cgroup、aufs、devicemapper等技术。 参考 Namespace in operation Linux namespace man page Introduction to linux namespace 什么是Namespace 简单来说,linux namespace是Linux提供的一种内核级别环境隔离的方法。在早期的Unix中,提供了一种叫做chroot的系统调用:通过修改root目录把用户关到一个特定的目录下面。这种就是简单的隔离方式,也就是chroot内部的file system无法访问外部的内容。Linux Namespace在此基础之上,提供了对UTS、IPC、mount、network、PID、User等隔离机制。 这里可以简单举例,比如Linux的超级父进程的PID为1,如果我们可以把用户的进程空间关到某个进程分支之下,并且像chroot那样能够让下面的进程看到那个超级父进程的PID为1,而不同PID Namespace中的进程无法看到彼此,这样就能达到进程隔离。 Linux Namespace有以下的种类,供给后续参考(刚看有个印象就行): 分类 系统调用参数 相关内核版本 Mount namespaces CLONE_NEWNS Linux 2.4.19 UTS namespaces CLONE_NEWUTS Linux 2.6.19 IPC namespaces CLONE_NEWIPC Linux 2.6.19 PID namespaces CLONE_NEWPID Linux 2.6.24 Network namespaces CLONE_NEWNET 始于Linux 2.6.24 完成于 Linux 2.6.29 User namespaces CLONE_NEWUSER 始于 Linux 2.6.23 完成于 Linux 3.8) 其主要涉及到三个系统调用: clone(): 实现线程的系统调用,用来创建新的线程,并可通过涉及上述参数做到隔离 unshare(): 让某一个线程脱离某namespace setns(): 把某一个线程加到某namespace 如果读者你想看具体的实例,请自己man一下(关注一下自己的linux虚拟机内核),或者google一下,我这里贴一个clone()的source code: ...

April 1, 2021 · 11 min · 2282 words · Me

Go编程模式:Visitor(k8s)

概述 最近在看kubernetes的kubectl部分源码,记录一下其中用到的visitor编程模式(实际上kubectl主要用到了builder和visitor)。visitor模式是将算法和操作对象结构分离的一种方法。换句话说,这样的分离能够在不修改对象结构的情况下向原有对象新增操作,是符合开闭原则的。这个文章以一些例子去讨论kubectl中到底如何玩的。 从一个例子出发 写一个简单的Visitor模式示例: 我们的代码中有一个Visitor的函数定义,还有一个Shape接口,其需要使用 Visitor函数做为参数 我们的实例的对象 Circle和 Rectangle实现了 Shape 的接口的 accept() 方法,这个方法就是等外面给我传递一个Visitor。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package main import ( "encoding/json" "encoding/xml" "fmt" ) type Visitor func(shape Shape) type Shape interface { accept(Visitor) } type Circle struct { Radius int } func (c Circle) accept(v Visitor) { v(c) } type Rectangle struct { Width, Heigh int } func (r Rectangle) accept(v Visitor) { v(r) } 然后,我们实现两个Visitor,一个是用来做JSON序列化的,另一个是用来做XML序列化的: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 func JsonVisitor(shape Shape) { bytes, err := json.Marshal(shape) if err != nil { panic(err) } fmt.Println(string(bytes)) } func XmlVisitor(shape Shape) { bytes, err := xml.Marshal(shape) if err != nil { panic(err) } fmt.Println(string(bytes)) } 下面是我们的使用Visitor这个模式的代码: ...

March 31, 2021 · 4 min · 696 words · Me

Kubernetes Handbook (Start & Pod)

使用minikube构建本地单节点k8s集群 minikube ssh kubectl cluster-info kubectl get nodes #查看节点信息 kubectl describe node minikube #详细信息 多节点k8s集群,使用Google K8s Engine 构建方式看GKE官网即可 k8s初步使用 kubectl run kubia –image=derios/kubia –port=8080 –generator=run/v1 --image=derios/kubia代表要运行的容器镜像 这里的--generator会被废弃,其含义指代的是创建一个ReplicationController而不是Deployment。 kubectl apply -f 更常用 kubectl get pods kubectl get pods -o wide 显示pod ip和pod的节点 如果使用GWE,可以访问集群的dashborad: kubectl clusert-info获取地址 gcloud container clusters describe kubia | grep -E “(username|password):“获取用户名和密码 如果仅仅使用minikube,则如下不需要任何凭证即可访问: 1 minikube dashboard Namespace相关操作 1 kubectl config set-context --current --namespace=my-namespace 创建服务对象,访问Web应用 如果使用minikube或者kubeadm等自定义k8s,loadbalancer是没有集成的,需要AWS或者Google Cloud。最好使用NodePort或者Ingress Controller。如果真要用minikube, 可以使用minikube tunnel解决, 或者minikube service kubia-http ...

March 31, 2021 · 6 min · 1100 words · Me