云原生时代的微服务架构

本篇分享主要围绕以下 4 个主题进行: 什么是云原生 ? 为什么要用云原生架构 ? 微服务的概念 微服务的技术选型 什么是云原生 ? 云计算和云原生 云计算不同于传统的自建机房,云计算就是将计算的抽象为基础设施然后通过网络分发,得益于云计算的无限扩展能力,使得“云计算”就像自来水厂一样,我们可以随时接水,并且不限量,按照自己家的用水量,付费给自来水厂就可以。以下云计算的五个基本特征。 以下是一些目前比较主流的公有云厂商: 云原生顾名思义,就是基于云计算特性所设计的应用服务,得益于云计算快速发展,基于云计算特性所设计的云原生应用相比传统的单体应用在安全性,扩展性,快速迭代,运维等各方便都有巨大的领先优势。云原生并不是指某一种技术,它是一种架构设计理念,只要符合这种架构设计理念的应用,都可以称为 云原生应用, 看看 CNCF 官方对于云原生的定义: 容器云技术的发展 云原生是依赖容器作为技术技术来实现的,但是容器并不是什么新潮技术,以下是容器云技术的发展历史,其中有几个关键的历史节点 早在 06 年的时候 Amazon 基于容器技术构建的 IaaS 平台 AWS,成为所有云计算厂商的鼻祖,由于技术领先的优势 AWS 现在依然也是云计算行业老大 13 年 Docker 的诞生进一步简化容器技术的使用门槛,Docker 公司自以为掌握云时代的核心技术,开始野心勃勃的有意挑战传统的云计算大厂例如 RedHat,Google 的江湖地位,公司股价也是一骑绝尘,却不料被 RedHat 联合 Google 发布的 Kubernetes 击溃,Kubernetes 的成功让大家以为容器技术并非云时代的核心技术,容器编排 才是核心技术。(备注:2020 年 K8S 官方宣布只要满足 K8S CRI 接口的容器均可以被 K8S 进行编排,Docker 被时代抛弃) 2015 年借助 Kubernetes 的成功,Google 宣布成立 CNCF 基金会,这是云原生时代的代表性的组织。致力于完善云时代的基础设施,帮助开发者构建更出色的产品 下图是 CNCF 的全景图: ...

November 30, 2021 · 3 min

基于 Spring Cloud 的微服务设计原则

最近几年微服务很火,大家都在建设微服务,如果不懂点微服务相关的技术,都不好意思跟同行打招呼了,也见过身边很多人在微服务踩过很多坑,我从 16 年开始接触微服务,有多家大型企业的微服务分布式系统的架构经验,所以就打算跟大家做一期关于微服务的分享,不过微服务和涉及的分布式计算非常的复杂,绝非是一篇文章就可以讲清楚的,本文只是从最简单的概念的基本使用带你入门,如果后续还有兴趣的话,可以查阅相关的文献和技术书籍去深入学习 本文的微服务分享以下三部分,总体大纲如下: 微服务的概念和原则(理论) Spring Cloud 如何低成本的实现微服务(实现) Spring Cloud 大型项目的架构方案(真实案例) 微服务的概念和原则 什么是微服务? 简单举例:看军事新闻的同学应该都知道,一艘航空母舰作战能力虽然很强,但是弱点太明显,就是防御能力太差,单艘的航空母舰很少单独行动,通常航空母舰战斗群才是主要军事力量,你可以把单艘航母理解为的单体应用(防御差,机动性不好),把航母战斗群(调度复杂,维护费用高)理解为微服务。 简单讲特征就是: 单体应用:简单,脆弱(某个模块出问题,整个系统不可用),战斗力弱,维护成本低 微服务架构:复杂,健壮(某个模块出问题,不会影响系统整体的可用性),战斗力强,维护成本高 大部分的开发者经历和开发过单体应用,无论是传统的 SSM,还是现在的 SpringBoot/Rails,它们都是单体应用,那么长期陪伴我们的单体应用有什么弊端?我们是面临了什么问题,导致我们要抛弃单体应用转向微服务架构?个人总结主要问题如下: 部署成本高(无论是修改1行代码,还是10行代码,都要全量部署替换) 改动影响大,风险高,测试成本高(不论代码改动多小,成本都相同) 因为成本高,风险高,所以导致部署频率低(无法满足快速交付客户需求) 当然还有例如无法满足快速扩容,弹性伸缩,无法适应云环境特性等问题但我们不一一详谈了,以上的问题,都是微服务架构要解决的问题,至于具体是怎么解决的,我们先放到后面再聊 解决什么问题,又引入了什么问题? 我们先看看微服务能带给我们什么?微服务架构的特点: 针对特定服务发布,影响小,风险小,成本低 频繁发布版本,快速交付需求 低成本扩容,弹性伸缩,适应云环境 我们知道一个朴素的理念,没有任何事物是完美的,任何东西都有两面性,有得必有失那么在选择微服务在解决了快速响应和弹性伸缩的问题同时,它又给我们带来了什么问题?个人总结如下: 分布式系统的复杂性 部署,测试和监控的成本问题 分布式事务和 CAP 的相关问题 系统应用由原来的单体变成几十到几百个不同的工程,会所产生例如包括服务间的依赖,服务如何拆封,内部接口规范,数据传递等等问题,尤其是服务拆分,需要团队熟悉业务流程,懂得取舍,要保证拆分的粒度服务既符合“高内聚,低耦合”的基本原则,还要兼顾业务的发展以及公司的愿景,要还要说服团队成员为之努力,并且积极投入,在多方中间取得平衡。 对于分布式系统,部署,测试和监控都需要大量的中间件来支撑,而且中间件本身也要维护,原先单体应用很简单的事务问题 ,转到分布式环境就变得很复杂,分布式事务是采用简单的重试+补偿机制,还是采用二阶段提交协议等强一致性方法来解决,就要取决对业务场景的熟悉加上反复的权衡了,相同问题还包括对 CAP 模型的权衡,总之微服务对团队整体的技术栈水平整体要求更高 微服务有应该遵循哪些原则? 古人云:兵马未动,粮草先行。建设微服务是需要建立长远规划,不是像写 CMS 那样建好数据库表,然后就开始干活,这样十有八九是会失败的。我们要进行微服务改造前,架构师要提前做好规划,我们把这里分为三步,前期阶段,设计阶段,技术阶段 前期阶段,大致要做好如下事情: 和多方充分沟通,确保能符合客户和组织的需求,并且得到认同 和团队沟通,让队友(开发/测试/运维)理解,并且积极投入 和业务部门沟通,指定版本计划和上线时间 设计阶段,参考 Sam Newman 的著作《微服务设计》,单微服务必须要满足以下的条件,才符合微服务的基本要求: 标准的 REST 风格接口(基于 HTTP 和 JSON 格式) 独立部署,避免共享数据库(避免因为数据库而影响整个分布式系统) 业务上的高内聚,减少依赖(从设计上要避免服务过大或者太小) 庞大的分布式系统,需要强大基础设施来支撑,微服务涉及哪些基础设施? CI/CD和自动化(分布式系统几乎不可能通过人工手动发布) 虚拟化技术(要保证微服务运行环境隔离,目前行业主流的是使用 Docker 容器) 日志聚合,全链路监控(高度可观察和分析诊断问题) 说了那么多,那什么样的情况下,你的团队不适合建设微服务?(请勿对号入座) 开发团队不具备自主性,所在组织对开发团队限制非常多(具体请参考 康威定律) 团队不熟悉业务,无法识别出服务的边界,进行合理的拆分(请参考 DDD 领域驱动设计) 微服务设计其实是很早就有的设计思想,因为随着虚拟化技术的崛起,微服务可以低成本的实现,所以也开始流行和兴起。 ...

September 14, 2020 · 3 min

从实践总结的几个 CodeReview 经验

资深的程序员都知道 Code Review 可以对代码质量,代码规范,团队代码能力提升带来很大的提升,还有著名的技术专家“左耳朵耗子”也说过: 我认为没有 Code Review 的公司都没有必要呆(因为不做 Code Review 的公司一定是不尊重技术的) 出自《程序员的练级攻略 - 修养篇》 国外很多技术公司都非常重视 Code Review 也都做的特别好,例如 Google,亚马逊,但是国内很多公司在践行 Code Review 的时候却是步履蹒跚,步步艰难,选用的方法不对,最终导致事倍功半的结果,总结一下我见过的几种情况: 因为 Code Review 导致团队成员之间相互指责,团队凝聚力产生间隙 Code Review 形式化,没有提升代码质量,减少 bug,反而降低开发效率 Code Review 确实产生了效果,但是因为流程太重,导致团队效率降低 我们也在践行 Code Review,探索的路上也遇到一些障碍和经验,总结分享一下,如果你也遇到这些问题,或许可以花一点时间读一读这篇文章,说不定会有帮助。 Code Review 能带来哪些好处,本文就不说了,大家都很熟悉了,本文主要简单说一下 Code Review 有哪几个基本的共识和原则: Code Review 高效的原则是用机器去做大部分的事情 Code Review 的时机(天时地利人和) 推行 Code Review 的关键原则 Code Review 高效的原则是用机器去做大部分的事情 不同的语言的格式和风格都是比较固定的,例如我最熟悉的 Java 语言常见的风格有以下几种规范: Order Java SE 的标准规范:https://www.oracle.com/technetwork/java/codeconvtoc-136057.html Google Java 开发规范: https://google.github.io/styleguide/javaguide.html 阿里巴巴 Java 开发手册:https://github.com/alibaba/p3c (国内常用) 还有我最近常用的 Ruby 语言,官方所推崇的几种风格规范: ...

August 25, 2020 · 1 min

技术管理者带团队的一些实践心得

前言 个人从程序员到技术 Leader 经历了不少的心路历程,我目前在带一支十几人的技术团队(控制团队人数主要是遵循亚马孙 CEO 贝索斯提出的两个披萨原则)我记得刚开始带团队的时候我是非常抗拒的,因为总觉得管理太多的“杂事”占用了我很多写代码的时间,包括目前虽然已经是一支十几人技术团队的 Leader,但是我平时也还是偏爱技术多一些,在业余时间都会抽空写写代码或者在 Leetcode 刷刷题,在从事管理工作这些时间里看过很多书,也踩过很多坑,总结了很多经验,想必也有很多程序员刚开始跌跌撞撞的走上技术 Leader 的岗位,所以想写一篇文章跟大家分享一下,希望可以帮助到需要的人,文章大纲如下: 技术管理者需要哪些综合能力? 如何才能在团队拥有 Leadership ? 从工程师到团队 Leader 有哪些转变 ? 如何提升技术团队的工作效能 ? 如何提升团队的凝聚力 ? 沟通的技巧 ? 管理者的自我认知和成长 技术管理者需要哪些综合能力? 如何才能在团队拥有 Leadership ? 既然说到管理技术团队,那么管理的对象自然就是程序员,那么程序员是一个什么样的群体?大多数程序员的特点是:“聪明且傲娇” 比如这个网上流传的段子,如何正确的向程序员提BUG: 技术 Leader 对个人综合素质要求很高(技术好的管理者,带技术团队是有一定优势的),先说说我认为技术 Leader 需要哪几个比较重要的综合能力 技术能力和基础知识(能看懂技术表象背后的原理) 沟通表达能力(逻辑,同理心,情绪控制) 业务抽象能力(架构和演化) 技术 Leader 必须要看透技术的本质,因为技术 Leader 平时的工作内容大多包含:技术选型,技术方案评审,代码审查,技术氛围的营造,如果管理者本身不是技术出身,可能无法和技术团队建立共识,沟通成本极高,最终让团队变成一个非常低效的组织,人浮于事,那么如何才能拥有这些能力,可以在技术团队拥有 LeaderShip ? 我个人总结有一下几点: 吃透基础技术和弄懂技术背后的原理(万丈高楼平地起,再流行的框架和技术,剥离华丽的外衣也离不开操作系统,网络,数据结构这些原理型的知识) 了解细节,永远在写代码(不熟悉代码就无法提出真正可落地的方案,就无法感知技术团队的痛点在哪里,也就无法团队提高效能) 持续的学习,持续的为团队带来新的知识和理解(技术 Leader 已经是团队技术问题的终结者,不可能再上传递了,所以不要成为技术团队的天花板) 有一个真心帮助大家的心态(帮助大家成长,提高效能,最终组织效能也得到提高,实现共赢的局面) 总结了以上经验和方法论之后,我们肯定会思考,上面所说的都只是过程和执行,那么管理者的目标或者说是工作的结果是以什么形式体现的? 总体概括来说的话,管理者的目标和工作结果主要体现在两方面: 做事:成本、效率、质量 带人:人才、梯队、成长 以上的方向又太抽象,其实管理者很多时间的大部分工作都在选择和权限,主要包含以下几个方面 有限资源的限定下,选择最大化的产出方案 做出符合当前环境的技术决策,帮助公司产品取得成功 用方法和工具不断优化和提升生产效率和质量 举一个实际的例子: 比如公司A在创业期,还没有稳定的市场和客户,这个时候技术管理者的决策要倾向成本 + 效率,例如:技术团队偏向全栈型,工作流偏敏捷,快速交付功能获取用户和市场的反馈用于升级和迭代产品 比如公司B在成熟期,有固定的市场和客户,行业已经没有新的蛋糕,这个时候需要比拼的就是效率 + 质量,技术团队偏向专家型,注重产品质量和客户体验用于形成行业口碑和用户粘性 从工程师到团队 Leader 有哪些转变 ? 其实工作变化还蛮大,所有很多人刚开始管理团队会出现很多的不适,我总结如下: ...

August 3, 2020 · 2 min

关系型数据库的基本设计原则

前言 工作的这些年发现一个比较奇怪的现象就是身边无论是工作十多年的老兵,还是初级刚入行的程序员,在高谈阔论技术和趋势的时候都是人工智能,大数据,区块链,各种框架,语言,算法,AI,BI,CI,DI…… 等等,倒是发现很少有人关注数据库,不知道是因为数据库感觉太低端还是太低调,总是不容易被人提起 技术就是这样,不太关注的地方就不会重视,越是不被重视的地方,掉进坑里的概率就会越大,所以就在这里给大家简单聊聊在使用数据库过程中有哪些防掉坑指南,也可以对刚入行的小朋友有一个提醒的作用,万丈高楼平地起,一定要先打好基础再去考虑上层的建筑,不要舍本逐末 本章主要分以下四个小节(预计读完 5 分钟左右): 数据库为什么重要 数据库有哪些使用技巧 数据库有哪些容易掉进去的坑? 深入学习数据库的建议 数据库为什么重要 很多人在开发过程中不太关注数据库,对于表结构的设计也没什么讲究大多属于“能用就行”,但是根据作者将近十年的开发经验来看的话,只要你是从事 Web 相关领域开发你就无法避免不和数据库打交道,在Web开发中大多功能操作本质上都是对数据库进行操作,不管你用是 Pythod,Java,Ruby 等语言进行 Web 开发,你其实都是在面向数据库进行编程,很多 Web 框架作者为了避免程序员接触数据库的相关知识甚至还封装了一层 ORM (Object Relational Mapping 对象关系映射),把数据库当做一个黑盒子,然后通过操作对象的形式来操作数据库 虽然某种意义上是简化的开发,对此我是持有保留意见的,因为对于程序员来说很有必要了解你的 SQL 语言在数据库是怎么执行的,你不仅需要使用 explain 执行计划来查看你的 SQL 是否高效(扫描行数,命中索引,回表,排序等),对比不同 SQL 的写法外,你还需要知道如何使用 show index 来查看你的索引是否高效(通过 Cardinality 由数据库评估),这些技巧很大程度依赖你对 SQL 的了解,SQL 对于程序员来说也是一门非常重要的技能,没错 SQL 就是操作数据库的语言,据我了解大多数的公司在面试的时候都会考察程序员的 SQL 功底,扎实的 SQL 功底不仅可以让你写出高性能的查询语言外,对于数据分析,报表统计也是有非常大的帮助 大多数商业公司的核心资产其实就是数据库里面的数据,是非常宝贵的财富,程序和系统挂了,最多就是一段时间不可用,大多是情况重启就可以恢复,但是是数据库不小心被误删了,如果是运维能力差的中小企业可能会面临倒闭的地步,从商业角度上来说数据库大多数软件公司的核心 很多程序员从菜鸟成长到高手,接触的项目从学校的"某某管理系统"到刚加入公司内部系统,然后再到大型分布式系统,在大型系统中,大多数人程序员通常遇到的第一个问题通常不是线程不够用,不是CPU负载过高,不是内存不够快,通常都是数据库扛不住压力了,为什么呢?数据库本身就基于磁盘的文件系统,每次读取数据都是通过 I/O 去访问磁盘,了解计算机原理的同学应该都知道,在冯诺依曼计算机体系结构里磁盘 I/O 号称是最慢的 I/O (毫秒级),通常在你的系统只有几千上万的数据量时,全表扫描通常不会有很大的延迟感,但是当你的存量数据达到百万千万时,那么一次普通的查询就会把你的数据库服务器撑爆,做过应用的人都知道,数据库挂了,不管是什么分布式,微服务的牛逼架构都基本没啥用了,唠唠叨叨说到这里,相信大家应该已经知道数据库的重要性的,后面我们再从数据库设计的角度来看下问题 数据库设计对系统的影响 这里我们简单做一个对比,良好的数据库设计可以为你带来什么 ? 减少数据冗余,避免数据维护异常 节省存储空间,高效的访问速度 糟糕的设计 ? 大量数据冗余插入,更新,删除异常 浪费存储空间,低效的访问速度 糟糕的设计(图) 比如说对于一个简单的年龄字段,严谨来说应该使用 tinyint(1字节)或者 smallint(2字节),但是你偏偏要用 int (4字节) 这就属于糟糕的字段选择,看到这里很多刚入门的同学就可能就会反驳了,这么在意空间利用是不是有点矫枉过正?包括存储已经很便宜了,还这么斤斤计较般的选择,反正最终实现的功能都是相同的,别人也看不出什么差别呀。对于这种观点其实我想反驳一下,这是典型的新手思维,你只在看到在单个字段上的空间节省,但是没有考虑过数据也是在持续增长,糟糕的设计越到后期增长成本会越高(这里就类似于 Java 的经典面试题,集合类 ArrayList 和 LinkedList 在少量数据对比时看不出时间上的差距,但是随着计算数据量的上升,消耗数据的差距也会越拉越大),等到了千万级数据量的时候,可能你设计的表和别人设计的表是相同的内容,但是你的表无端的多出几百G的存储空间,如果你的应用还是多数据中心的话,那么这种无端的空间浪费还会被拷贝几十倍到不同的数据中心,而且只要你的应用还在线上运行,那么这种增长所带来的成本还会持续上升,这里也仅仅只是说对空间的浪费,下面在分析表结构存储上,还会具体说一下糟糕的设计对于性能会有多大的影响,这对企业来说就是边际成本的递增,从技术和架构上来说就会让你的系统不具备可扩展性 ...

February 27, 2020 · 2 min