掘友等级
获得徽章 0
《左耳听风》11月day30
分布式系统的发展
从 20 世纪 70 年代的模块化编程,80 年代的面向事件设计,90 年代的基于接口 / 构件设计,这个世界很自然地演化出了 SOA——基于服务的架构。SOA 架构是构造分布式计算应用程序的方法。它将应用程序功能作为服务发送给最终用户或者其他服务。它采用开放标准与软件资源进行交互,并采用标准的表示方式。
开发、维护和使用 SOA 要遵循以下几条基本原则。
可重用,粒度合适,模块化,可组合,构件化以及有互操作性。
符合开放标准(通用的或行业的)。
服务的识别和分类,提供和发布,监控和跟踪。
但 IBM 搞出来的 SOA 非常重,所以对 SOA 的裁剪和优化从来没有停止过。比如,之前的 SOAP、WSDL 和 XML 这样的东西基本上已经被抛弃了,而改成了 RESTful 和 JSON 这样的方式。而 ESB(Enterprise Service Bus,企业服务总线)这样非常重要的东西也被简化成了 Pub/Sub 的消息服务……
不过,SOA 的思想一直延续着。所以,我们现在也不说 SOA 了,而是说分布式服务架构了。
《卖桃者说》11月day29
如果有很多不确定因素的话,你可以用下面这个小方法,它能帮助你思考现在应该走什么样的路:
首先闭上双眼,幻想你未来的生活状态,可以是三年之后的某天,你主导开发的一款应用备受市场好评;或是五年后,你终于成为了公司的 CTO。然后从幻想中的结果倒推,如果你想在未来成为那样的人,就要判断一下,现在要选择的这条路能不能帮你实现这个梦想,这个决定是让你离想象中的未来更近,还是更远了呢?
职场如此,生活中也一样。当你被情绪左右,在匆忙做出决定之前,不妨先给自己一点时间,冷静一下再想想,什么才是自己想要的。
《数据结构与算法之美》11月day28
在基础篇中,关于“图”,我们讲了图的定义和存储、图的广度和深度优先搜索。今天,我们又讲了一个关于图的算法,拓扑排序。
拓扑排序应用非常广泛,解决的问题的模型也非常一致。凡是需要通过局部顺序来推导全局顺序的,一般都能用拓扑排序来解决。除此之外,拓扑排序还能检测图中环的存在。对于 Kahn 算法来说,如果最后输出出来的顶点个数,少于图中顶点个数,图中还有入度不是 0 的顶点,那就说明,图中存在环。
关于图中环的检测,我们在递归那一节讲过一个例子,在查找最终推荐人的时候,可能会因为脏数据,造成存在循环推荐,比如,用户 A 推荐了用户 B,用户 B 推荐了用户 C,用户 C 又推荐了用户 A。如何避免这种脏数据导致的无限递归?这个问题,我当时留给你思考了,现在是时候解答了。
实际上,这就是环的检测问题。因为我们每次都只是查找一个用户的最终推荐人,所以,我们并不需要动用复杂的拓扑排序算法,而只需要记录已经访问过的用户 ID,当用户 ID 第二次被访问的时候,就说明存在环,也就说明存在脏数据。
《卖桃者说》11月day27
轮子不要重复造
但是事实上你没必要这样做也不应该这样做。大厂研发力量雄厚,业务场景复杂,数据量大,自己从挖地基开始研发自己的推荐系统则是非常常见的,然而中小厂职工们则要避免重复造轮子。这是因为下面的原因。
中小企业,或者刚刚起步的推荐系统,要达成的效果往往是基准线,通用的和开源的已经能够满足;
开源的轮子有社区贡献,经过若干年的检验后,大概率上已经好于你自己从零开始写一个同样功能的轮子;
对于没有那么多研发力量的厂来说,时间还是第一位的,先做出来,这是第一要义。
既然要避免重复造轮子,就要知道有哪些轮子。
有别于介绍一个笼统而大全的“推荐系统”轮子,我更倾向于把粒度和焦点再缩小一下,介于最底层的编程语言 API 和大而全的”推荐系统”之间,本文按照本专栏的目录给你梳理一遍各个模块可以用到的开源工具。
这里顺带提一下,选择开源项目时要优先选择自己熟悉的编程语言、还要选有大公司背书的,毕竟基础技术过硬且容易形成社区
《碳中和极简入门课》11月day26
所谓碳达峰,就是温室气体排放达到最高值;所谓碳中和,就是总体而言不再排放温室气体。发展中国家有发展经济、改善民生的客观要求,但是存在技术落后,减排的成本高的问题,再加上发达国家的碳溢出效应,因而导致碳排放增加。
我们国家积极应对气候问题,制定了 30 年碳达峰、60 年碳中和的整体目标,这里面有能源安全、技术进步、大国担当和能源革命方面的考量。西方国家想用碳关税来迫使其他国家履行减排义务,但是也要遵循公平公正的原则,脱离实际情况是不可取的。
《技术管理实战36讲》攻克计划 11月day25
开始,你作为工程师,需要有很好的技术实操能力,这是作为工程师的职业素质。慢慢地,随着你能做的事情越来越多、越来越大,你会提升整体架构能力,成为一名架构师。而如果你对某个专业领域的技术越来越专精,你会成为一名技术专家或科学家。
当然,你也可以不断拓展自己项目管理能力和带团队的能力,这样你会成为越来越高级的技术管理者,也可以去创业公司做技术合伙人。当你越来越关注行业发展、商业逻辑、公司经营,就慢慢拥有了职业经理人和公司创始人的视角;当越来越关注资本运作和资本产生的价值,就会从投资人的角度去看待各行各业和整个社会。
这里我是按照视角的迁移和能力的扩展来阐述整个过程的,但是作为每个人的职业发展,却并不需要完全沿着这个过程,也并没有越后者越高级的说法,最终你会停留在自己喜欢和认同的角色上,那个就是最好的。
但是,无论你走哪条路上,你都会发现有些能力是共通的,比如规划、带人、沟通、执行等管理能力覆盖了全部 8 个方向。
因此,这里你还需要区分“技术管理能力”和“技术管理岗位”这两个概念。你可能出于兴趣、机遇等各种原因不会去选择做“技术管理岗位”,但是,“管理”作为一项综合能力,是你未来的职业发展所不可回避的,至少你都需要和管理者合作。只不过因为你的角色不同,需要掌握的程度不同。
总之,对于技术人来说,无论你是否做技术管理岗,你所有的职业发展,都会围绕着技术和管理这两条腿在走路,一条腿是走不远的。
《Android技术开发课》11月day24
什么是架构
什么是架构,每个人都有自己的看法。在我看来,所谓的架构就是面对业务需求场景给出合适的解决方案,使业务能够快速迭代,从而达到“提质增效”的目标。
我先举个例子,告诉你什么是架构,以及架构的作用。我曾经为了解决 UI 渲染卡顿这个需求场景,我们设计了异步创建 View、异步布局与主线程渲染这个架构。不过架构只是设计的抽象,对于具体的实现,我们可以称之为框架。好的框架可以隐藏大家不需要关心的部分,提升我们的效率。例如 Facebook 的 Litho、微信的Vending,它们通过框架约束和异步来解决 Android 应用 UI 线程卡顿问题。
如果说监控是为了发现问题,核心在于“防”,那好的架构可以直接避免出现问题,所以架构设计的目标在于“治”。为了帮助你更好地理解架构,我们先从 Android 的架构设计说起。
《超级访谈:对话道哥》11月day23
道哥:因为从逻辑或者说从数学的角度来讲,所有的定理或者说所有的推论和结论都是建立在一个前提假设之上的,这个前提假设在数学里叫公理。如果放到其他逻辑系统,实际上就是问题的前提。从几个简单的前提可以推导出所有的一切,真正大的改变和大的创新都是把这个前提或者假设改掉。
我来想想有没有什么合适的例子。阿里云的例子其实很典型。关于云计算,王坚博士是有非常明确的假设的,它是建立在 3 个基础假设之上的。首先,互联网成为基础设施;其次,云计算成为公共服务;最后,数据中心成为一台计算机。基于这三个假设,他推导出来了阿里云要做的一切。
如果这三个假设中有一个发生改变,那么后面做的所有东西都是错的。他的战略眼光在于他笃定地相信了这三个假设是未来。这也是他有勇气的地方,直接赌了。
再比如说自动驾驶遇到了很大的挑战,很可能是因为它的前提是虚假的。现在所有的城市道路是为人类的驾驶员设计的,而不是为机器设计的。光是这个前提的改变就意味着基础设施需要改变,这就变成了一件很大的事情。这也是为什么现在自动驾驶系统塞不进人类的城市。
《Kubernetes入门实战课》11月day21
只是有的应用的状态信息不是很重要,即使不恢复状态也能够正常运行,这就是我们常说的“无状态应用”。“无状态应用”典型的例子就是 Nginx 这样的 Web 服务器,它只是处理 HTTP 请求,本身不生产数据(日志除外),不需要特意保存状态,无论以什么状态重启都能很好地对外提供服务。
还有一些应用,运行状态信息就很重要了,如果因为重启而丢失了状态是绝对无法接受的,这样的应用就是“有状态应用”。
因为只使用 Deployment,多个实例之间是无关的,启动的顺序不固定,Pod 的名字、IP 地址、域名也都是完全随机的,这正是“无状态应用”的特点。
但对于“有状态应用”,多个实例之间可能存在依赖关系,比如 master/slave、active/passive,需要依次启动才能保证应用正常运行,外界的客户端也可能要使用固定的网络标识来访问实例,而且这些信息还必须要保证在 Pod 重启后不变。
Kubernetes 就在 Deployment 的基础之上定义了一个新的 API 对象,名字也很好理解,就叫 StatefulSet,专门用来管理有状态的应用。
Service 自己会有一个域名,格式是“对象名. 名字空间”,每个 Pod 也会有一个域名,形式是“IP 地址. 名字空间”。但因为 IP 地址不稳定,所以 Pod 的域名并不实用,一般我们会使用稳定的 Service 域名。
Service 发现这些 Pod 不是一般的应用,而是有状态应用,需要有稳定的网络标识,所以就会为 Pod 再多创建出一个新的域名,格式是“Pod 名. 服务名. 名字空间.svc.cluster.local”。当然,这个域名也可以简写成“Pod 名. 服务名”。
为了强调持久化存储与 StatefulSet 的一对一绑定关系,Kubernetes 为 StatefulSet 专门定义了一个字段“volumeClaimTemplates”,直接把 PVC 定义嵌入 StatefulSet 的 YAML 文件里。这样能保证创建 StatefulSet 的同时,就会为每个 Pod 自动创建 PVC,让 StatefulSet 的可用性更高。
《设计模式之美》11月day20
如果你是一名比较资深的程序员,最开始学习编程的时候,接触的是 Basic、Pascal、C 等面向过程的编程语言,那你对这两个概念肯定不陌生。但如果你是新生代的程序员,一开始学编程的时候,接触的就是面向对象编程语言,那你对这两个概念可能会比较不熟悉。所以,在对比面向对象与面向过程优劣之前,我们先把面向过程编程和面向过程编程语言这两个概念搞清楚。
实际上,我们可以对比着面向对象编程和面向对象编程语言这两个概念,来理解面向过程编程和面向过程编程语言。还记得我们之前是如何定义面向对象编程和面向对象编程语言的吗?让我们一块再来回顾一下。
面向对象编程是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石 。
面向对象编程语言是支持类或对象的语法机制,并有现成的语法机制,能方便地实现面向对象编程四大特性(封装、抽象、继承、多态)的编程语言。
《设计模式之美》11月day19
设计原则
在专栏的最开始,我们总结了一套评判代码质量的标准,比如可读性、可维护性、可扩展性、复用性等,这是从代码整体质量的角度来评判的。但是,落实到具体的细节,我们往往从是否符合设计原则,来对代码设计进行评判。比如,我们说这段代码的可扩展性比较差,主要原因是违背了开闭原则。这也就是说,相对于可读性、可维护性、可扩展性等代码整体质量的评判标准,设计原则更加具体,能够更加明确地指出代码存在的问题。
在专栏中,我们重点讲解了一些经典的设计原则,大部分都耳熟能详。它们分别是 SOLID 原则、DRY 原则、KISS 原则、YAGNI 原则、LOD 原则。这些原则的定义描述都很简单,看似都很好理解,但也都比较抽象,比较难落地指导具体的编程。所以,学习的重点是透彻理解它们的设计初衷,掌握它们能解决哪些编程问题,有哪些常用的应用场景。
SOLID 原则并非一个原则。它包含:单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)。其中,里氏替换和接口隔离这两个设计原则并不那么常用,稍微了解就可以了。我们重点学习了单一职责、开闭、依赖倒置这三个原则。
《Java并发编程实战》11月day18
解决并发编程里的分工问题,最好的办法是和现实世界做对比。对比现实世界构建编程领域的模型,能够让模型更容易理解。上一篇我们介绍的 Thread-Per-Message 模式,类似于现实世界里的委托他人办理,而今天介绍的 Worker Thread 模式则类似于车间里工人的工作模式。如果你在设计阶段,发现对业务模型建模之后,模型非常类似于车间的工作模式,那基本上就能确定可以在实现阶段采用 Worker Thread 模式来实现。
Worker Thread 模式和 Thread-Per-Message 模式的区别有哪些呢?从现实世界的角度看,你委托代办人做事,往往是和代办人直接沟通的;对应到编程领域,其实现也是主线程直接创建了一个子线程,主子线程之间是可以直接通信的。而车间工人的工作方式则是完全围绕任务展开的,一个具体的任务被哪个工人执行,预先是无法知道的;对应到编程领域,则是主线程提交任务到线程池,但主线程并不关心任务被哪个线程执行。
Worker Thread 模式能避免线程频繁创建、销毁的问题,而且能够限制线程的最大数量。Java 语言里可以直接使用线程池来实现 Worker Thread 模式,线程池是一个非常基础和优秀的工具类,甚至有些大厂的编码规范都不允许用 new Thread() 来创建线程的,必须使用线程池。
不过使用线程池还是需要格外谨慎的,除了今天重点讲到的如何正确创建线程池、如何避免线程死锁问题,还需要注意前面我们曾经提到的 ThreadLocal 内存泄露问题。同时对于提交到线程池的任务,还要做好异常处理,避免异常的任务从眼前溜走,从业务的角度看,有时没有发现异常的任务后果往往都很严重。
《超级访谈:对话玉伯》11月day17
玉伯:做基础技术的同学,往往做着做着,想去做业务。做业务支撑的同学,往往做着做着,会想去做基础技术。这就是一个围城,城外的人想进去,城里的人想出来。
回到一线同学,这个围城带来的困惑非常常见。技术人对自身价值认知的不同,到现在为止都是一个普遍存在的问题。但这个问题很难解,靠沟通是解不掉的。体验技术部的做法是,尝试每隔半年,如果有做业务支撑的同学想去做基础技术,且也有这个能力的话,那就调整一下。反之也一样,让想做基础技术的同学,能选择去做做业务。
调整完成后,往往能让同学有完全不一样的感受。比如调整去做基础技术的,会刚开始很兴奋,但很快会发现,做基础技术也有一堆 bug 要改,也有各种项目排期,跟在业务线接需求是一样的。
这就是个围城。做基础技术的,也有很多同学觉得基础技术很难拿 3.75 绩效,基础技术很多是长周期,有同学就等不及,觉得做业务更容易拿到结果,公司很多奖项、聚光灯都是放在业务上的。每个基础技术方向,往往要做到一定阶段才会被看见,大部分情况下会在边缘,别人看不见,各有各的难处。
调完之后,最大的一个好处,是可以让做基础技术的和做业务支撑的同学,能彼此互相理解了,能真正感受到,原来都挺难。有些同学,能在调岗后,更善于去观察别人,同时开始更了解自己,知道自己原来更适合做业务,或者更适合做基础技术,自己的心就能安定了。心的安定,需要亲身去试试,很难通过沟通来解决。
《超级访谈:对话玉伯》11月day16
玉伯:行业也没什么标准,只能说我的经验。去看一些中后台的操作页面,会发现其实很多时候,好用并不取决于长得是否好看,好用更多取决于产品的操作交互是否贴合业务场景。
分享个 Ant Design 在设计过程中的一个坑。我们内部有一个客户服务系统,Ant Design 在早期追求排版布局的美观好看。为了好看、有呼吸感,排版会比较大气,错落有致。但这种设计,对整个客服系统来说,就很痛苦了。后来我们才理解,一个好的客服操作页面,需要页面信息密度足够高,方便客服人员在一个页面里就能找到各种信息并做快速操作。这种情况下,别看页面上密密麻麻的,密密麻麻才好用,宽松排版虽然好看,但并不好用。
业界去讲体验不好的案例时,经常用的一个比喻是说飞机操作仪表盘是不好的体验,因为上面有非常多的按键,很不好用。但我要对这个说法打个问号,这很可能只是业界的一个谬误。如果真把飞机的操作盘简化成 iPhone 一样,那飞机可能就要失事了。要回到专业领域去思考,比如去调研真正在飞机控制室里的飞行员是怎么想的。我找过很多文章,到现在为止都没有看见真正从事飞机行业的人出来说话,都是一帮搞互联网行业的用户体验设计师在那里拿它举反例。
所以从好看到好用,我目前更多在做的事情是,让特定领域的设计师深入业务。目前语雀的 UED 在语雀团队,设计师必须懂业务,得去研究用户的场景是什么、用户的高频操作是什么,然后再回到设计上,考虑怎样做到体验最好。在这个过程中,大家在保证操作效率和好用的基础上,同样要保证好看,这个好看是指多数人默认的好看,不是设计师一人觉得的好看。通常好看是更容易做到的,好用是更难做到的。
在前端这块我们提过产品工程师的概念,在设计这块,我们也提过一个概念,叫产品设计师。我不大想提体验设计师的概念,我们更多倡导产品设计师。最终前端和设计,都要落回到产品上。做设计也好,做前端实现也好,有时候体验好了,产品也不一定好用,这是两回事。
《超级访谈:对话玉伯》11月day15
玉伯:前端的核心价值,可以等同为一个问题:“公司为什么需要前端团队?前端团队因何而存在?” 我找到的答案有三点。
第一点,前端可以为公司降本增效,这是一个基本盘的价值。一个公司要做互联网产品,可以采用外包的方式,也可以采用自建团队的方式。为什么阿里等互联网公司采用了自建技术团队,核心原因是,自建技术团队,可以让产品研发更快,质量有保证,整体可持续发展。
组织设计上,技术团队经常会集中在一起,前端团队往往也会集中在一起。集中可以带来效率提升。假设一个业务需要 30 个前端来支撑,放到我这里,可能只需要 20 人就能满足业务需求。因为集中化管理,可以复用专业经验,我们知道如何更高效更专业地支撑业务。前端团队放在一起,在判断需求的优先级时,全局取舍会更自然发生。当前端分散在各个业务时,好处是能形成自闭环,但会带来一个常见问题:零散前端往往会被迫接好多需求。一旦前端是集中的,同时前端人员整体又紧缺时,面对业务需求,前端往往就不会再无条件接需求了。在需求的取舍过程中,就砍掉了很多没必要做的需求。砍需求往往是对业务的最大提效,不做一些需求,反而能提升需求质量,最终让业务做对需求。
但如果自己就是业务方,独立负责一块业务,很多 Leader 肯定就会想自己闭环最好,不然还得等排期。还不如自己直接招几个人,这样更高效,这是人性。但实际上,需要大家更客观去看。早期自闭环,可以让业务从 0-1 更高效。发展到一定阶段后,特别是各个业务板块需要互相关联时,集中化的技术支撑,往往能复用专业能力,整体业务效能会更高。
我现在更能理解一句话:分工是整个社会效能提升的关键。工业社会的分工极大提高了社会运转效率。以前农业社会衣食住行所需要的东西都可以自己生产,这叫做自闭环,效率是极低的。正是因为有了社会分工,整个人类社会才飞速发展。
降本是最近几年才凸显。现在不少公司开始提经营责任制,各个 Leader 会更意识到要省钱。举个例子,设计师对业务来说很重要,但业务如果自己去招一个创意设计师,往往不如用设计大团队提供的创意同学,这样会更省钱。统一的设计或前端部门,可以整体统筹,议价能力也更强,可以非常实在地降低成本。
简言之,前端团队的存在,是因为技术专业分工能带来整体效能的提升。同时前端团队往往会是一个整体,集中化可以降低公司的整体成本。
《数据结构与算法之美》11月day14
短网址服务的两种实现方法。
第一种实现思路是通过哈希算法生成短网址。我们采用计算速度快、冲突概率小的 MurmurHash 算法,并将计算得到的 10 进制数,转化成 62 进制表示法,进一步缩短短网址的长度。对于哈希算法的哈希冲突问题,我们通过给原始网址添加特殊前缀字符,重新计算哈希值的方法来解决。
第二种实现思路是通过 ID 生成器来生成短网址。我们维护一个 ID 自增的 ID 生成器,给每个原始网址分配一个 ID 号码,并且同样转成 62 进制表示法,拼接到短网址服务的域名之后,形成最终的短网址。
课后思考
《Rust语言从入门到实践》11月day11
在同一时刻,同一个所有权变量的不可变引用和可变引用两者不能同时存在,不可变引用可以同时存在多个。可变引用具有排它性,只能同时存在一个。
借用结束后,原本的所有权变量会重新恢复可读可写的状态。不可变引用可以被任意复制多份,但是可变引用不能被复制,只能转移,这也体现了可变引用具有一定的所有权特征。所有权和引用模型是 Rust 语言编写高可靠和高性能代码的基础,理解这些模型有助于优化程序的效率,提高代码质量。
本文通过探索性的方式尝试遍历不可变引用与可变引用的各种形式和可能的组合,由此揭开了 Rust 中引用的各种性质以及同所有权的关系,并总结出了多条相关规则。看起来略显繁琐,但每个示例其实非常简单,理解起来并不困难。请一定记住,不要死记硬背那些条条框框,请你亲自敲上面的代码示例,编译并运行它,在实践中去理解它们。久而久之,就会形成一种思维习惯,觉得 Rust 中的这种设计是理所当然的了。
《B端体验设计入门课》11月day10
小白选手,怎么快速出效果?
如果你刚刚进入 B 端行业,完全没有做过大屏,也不会一些复杂的 3D 软件,那一定会感觉很困难。因为不会 3D 软件,连大屏的效果图都没有办法做出来,研发更不知道该怎么做效果。一些团队会选择找外包团队直接制作,我们也有过类似的阶段,但是这个费用非常高,有些大概要几十万。
所以,小白要面临的问题就是:怎么才能用更低的预算,更快地做出优秀的效果呢?
其实市面上已经有很多公司识别到了这个需求。这些公司基于自己的技术能力与相关案例,总结出了很多的案例和模板,也做出了 Web 端的 B 端 SaaS 产品帮助你解决这个需求。其中阿里也做出来一个不错的平台,叫做 ThingJS,里面基于制造业、智慧城市等等这些场景提供了一些比较基础的模板。如果你的要求不是特别高,场景也比较通用,那么这样的模板就是最佳的选择,既可以做出不错的效果,成本也会低很多。
会一些 3D 软件,怎么做得更好?
单一的内容对于 B 端来说意义不大,那和大屏互动呢?在大屏设计这节课中,我分享过如何做出更有价值感的大屏,如果你已经掌握了一些 3D 软件,那么结合 C4D 和 Octane render 就可以和研发配合输出一些更好的效果了。
《左耳听风》11月day9
流量调度的主要功能
对于一个流量调度系统来说,其应该具有的主要功能是:
依据系统运行的情况,自动地进行流量调度,在无需人工干预的情况下,提升整个系统的稳定性;
让系统应对爆品等突发事件时,在弹性计算扩缩容的较长时间窗口内或底层资源消耗殆尽的情况下,保护系统平稳运行。
这还是为了提高系统架构的稳定性和高可用性。
此外,这个流量调度系统还可以完成以下几方面的事情。
服务流控。服务发现、服务路由、服务降级、服务熔断、服务保护等。
流量控制。负载均衡、流量分配、流量控制、异地灾备(多活)等。
流量管理。协议转换、请求校验、数据缓存、数据计算等。
所有的这些都应该是一个 API Gateway 应该做的事。
下一页