包含标签 架构 的文章

『每个架构师都应该研究下康威定律』

InfoQ 中国在 2016 年,发表过一篇文章,杨波的《每个架构师都应该研究下康威定律》。这篇文章对当时的我,触动是非常深刻的。一些说不清道不明的经验,被别人用浅显易懂的道理,讲得一清二楚。 康威定律是很早就听说过的,后来陆续又有一些接触,每次时隔一段时间再做了解,就会有非常深的触动。我理解,原因无他,因为它聚焦在组织架构和系统设计的关系上,而这两者,一个是架构师目标,一个是架构师的手段/工具。文中用很简短的一句话,讲清楚了这中间的关系。 系统架构的目标是解决利益相关者的关注点。 这句话简直太重要,太精妙了。 1. 架构师的目标,是各个利益相关者的关注点 很多人对架构师的误解,都以为是架构师是技术执行,是 top-level coder,对 coding 的结果负责。这就犯了以表象取人的问题。为什么?我后面再提。 架构师首先应该关注的,是项目中,各个角色,各个利益相关者,他们的利益诉求,他们在项目中的焦点。根据这些焦点,得到一个权衡的方案,并取得最大限度的支持。 2. 架构是权衡的艺术 权衡的英文表述比较准确一些。trade-off 。利益交易和平衡。 权衡的方法是博弈,无论是纳什均衡还是帕累托最优,权衡目标是达成一个相对稳定的博弈结果。这个结果,就是架构的目标需求。 所以你看,脱离实际场景谈『架构』,本来就是虚空的。 3. 架构首先是业务架构,其次才是技术架构 道理很简单,业务架构往往涉及最直接的利益分配,从市场到产品到后勤保障,通常都对业务指标虎视眈眈。产品技术指标他们并不关心。 从工作流程上来讲,业务架构决定产品设计,产品设计决定技术设计。说业务架构是技术架构的前置步骤,一点不为过。 唯一的例外,可能就是大厂里面做平台产品研发的案例了。从无到有形成一个平台,比如阿里 IaaS 云。商业模式不清晰,业务架构反而受制于技术架构。不过这种机会今后出现的可能性,越来越小。 4. 技术架构是工具/手段 确定了各个 stakeholder 的 key points,剩下就是怎么做的事情了。技术手段、技术架构,不过是实现平衡的工具而已。通过技术架构,将权衡的方案,表达出来,这是一个称职的架构师,秀于外的工作。 我个人对架构师的定义是,以权衡项目中各个利益相关方的利益关注点为目标,以技术设计为工具和手段,以持续的产品技术服务为交付物的产品研发决策者。 所以回过头去看,架构师的工作中,技术架构的部分,优先级排不到前列,称得上是最基础、最『本分』的技能。技术好,技术设计灵活,不是一名架构师值得炫耀的资本。架构师值得炫耀的,是他能够在复杂纷扰的环境中,仍然可以理出线头,正确判断形势,做出合理的架构设计。 比方说,一名做 ToB 业务的 SaaS 平台架构师,既往工作中,以项目经理/甲方的利益诉求为主,以己方销售的利益诉求为辅,养成了习惯。一个需求做不做,怎么做,第一问己方销售/甲方,其次问项目经理,总可以得到答案。有一天,他去到一家做 toC 产品的公司任架构师,他面临的 stakeholders 发生了翻天覆地的变化,『甲方』成了成千上万的个体,怎么去问每个个体,他们的 key points 是什么?所以这位架构师的转变是,以直接上级的利益诉求为主,以产品经理的利益诉求为辅。那么,这个架构师,很明显就犯了最低级的失职。即便他的技术实力再强,首先目标就错了,谈何取得胜利? 雷军讲的,以战术上的勤奋,掩盖战略上的懒惰,大概也是说这个意思。 啰嗦一句。无论是 toC 产品还是 toB 产品,架构师首先应该予以重视的 stakeholder,都应该是财务上销项对应的一方。也就是为公司提供入账的一方。有人可能会觉得奇怪,toC 产品不应该是用户为首要的 stakeholder 吗?真不一定。如果是付费用户,那么他们是公司账上销项对应的一方,他们算首要的 stackholder。如果用户是免费使用公司服务,那么应该把他们看做产品/服务的一部分,把他们看做产品/服务的资源,而不是 stackholder。既然是资源,能为己所用就可以;既然是产品的一部分,只要产品不散就可以。不需要过多考虑免费用户的诉求和偏好。 有些免费产品讲情怀,前提是他们活着不成问题。没干爹可抱的企业,先把自己的财务账算清楚,努力维持公司现金流为正,先有资本活下去,才是正道。别人在山顶为踏足云顶做赋,那是情怀,你在山底谈云,那是浮云。 5. 架构不止『偏技术』,不是每一名架构师都需要『偏管理』的搭档 架构师的责任,是交付能够让至少大多数 stakeholder 满意的架构方案,并且落地执行,交付一个 predictable 的结果。……

阅读全文

用 openresty 来做 app api 接口的验真

app 服务器端的开发中,有一个百年不变的小东西:api 访问的验真问题。因为 http 协议是无状态的,每次 app 发起请求,我都需要验证这次请求的确是由真实的、授权的 app 发起,以此来阻止不诚实用户发起的攻击、数据爬取,确保产品的安全,和用户在产品上的信息安全。 JWT(JSON Web Token)是一个 http 之上的不错的 api 验真协议,结合 https,几乎可以安全地传输各种数据。最关键是,它原理简单,没用到啥黑科技,新瓶装老酒,但实用。 openresty 是春哥做的一款神器,在 nginx 上挂了个 lua 引擎,可以用 lua 脚本指挥 nginx 做很多事情。了解 lua 的童靴都知道,lua 的执行性能堪比 C++/Java 这些编译型语言,大家在一个量级。能做到这步,已经相当感人。用 openresty 来实现 jwt 协议,做 api 访问的验真,可以降低后台系统的复杂程度,同时还能提高系统鲁棒性,防止被恶意攻击时系统雪崩。 现在已经有 openresty 的 jwt 模块,叫 lua-resty-jwt 的,还有基于它做了二次封装的 openresty-nginx-jwt。 有了这个 jwt 的 openresty 模块,可以在 http server 这一层对 api 访问做验真,业务系统接收到的请求理论上都是真实的,避免调用庞大的业务系统做验真。这在收到 api 攻击的时候效果最明显,那时每次调用庞大的业务系统,加载若干组件,仅仅做了一次验真,然后就释放资源,销毁请求。简直是罪过。 话分两头说,直接上这个 jwt 模块存在一些风险。要在生产环境使用 jwt,还有一些工作必须做。 secret 的策略。jwt 协议中,并没有规定 secret 怎么来的,实际操作中,不同的 secret 策略会有不同的效果。 整个系统使用一个固定的 secret。不诚实用户可以注册账户,暴力穷举或内存搜索,得到 secret 明文。存在系统性风险。风险高。 一台服务器使用一个 secret,secret 写到 openresty 的配置中。仍然有上述问题,还增加了做负载均衡的难度。风险高。 一个用户一个 secret,openresty 根据用户信息取 secret 编解码。风险低,复杂度高。 api 访问日志需要保存。特别对验真失败的访问,要能有手段及时处理日志,分析风险,对恶意用户可以屏蔽 IP 等手段规避。 经过验真的 api 访问日志结合静态资源访问日志,可以模拟真实用户的访问场景。结合 lazy load 等前端技术,甚至可以判断出用户究竟看了几页,资源加载速度快还是慢。这么好的资源,不能浪费。 接上面。第一点好解决,一个 subrequest,或者单独给 lua-resty-jwt 一个 redis 存用户的 secret,就行了。第二点和第三点说的其实是一件事情,记日志,而且是把验真失败和验真成功的日志分开记。验真失败的日志需要参与在线准实时的计算,验真成功的日志打包保存,用来做离线的大数据分析,统计用户访问指标,优化产品。……

阅读全文