关于架构师:如何让技术架构师具有预知未来业务发展的能力-京东云技术团队

大家好,明天咱们来分享业务架构,然而咱们并不是以产品经理角度讲述一个业务架构是什么以及如何做?而是以一个技术架构师的角度,讲述如何承接业务架构或在没有业务架构的时候,如何判断业务变化趋势而对系统架构提前做出反馈。 一、产生背景研发人有技术架构,产品经理有业务架构(通常是一个人),当一个技术架构师不懂业务架构的时候,就会呈现如下对话。 技术工程师小王:“产品经理又改需要,昨天和我说订单依照库存状态拆分,我刚刚上线明天又和我说依照促销类型类型拆分” 架构师小孙:“业务原本就倒退迅速的,那天他还和我说想依据商品体积拆分的,被我挡了回去”。 技术工程师小王:“厉害,还是你有话语权”。 我置信大家常常遇到相似的问题,然而如果技术架构师懂业务架构,就会变成上面的对话场景。 技术工程师小王:“产品经理又改需要,昨天和我说订单依照库存状态拆分,我刚刚上线明天又和我说依照促销类型类型拆分,还好,你上次和我说这块规定是多变的,让我把不同订单拆分逻辑,拆分为原子化,我改下配置就搞定,不愧是架构师,你怎么晓得这块多变?难道会占卜?” 架构师小孙:“哈哈,预知将来原本就是架构师的职责”。 技术工程师小王:“快教教我吧”。 上面咱们就来学习下如何,如何让技术架构师具备预知将来业务倒退的能力。 二、解决方案技术架构师须要理解业务架构的常识,然而又不必像产品经理晓得那么多,例如价值链等等概念。他须要晓得的如何辨认业务倒退变化趋势,并把对应局部的技术架构做好结构化、扩展性。我明天就来介绍一个简略的办法- MIT常识模型。简略来说是 1:映射(Mapping) 2 辨认(identify) 3 询问(ask about) 映射(Mapping):所有的需要能够映射到如下系统化、结构化的语言,计算机程序是在什么样的场景(事件)下开始口头,程序须要读取哪些数据(实体),根据什么样的程序(流动)、规定(工作)由谁(组织/角色)执行,执行后会产生哪些数据(实体)。然而针对一个特定的场景来说,程序(流动)、规定(工作)由谁(组织/角色)是更容易多变的。 辨认(identify)&询问(ask about):所以咱们在和产品经理沟通需要的时候,最次要的是辨认程序、规定(组织/角色通常在权限零碎RBAC模型能够配置,能够不必多思考)。如何疾速辨认程序和规定呢? 1、 程序:一个场景通过的多个业务流动,这个通常产品经理的业务流程图会展现,例如商品引入性能,须要通过“洞察”、“选品”、“招商”、“法务”等多个业务流程节点。找到这个程序后,次要问产品2个问题就能够判断是否多变,“这个程序,是否在不同客户/渠道/品类等不同端或渠道不同”,“这个程序,是否因为短期上线压力,斗争只是做了简化”。通常产品经理在调研的时候会取得这个信息。如果产品经理不确定,能够让产品经理在调研下,有个这个信息,在零碎架构解决的时候,就能够有多种形式解决扩展性,能够做出多个微服务,或者利用流程引擎工具实现扩展性。 2、规定:通常是( IF A then B)模式,他通常在在每个程序节点上面,例如在商品引入的“洞察”的业务流动时候,如果发现有如下话术“如果商品是大家电,须要思考竞对价格因子”,“如果商品是畅销类型,能够不必参加洞察”等等。如果发现这类术语,根本能够判断是规定;当然还有些规定比拟荫蔽,须要咱们来开掘,例如案例中“订单依照库存状态拆分,我刚刚上线明天又和我说依照促销类型类型拆分”,这里其实并没有那么显著的( IF A then B)模式,然而通常有形容词的动词,都有可能变动(例如 依照库存状态拆分)。然而如果在开掘下或认真思考下,就能够看出进去这个两个拆分逻辑,肯定是有条件或程序的,否则同一个订单拆分会乱套的。如果在这个时候,咱们在诘问下产品2个问题,“1、这个规定,是否在特定的条件下才无效,例如客户/渠道/品类等不同端或渠道、时间段、优先级程序”。“2、这个规定,在不同客户/渠道/品类等不同端或渠道,还有可能其余规定“。同样,如果产品经理不确定,能够让产品经理在调研下,有个这个信息,在零碎架构解决的时候,就能够多种形式解决扩展性,最简略代码的能够做策略模式,或利用配置文件、规定引擎dools等实现扩展性。 三、案例剖析通过以上简略的模型,咱们就客户还原架构师小孙,在和产品经理沟通的需要场景。 产品经理小李:“这次咱们要做个业务,订单履约。这是我的PRD,明天咱们一起看下。。。。。。“ 架构师小孙:“PRD写的挺具体的。通过我这个PRD。咱们了解了订单履约大略要实现的性能,你看我这样说是否正确:订单履约性能需要,须要读取订单数据,在通过拆分、打标程序,产生多个拆单后订单,并传输给物流零碎。通常这些工作,由零碎主动解决无需人员干预。是吧? 产品经理小李:“是的,大的逻辑是这样的” 架构师小孙:“这里拆分、打标程序,否在不同客户/渠道/品类等不同端或渠道不同。是否因为短期上线压力,斗争只是做了简化?“ 产品经理小李:我调研了4个客户,3个订单渠道,以及竞品都是通过这个这几个环节。目前看没有在新节点的可能性。 架构师小孙:“好的,那我为了老本思考。我先把流程节点设计为固定,后续你这里发现有多变的场景及时告诉我,另外我看你在拆分环节,提到订单依照库存状态拆分,这里是所有订单都依照库存状态拆分吗?” 产品经理小李:“额,我我感觉是“ 架构师小孙:“我倡议你在调研下,不同客户/渠道/品类等不同端或渠道下,是否有不同逻辑”,通常在有形容词的动作,都是可能变动的。 —— 一段时间后 产品经理小李:“嗯是的,客户A说他们除了库存、还有运费、礼品卡、商品体积拆分逻辑,这些会依照程序来顺次进行“。 架构师小孙:“OK。这块我设计为可扩展性的” 四、总结陈说看,架构师有业务预知性或者业务敏感性其实挺简略的,就是找对地位,多问些问题,就能够为一线研发缩小很多工作量。这个能力在很多中央,也能够称为业务敏感性。所以零碎扩展性设计肯定离不开业务输出,然而如何通过几个简略的问题,就能够疾速找到业务多变的中央,就是我本次分享的MIT模型解决的。大家也能够请依据一个业务场景,按此MIT常识模型剖析下业务多变的点。 起源:京东云开发者社区 作者:京东批发 李春丽(未经受权请勿转载)

May 18, 2023 · 1 min · jiezi

关于架构师:软件架构生态化多角色交付的探索实践

作者:京东批发 李春丽 作为一个技术架构师,不仅仅要紧跟行业技术趋势,还要联合研发团队现状及痛点,摸索新的交付计划。在日常中,你是否遇到如下问题 “ 业务需要排期长研发是瓶颈;非研发角色感触不到研发技改提效的变动;引入ISV 团队又放心品质和平安,培训周期长“等等,基于此咱们摸索了一种新的技术体系及交付计划来解决如上问题。 背景嗨,大家都晓得软件研发须要许多角色独特合作,包含客户、产品经理、研发工程师、测试人员、施行经营团队等等。在这泛滥角色中,研发工程师的人数占比最高,然而研发资源毕竟无限,随着需求量一直减少,在我的项目中还会听到如下吐槽: 1、研发团队排期瓶颈,非研发角色感触不到研发技改提效的变动。 2、引入ISV 团队又放心品质和平安问题,而且培训老本高、周期长,在外围简单零碎中,不敢也无奈短时间大规模引入。 不过,如果有一种办法可能实现生态化交付和全民开发的愿景,那就能够解决上述问题了!这种办法能够让所有角色,无论是技术还是非技术的,以平安、更简略的形式参加进来。 这样一来,就能够在不减少团队人数的状况下,进步团队的吞吐量,实现更高效的需要交付,是不是很微妙呢? 挑战为了达到生态化交付和全民开发的愿景,咱们须要解决如下几个问题? 1、如何让非技术角色实现研发的交付? 2、如何让全民开发者残缺实现一个需要闭环,而非仅仅实现其中一部分需要? 3、如何解决交付中外围系统安全问题? 咱们带这几个问题看下解决方案。在讲技术计划之前,咱们先站在客户角度,从整体看一下,一个零碎的需要都来自哪里?而咱们都晓得比起从0-1新做一个零碎,二次扩大类需要更加简单,咱们明天就以二次扩大类需要动手和大家一起分享下,在京东智能供应链Y做的一些实际。 计划设计思路 如上图就是任意一个零碎中二次扩大类需要分类的最大汇合,次要有8类:API类、参数类、模版类,界面类、流程类、规定类及数据库类。 1、API类:次要是新增API和在原有API的扩大,例如,原有API上新增一些属性。 2、模版类:次要是新增一个模版。例如,制作一类新的合同模版或问卷调研,各部门填报填写。 3、参数类:次要是新增KV类的参数。例如,新增“是否包含自营商品“参数,并让这些参数在某些逻辑中起到作用。 4、UI类:次要是新增菜单、按钮、布局、图表、校验规定等。例如新增一个外呼按钮,并调用外呼零碎 接口。 5、流程类:在原有流程节点中新增新的节点。 6、规定类:在原有的规定前、后等,新增新的规定。 7、数据库类:在原有表中减少新的属性,或者新增一个子表。 8、最初还有一类其余:无奈划分为某一类,须要简单的逻辑解决实现。例如 数据重新聚合与逻辑运算 咱们就基于这些研发的需要类型,设计一套技术体系,实现生态化交付和全民开发的愿景。 技术计划 咱们把软件系统分成三层,建设残缺的全链路扩大技术体系,在把这些能力通过零低代码伎俩把他们进行买通、包装和凋谢,就能够实现屏蔽源代码的状况下,对系统进行平安、简略、闭环的二次加强,进而达到全民开发的指标。具体包含: 1、界面层:该层扩大次要伎俩就是零低代码技术。 2、接口层:该层扩大次要伎俩就是依附不同模型之前的映射来解决,而模型的扩大就能够依附对象扩大来解决。 3、服务层:该层扩大次要依附流程、规定引擎来实现,这个业界有很多开源工具,例如activity和drools等。另外还有很多场景是简单的逻辑变更,这个能够依附插件、事件驱动模式来实现。 4、模型层:该层扩大次要伎俩就是依附元数据驱动,通过依赖元数据对象,而非底层物理数据库。 以上能力,在通过最初零代码技术的加持和封装,实现可视化配置,造成一个工作空间,在对工作空间进行分角色受权,让不同角色以相熟的语言进行操作,这样就能够实现生态化交付和全民开发的愿景。 所以说扩大的技术体系不是一个繁多的解决方案,它须要零低代码、插件、业务事件、元数据驱动、流程规定引擎等技术独特合作才能够。而难点是这几个技术须要相互搭配好,实现扩大的互认,例如咱们在对象模型扩大中减少了一个属性,这个属性须要在界面展现、须要在接口中透传、须要在规定中校验,这就须要做好顶层架构设计。 咱们通过几个案例来形容,它须要和能够实现哪些能力? 案例案例1:让非技术参加进来,领会技术提效的变动需要形容:基于业务变动,一个外围零碎,需新增 “渠道类型” 这个属性,改变波及: 1、数据模型变动(技术上:数据库字段变动) 2、后端服务及规定变动(技术上:接口变动、对象变动、判断规定变动等)、 3、展示界面变动(技术上:UI 界面减少带数据权限的查问条件、表格新列及图表减少等), 也就是须要软件不同档次的进行变动。通常,这些特地技术的需要变更,只能技术排期做,然而通过这种新形式。产品经理/客户就能够在无需期待,7 分钟内,全程零代码的模式下实现。 1、在对象扩大中,减少新的属性。 2、在规定引擎中,基于新的属性,编排减少新的校验。 3、在界面扩大中,把在对象扩大中的新列拖拽进去,展现为查问条件,并制作一个新的饼状图展现到界面。 通过这个案例,也就是说咱们能够把黑盒的研发工作,平安、高效的交付给其非研发角色自助实现,晋升交付效率,减低沟通老本。另外还有一点值得一提,这种形式也让非技术人员,能够直观的感触到技术提效的变动。 案例2:不涉及代码状况下,实现平安一站式开发需要形容:基于业务变动,一个外围零碎,须要与客服系统集成,实现对某类非凡业务的客服外呼,改变波及: 1、新增一个外呼按钮 2、新增前端规定校验,只有履约数据滞留2天的才须要进行客服染指。 3、调用外呼接口,组装数据减少简单逻辑并传递。 4、发送邮件告诉相干角色。 同样,这些也是特地技术的需要变更,原来只能原厂技术开发来排期做,然而通过这种新形式。客户IT或ISV,就能够在不涉及代码的状况下,通过对立平台一站式实现需要的变更。 1、在界面层中,通过零低代码伎俩实现按钮新增。 2、在界面层中,通过零低代码伎俩实现规定校验的新增。 3、在服务层中,通过插件形式,实现代码逻辑解决,并调用外呼接口。 4、在服务层中,通过事件订阅形式,监听外呼状态,配置邮件模版,实现邮件主动发送。 通过这个案例,咱们能够看进去,业务需要具备多变性,不能仅仅依附一种伎俩实现扩大,须要多种形式进行搭配,能力实现大幅度提效。 完结其实零低代码、插件、业务事件、元数据驱动、流程规定引擎等技术在行业中并不是一个新事物,而这些技术能够相互搭配,实现完满集成和互认,让用户在一个平台针对不同业务的场景应用适合的技术,实现需要的自助化,是个难点。它不仅仅须要平台技术,还须要对业务零碎须要正当的形象、抽取。 最初,咱们在回过头看看最开始的技术挑战。是不是都解决了呢? 1、如何让非技术角色实现研发的交付?答:通过零低代码模式进行封装和凋谢。 2、如何让全民开发者残缺实现一个需要闭环,而非仅仅实现其中一部分需要?答:须要全链路凋谢和买通,并不仅局限一种技术手段。 3、如何解决交付中外围系统安全问题?答:屏蔽源代码的残缺扩大体系。

April 19, 2023 · 1 min · jiezi

关于架构师:架构师日记如何写的一手好代码

作者:京东批发 刘慧卿 一 前言在日常工作中,我常常听到局部同学埋怨代码品质问题,潜台词是:“除了本人的代码,其他人写的都是垃圾,得送到绞刑架上,重构!”。明天就来聊一聊,如何写的一手好代码。要答复这个问题之前,得先弄清楚一个问题,好代码的规范是什么?易浏览,可扩大,高内聚,低耦合,编程范式,设计准则......,要求不少,却很难度量。实则代码和文章一样,正所谓文无第一,武无第二。 这里不打算从规定宝典,最佳实际等方面动手,因为那将陷入到有数的规定细节中去,容易不得要领。这也是很多同学,学了很多当下最新技术,把握了N门编程语言,却始终没有显著晋升的起因。对于技术而言,底层的原理和运行法则是基本,它和编程语言,语法等应用层的重要水平是不一样的,切记不要进入这个误区。 技能的把握个别须要经验学习、模拟、思考、翻新四个过程,上面就分几个阶段来探讨一下,到底该如何疾速学习成长。 二 学习进去的代码学习意识如果说人生有什么捷径,寻找前人走进去的路,就算是捷径了吧。前人须要花了几年,甚至穷其毕生钻研的成绩,摆在那里,用还是不必?答案应该是必定的,接下来要做的,只是如何把它们找进去,联合当下的情景,在泛滥的解决方案中选出卓有成效的就能够了。 Henry Spencer曾说:“不懂 Unix 的人注定最终还要反复创造一个撇脚的 Unix”。 所以有必要建设这种意识:无效的学习是升高指标老本的最佳策略之一。这比本人摸着石头过河,在工夫老本上,会有很大的节俭,这还没思考物质和精力上的投入,各种试错,就更划算了。 抉择楷模既然是取经学习,就要学习优良的,胜利的教训,如此,雷同的精力投入,取得的回报往往更高。科班出身,或者正在和你同行的都不是好的抉择,你不晓得他们最终会不会误入歧途。所以抉择楷模时,肯定要跳出圈子,去找你能找到的最优质的的那些,你的抉择能够涵盖历史上,行业里,公司中各个维度。 学习的过程中,带着批评的思维去消化,只有这样能力改良翻新,所有的清规戒律都有其限定范畴,当限定边界突破了,之前的正确性,就值得你去狐疑。举个例子,很多编码标准里都有那么一条:“一行代码长度,不超过80个字符”。 它的来历是这样的:在很久很久以前,有一个很风行的人机交互接口(终端) 叫 VT100,用来解决字符/文本,起初其它的很多终端都是以它为规范。这个终端屏幕24行、80列,编辑器菜单还占了 4 行。所以,代码编写倡议是一个逻辑的解决代码,20行最佳、每行字符长度不超过80列。目标就是为了可视性(目之所能及)、可维护性。而现在显示终端的分辨率普遍提高了,所以降级调整标准并无不可,比方:“每行 120 个字符,每个函数体代码 80 行以内”。 所以,很多历史教训,理解其背地的运行逻辑,能力施展出它本来的作用。 学以致用大家常说万事开头难,到底难在哪里?难在信心上,难在门槛上。信心能够通过痛点和指标来牵引,门槛能够通过指标拆解来升高。高质量的实现某件事情,有很多迷信的工具和办法,比方:PDCA循环,SMART准则等,有趣味的,能够拓展学习。 这里想要表白的是,领有痛点和指标是可能坚持不懈的前提,因为在学习实际的过程中,可能练习中进行利用,并能取得实在反馈和回报,这是可能保持精进的原动力。否则就容易陷入,相似咱们背诵四级利用单词‘’“abandon”的魔咒,也不晓得从它开始背诵了多少遍了。 再举个例子,咱们须要做零碎模块解耦,调研下来,应用音讯队列MQ中间件,可能很好的解决咱们目前面临的问题。 第一步,开始学习无关MQ的常识,理解各种MQ中间件的实用场景,联合应用场景,给出具体中间件的选型;第二步,将MQ中间件引入到咱们的零碎中。应用的过程,就是一个一直发现问题,钻研起因,修复问题,总结经验的过程。如果没有实在的利用场景,往往会始终停留在第一步,重复开始,直到失去急躁,最终放弃。 小结想要写好代码,须要有学习的意识,至多可能晓得什么样的代码是好的,什么样的代码是有改良空间的。这种判断能力,须要通过一直的浏览各种类型的代码,从中找出楷模。材料的起源能够是经典书籍,好的开源我的项目,甚至是你身边的优良我的项目。同时也须要躲避一些误区: 工作上遇到的大部分问题,只有去寻找,都是有解决方案的。须要亲自下场试错,发明答案的场景,很少;教训都是有实用边界的,照搬的教训不肯定就适宜咱们,这须要理解教训背地的撑持逻辑,灵便的做出调整;学习指标的抉择是须要机会的,要有适合的实际场景,否则,往往会事倍功半,甚至大功告成;三 模拟进去的代码认知陷阱所谓代码模拟,不是简略的照猫画虎。而是遇到问题了,能够基于之前的学习积攒,可能疾速的找到优良的解决方案,并加以利用。能够是一个技术点,能够是一种模式策略,能够是一种解决方案,甚至是一种编程思维。 这个阶段通常处于认知模型的第二层:“晓得本人不晓得”。也是冲破认知极限,疾速成长的阶段。直观感触就是一个问题接一个问题,一个概念接一个概念,要了解和学习的常识太多了。这对集体的毅力和急躁是一个考验,很多人就是在这个阶段进入认知陷阱,最终转行了。 以终为始在实际过程中,会面临着要学的常识,要补的课,太多了:“计算机网络,应用服务,数据存储......”。计算机网络又蕴含运营商,光纤,电缆,域名,cdn,交换机,代理服务,http协定,客户端,浏览器,会话...,每一个节点又能够往下拆下去,感觉没有止境。 是须要全副弄懂再去入手吗?我到底是要做一个专才,还是成为一个全才?这个问题还要以倒退的眼光来看。上面就以市场人才发展观为例,开展探讨一下。 • T型人才 事实中往往是“T型人才”比拟受用,"一"示意有博大的知识面,"|"示意常识的深度。两者的联合,就是传说中的一专多能。特地是大公司,员工岗位分工比拟细,像螺丝钉一样,只有做好眼前的事件就好了。如果专之外加上多能,在横向上具备比拟宽泛的一般性常识涵养,而且在纵向的专业知识上具备较深的理解能力和独到见解,就有了较强的创新能力。 • 型人才 咱们晓得,因为行业的疾速迭代,叠加各种不确定性,有些岗位的合理性受到不同水平的挑战,失去竞争力,遭逢下岗的境遇。业内又喊出了“型人才”的概念。 型人才是源于新加坡的一种人才观,在T型人才的根底上,进一步进化。比T多进去的一竖,个别是源于兴趣爱好或工作所需,孵化进去的第二事业线。“两条腿走路”,势必有更强的抗危险能力,和更强的市场变动应答能力。 • 梳子型人才 梳子型人才更加形象了,多条腿走路,即在多个业余有深刻的专业知识,同时在顶层放弃一个一生学习的习惯。它代表着弱小的底层思维和逻辑能力,它决定了你是否具备常识迁徙能力,肯定要先夯实它,否则很容易变成三天打鱼两天晒网。 人的精力和能力是无限的,机会也不是人人都能碰上的,所以梳子型人才往往不是咱们的第一指标。咱们能够先从T型人才开始致力,时机成熟之后再往型,甚至梳子型人才上迈进。 以终为始,能力看得清脚下的路。对于技术的学习和利用也是如此,以后须要什么,就学习什么,深挖什么。有余力了,机会来了,就能够被动转身,再创辉煌。 小结学习实际阶段处于比拟吃力的爬坡过程。考验的是对实现目标的毅力和信心,意识到这一点至关重要。技术的钻研方向,深刻水平,还是倡议循序渐进,结合实际利用场景,先在以后畛域扎深扎透,再伺机倒退,多条腿并行。 四 设计进去的代码编程思维所谓编程思维,就是“了解问题,找出门路”的思维过程,它由合成、模式识别、形象、算法四个步骤组成。 一个简单问题会先被拆解成一系列好解决的小问题;每一个小问题被独自检视、思考,搜寻解决方案;聚焦几个重要节点,漠视小细节,造成解决思路;最初,设计步骤,执行,直至问题解决。编程思维并不是编写程序的技巧,而是一种高效解决问题的思维形式。 编码准则计算机是人造的学科,编码准则就三个字:好保护。如果思考指标诉求,可能还能够追加一条:“运行快”,但目前大部分利用场景,计算机性能曾经足够快了,很多时候,第二条往往被疏忽掉了。 开闭准则,KISS 准则,组合准则,依赖反转,繁多职责准则等大部分设计准则都是围绕着这个根本准则开展的。如果你感觉你的编码设计比拟顺当,老得腾出精力来调整保护,那么大概率这个设计是不合理的,你得想方法让本人从中解放出来。 理论编码过程中的各种标准束缚,比方:代码标准,设计模式,日志打印标准,异样解决策略,接口设计规范,圈复杂度等,参照根本编码准则去了解,就能想的通了。 抽丝剥茧所有的技巧都是建设在相熟的根底上,对于程序员来说,就是代码。浏览海量的代码,编写海量的代码,在这个过程中,一直的改良调优,是练就硬功夫的前提。上面就以案例的模式,为大家展示一下该如何浏览源码,借此晋升本人的设计能力。 案例是取自RocketMQ开源我的项目,你能设想上面这段代码为什么这么写吗? 代码出处:org.apache.rocketmq.store.logfile.DefaultMappedFile#warmMappedFile• 背景介绍 RocketMQ 应用文件预热优化后,在进行内存映射后,会事后写入数据到文件中,并且将文件内容加载到 page cache,当音讯写入或者读取的时候,能够间接命中 page cache,防止屡次缺页中断。这个办法的作用就是文件预热。 ...

April 6, 2023 · 1 min · jiezi

关于架构师:Java架构师十项全能40周完结无密计划v成本

download:Java架构师-十项全能40周完结无密打算v老本Java反序列化-CC2剖析如何应用PriorityQueue和TransformingComparator作为切入点和跳板首先,让咱们看看TransformingComparator类作为跳板是如何被调用到利用链的。public int compare(final I obj1,final I obj2) {final O value 1 = this . transformer . transform(obj 1);final O value 2 = this . transformer . transform(obj 2);返回this.decorated.compare(value1,value 2);}复制代码在TransformingComparator#compare办法中,调用transform办法来批改obj1和obj2的值。正是这种办法调用了利用链。让咱们看看PriorityQueue类是如何作为入口点应用的。公有void read object(Java . io . objectinputstream s)抛出java.io.IOException,ClassNotFoundException {//读入大小,以及任何暗藏的货色s . default read object(); //读入(并抛弃)数组长度s . readint(); queue =新对象[大小]; //读入所有元素。for(int I = 0;I <大小;i++)queue[I]= s . read object(); //元素保障处于“正确的程序”,然而// spec素来没有解释过那可能是什么。heap ify();}复制代码在PriorityQueue#readObject办法中,反序列化的数据存储在队列字段中,而后调用heapify办法调整数据,造成二进制堆。调整数据时,会对数据进行比拟,较小的数排在第一位。在比拟数据时,会调用compare办法,这样PriorityQueue类就与TransformingComparator连接起来了。看看这个操作是如何在代码中实现的公有void heapify() {for(int I =(size > > > 1)-1;I > = 0;我-)siftDown(即,(E)queue[I]);}复制代码在heapify办法中,通过向后挪动数字来调整数据。private void siftDown(int k,E x) {if(比拟器!=空)siftDownUsingComparator(k,x);其余siftDownComparable(k,x);}复制代码在向后挪动之前,会判断是否有比拟器,如果有,调用if中的办法,否则调用else中的办法。这里间接看I-minute办法,因为只有在有比拟器的状况下,才会调用比拟器中的办法来比拟两个数。private void siftdownsusingcomparator(int k,E x) {int half = size > > > 1;while (k <一半){int child = (kobject c = queue[child];int right = child+1;if(右<大小&&comparator.compare((E) c,(E) queue[right]) > 0)c =队列[child = right];if(比拟器. compare(x,(E) c)突破;queue[k]= c;k =孩子;}queue[k]= x;}复制代码如您所见,if中的办法调用comparator中的比拟办法来比拟两个数字。正是这一步容许PriorityQueue类作为入口点与TransformingComparator类作为跳板相结合。用优先级队列和转换比拟器结构poc首先是利用链。PriorityQueue.readObject()TransformingComparator.compare()ChainedTransformer.transform()InvokerTransformer.transform()复制代码开始构建概念验证公共动态void main(String[] args)引发异样{ ...

October 13, 2022 · 2 min · jiezi

关于架构师:阿里P8推荐的架构师学习路线惨遭泄漏一夜转发超10W

技术人P8什么概念?失常本科校招进阿里,6年以下别想P8,一般社招进入阿里,30岁以下P8简直没有,P8不仅仅是集体技术能力强,还有要有撑起整个团队的能力; 这位大佬在阿里曾经工作了8年,从刚开始的小菜鸟,再到当初P8率领几十人的团队,真是费尽了心血,他对本人的评估是:我除了耐性之外就只做了一件事件——扎实根底,复盘与总结,尤其是在做我的项目的时候; 认知常识积攒是一个“自下而上”的过程。这里是我的了解,当你上一门课的时候,你明确晓得这门课主题是什么,课程安顿是什么,每个单元外面会有哪些知识点,体系曾经很明确。然而认知常识积攒却更像是反向的:通过看文章看到一个乏味的知识点,是一个系统的全面,须要基于这个点缓缓顺藤摸瓜找到了所在的畛域,看到了更多的相干常识,在往上总结出一个主题。倡议是,不要在一开始就给本人的认知体系建设无比具体的构造,而是应该先建设最底层的一条条常识笔记,而后总结成专属于你本人的模块。 P8修炼手册(Java版)这位大佬就是这样做的,建设最底层的一条条常识笔记,而后总结成专属本人的模块和技术架构,这8年他一直的总结一直的精简,最终造成了这份——P8修炼手册(Java版); 这份笔记原来仅在团队外部流传,然而前段时间惨遭泄露,被人上传到互联网平台,一夜之间爆火,近80万的下载量,据说曾经有28人收到了大厂offer,作为互联网雷锋的我,这么好的笔记怎么能不给大家安顿呢; 这份笔记蕴含JVM、Java汇合、多线程并发、Java根底、Spring 原理、微服务、Netty 与RPC、Zookeeper、Kafka、数据库、算法、机器学习、云计算 等30+个知识点 因为文章篇幅无限上面就以截图形式给大家展现,须要残缺PDF版的敌人能够【点击此处即可支付】 目录一览JVM Java汇合+多线程并发 Java根底+Spring原理+微服务 Netty与RPC+网络 日志+Zookeeper+Kafka Rabbit+Hbase+MongoDB 设计模式+负载平衡 数据库+一致性算法 Java算法+数据结构+加密算法+分布式缓存 Hadoop+Spark+Storm YARN+机器学习+云计算 内容一览线程 Java&实现 Java线程池工作过程 Spring Netty与RPC 网络架构 Rabbit 数据库 加密算法 云计算 总结当初Java内卷重大,因为失常面试无奈疾速地筛选出人才,就好比一个富豪须要招一个司机,后果来了1000人来应聘,要想疾速招聘到适合的人选,那么面试官该怎么办?他只能去问一些比拟高端的问题,比方不是本科的淘汰,30岁以上的淘汰,不晓得齿轮传动原理的淘汰等等。 然而有没有人真正的静下心来去思考,是哪个阶段的内卷重大?你感觉阿里P7内卷吗?不要总是杞人忧天,技术人就是以技术为主,把技术提上来所有都不必放心; 如果想要解脱内卷的解放,那么这份P8修炼手册你或者该好好地浏览一下,残缺PDF版曾经整顿好,能够【点击此处即可获取这份文档】

September 15, 2022 · 1 min · jiezi

关于架构师:Java架构师成长直通车40周完结无密

download:Java架构师成长直通车(40周完结无密)OAuth2学习中的一些高频问题的QA对于OAuth2相信很多初学者都有一些疑难,胖哥将这些疑难一一收集了起来做成了QA,或者能帮助学习者。OAuth2相干的QA Q:OAuth2 的一些罕用场景? A: OAuth2次要用于API授权,是跨API服务之间授权的解决打算。它实用于单点登录(SSO)、微服务之间的授权鉴权、API开放平台等场景。 Q: 什么是OAuth2客户端? A: 在OAuth2授权服务器上注册为客户端,并获得专属client_id标识的才是OAuth2客户端。安卓利用、IOS利用、Web前端等客户端利用也要遵循这个原则,它们本身注册到OAuth2授权服务器才能成为OAuth2客户端,否则就不是OAuth2客户端,必须是它们本身,而不是撑持它们的后端服务。 Q:OAuth2 客户端为什么分为public和confidential两种类型,别离是什么场景? A:rfc6749#section-2.1 根据OAuth2客户端自身是否有能力保护客户端凭据(client credentials)的私密性,是否能平安地通过授权服务器对客户端的资质进行认证将OAuth2客户端分为机密客户端和公共客户端。大部分的后端数据服务都应该被注册为机密客户端;无奈保障自身凭据安全的都应该被注册为公共客户端,公共客户端是没有client_sercet的,间接注册到OAuth2授权服务器的执行客户端,不通过后端利用进行拜访令牌中继的都是公共客户端,例如在一些特定场景下需要直连授权服务器的Web利用、移动利用。 Q:OAuth2 的access_token和refresh_token应该间接返回给前端吗? A:能不能返回给前端取决于这个前端是不是间接在授权服务器的OAuth2客户端,如果不是,就不能持有access_token和refresh_token,access_token和refresh_token的签发目标只能是OAuth2客户端。如果暴露面放开,则很容易被盗用。 Q: 非OAuth2客户端的客户端利用既然不能间接持有access_token和refresh_token的话,应该如何获取授权状态? A:当授权胜利后,令牌和用户客户端侧可能借助于session或者cookie进行一个映射,当然也可能考虑计算出一个不通明令牌( Opaque Token )映射,具体根据业务考量。 Q:OAuth2中的scope是什么? A:OAuth2是一个授权框架,授权天然要划定一个范畴(scope),以保障OAuth2客户端在既定的范畴内行事而不越界。它起到的作用和RBAC中的role其实类似,都是用来限度资源的拜访权限的。 role针对的是资源具备者(Resource Owner),而scope针对的是OAuth2客户端。 当然openid是一个例外,这个是OIDC 1.0的标识,算一个关键字。 Q:OAuth2 中的登录页面和授权确认页面能不能用前后端分离的形式? A:很多开发者不心愿点击授权的时候被302重定向到授权服务器提供的登录页面,然而你得明确一个情理, OAuth2客户端和授权服务器之间并不是一个残缺信赖的关系。外卖小哥给你送外卖,你必定心愿发放给他的是一个临时门禁通行码,而不是一个罕用通行码。另外ajax无奈平安地处理OAuth2授权流程中的302重定向问题,这也是一个技术问题。 Q:OAuth2 客户端是否做用户认证? A:OAuth2本身并没有定义用户如何向OAuth2客户端认证身份,这里要和授权服务器上的用户认证区别开来。OAuth2客户端在实现授权时可能拿到授权凭据,然而并不能间接拿到用户信息,如果授权服务器提供了获取用户信息的资源接口,OAuth2客户端可能通过该接口尝试获取用户信息用来表明用户的身份,这取决于用户是否授权了OAuth2客户端这样做。OIDC 1.0补充定义了OAuth2客户端对用户进行认证的细节流程。 Q:OAuth2客户端认证是什么? A:confidential类型的OAuth2客户端诚然在OAuth2授权服务器注册,它们要根据一些策略(Client Authentication Method)来向授权服务器证实自己是非法的客户端。这样它们才能调用一些OAuth2规定的端点,比如/oauth2/token令牌端点、/oauth2/revoke令牌撤销端点等等。对于OAuth2客户端认证的细节可能参考胖哥专栏中的OAuth2客户端认证过滤器详解一文。 Q:OAuth2明码模式为什么被废除了? A:准确地说目前明码模式在OAuth2.1中被移除了,包含OAuth0、okta等出名三方授权服务机构都对明码模式进行了移除处理。明码模式诞生的时候,像React、Vue这种单页利用还没有衰亡,以至连框架都还没有呢。它更像一种为理解决遗留问题而采纳的过渡打算。在传统利用中,用户习惯了把明码间接交给客户端换取资源拜访权限,而不是跳来跳去去拉授权、确认授权。OAuth2诞生之时为了让用户从传统思维中慢慢转变过去就设计了这种模式。 它冲破了托付授权的模式,升高了OAuth2的安全性。更多的细节请参考我往期的相干文章。 Q:OAuth2中的资源服务器怎么讲? A:只需蕴含了需要OAuth2客户端携带access_token拜访的资源接口的服务器都可能认为是资源服务器,包含OAuth2客户端、OAuth2授权服务器都可能根据业务和架构承担资源服务器的功能。从用户(资源所有者)角度来说,存放用户可能授权的资源接口的服务器都可能是资源服务器。资源服务器可能对拜访令牌access_token进行解码、校验,并必定本次请求是否合规。 Q:微服务是否可能不使用OAuth2? 当然可能,OAuth2只不过是目前微服务访问控制的解决打算之一,并不是唯一选项。总结这就是最近胖哥被问的比较多的一些问题,相信能够帮助各位。OAuth2的货色并不简略,通过近三年内断断续续的学习,胖哥才完残缺全理解这个货色,所以各位学习者不要心急,学的枯燥的时候先晾一时间,学这个最重要的是理解它的概念和流程,这远比各种框架重要,OAuth2本身和语言是无关的。

June 12, 2022 · 1 min · jiezi

关于架构师:图灵JAVA互联网架构师五期学习分享

download:图灵JAVA互联网架构师五期java中的static关键字说明显还得靠JVM 前言Java中Static想必大家肯定使用过吧。他是用来润饰类或者成员变量或者方法的。对于Static的用法还是很简略的,因为他就是一个修饰词。然而如果不理解他润饰的作用原理的话,可能会闹出bug来变量那么咱们拜访对象中的属性天然也就存放在堆中的。然而当static润饰属性之后他就发生了变动了。 class Demo { //成员变量 public int num = 100; //动态成员变量 public static int count = 200; //动态方法 public static void method(){ System.out.println(count);} }复制代码num属性属于惯例属性,count属性属于动态变量。他们不只仅是名称上的不同。从JVM的角度看他的存放地位也不同。首先num依赖于具体的对象,所以他和对象存放在一起都是堆中。而count独立于对象。JVM中顺便有一块空间用于存放动态变量。这个空间咱们叫做方法区。方法除了润饰变量外,static还可能润饰方法。被润饰的方法咱们叫做动态方法 。动态方法的个性和动态变量一样都属于类而不是对象。动态方法外部只能拜访动态变量而无奈通过this对象进行拜访对象属性。总结下来就是动态方法外部只能拜访动态变量无法访问非动态变量。除了动态方法外,还有一个非凡的方法叫做动态代码块。这个方法不需要咱们筹备方法名,入参,出参等等。只需要筹备方法体。对于方法体外部和动态方法外部申请是一样的。 对于动态代码块和动态方法他们和一般方法还有一个重要的区别就是执行时机。动态变量与一般变量的区别就是内存分布地位,而方法是在栈中操作的,不涉及内存的存储,所以区别就是方法执行的时机。这里需要咱们提前了解点类加载机制。首先咱们一个类的加载分为五个过程。首先是加载class元信息,最初一步是进行初始化。至于后面三步咱们这里可能不理解。重点知道在类加载的最初阶段会进行初始化,而初始化的操作就是执行动态方法和动态代码块。从类加载过程中咱们也能够看的进去动态方法是不依赖于对象的调用的。因为动态方法中只能使用到动态属性。也就是说动态属性使用时还没有创建对象。这也佐证了动态变量不依赖对象的说法。总结本文次要讲解Java基础,请原谅我没有华丽的词藻渲染杰出的文章。诚然基础但经常是咱们容易忽略的学识点。只有不断的学习,才能不断的提高,对于static的进一步使用场景,目前我能想到的就是单例模式中会使用。

May 30, 2022 · 1 min · jiezi

关于架构师:企业级飞速低代码-这5个理由让软件架构师积极拥抱低代码

从防止技术债权到简化和整合业务流程到解锁单体零碎,低代码提供了速度和灵活性。 软件开发者和架构师已经有理由对低代码技术持狐疑态度,但明天,许多成熟的低代码平台使麻利开发团队可能进步生产力、减少品质、并频繁部署。开发人员应用低代码技术来构建应用程序、客户体验、门户网站、搜寻体验、工作流集成、数据管道、数据流、仪表板、测试自动化、机器学习模型和其余解决方案。 "低代码作为一个弱小的概念,其应用的规模将在2022年持续增长。它开释了IT资源,为业务部门提供了高度定制的软件,并最终反对继续的数字化转型。然而,它必须建设在可扩大的数据平台和严格的治理模式之上。否则,大量的定制应用程序会成为数据仓的噩梦"。Fluree的联结首席执行官和联结创始人Brian Platz解释了为什么往年对低代码技术有重大趣味,以及为什么这种状况会继续下去。 Platz 指出了几个软件架构方面的问题,这些是在抉择低代码平台时应该思考的因素。但也有很多益处,低代码能够解决一些长期的架构痛点,特地是对于开发和反对许多定制化应用程序的企业。本文将为大家分享一些行业专家对于技术组织为什么应该在其企业架构中拥抱低代码解决方案的见解。 防止产生技术债权依据对于日益增长的技术债权威逼的钻研,企业将超过40%的IT估算用于解决技术债权,而不是日常经营或构建新能力。所提到的两个最要害的问题是开发团队的人员流动以及太多的开发语言和框架。 低代码解决方案往往是可视化的编程范式,当新的开发人员被调配来提供反对时,能够更容易了解和保护。另外,低代码平台往往有API和其余规范的形式来扩大和对接代码,使其更容易找到和追踪应用程序流。 OutSystems的高级技术胜利经理Jay Parnau示意,低代码还简化了生产反对。"在应用低代码之前,我作为一个开发人员,有一半的工夫是用来防止产生新的技术债权,或者在凌晨2点他人的谬误导致系统瘫痪的状况下随叫随到。我晓得平台会反对我以正确的形式做事,而保护工作也只是过来的一小部分"。 迅速创立新的员工体验KNIME首席数据科学家和布道负责人Rosaria Silipo博士解释了低代码平台如何帮忙简化沟通和需要收集,疏导团队更快地建设员工体验和工作流利用。她说:"当试图与其余部门沟通时,低代码工具更容易。一个低代码的、基于可视化编程的工具可能是你与不太懂代码的部门进行沟通的无效计划。通过应用低代码工具,专业人士能够节俭贵重的工夫,这些工夫能够专门用于其余问题,包含那些须要编码的问题"。 Copado公司产品高级总监Gloria Ramchandi对此示意同意,并示意低代码也有助于开发团队满足构建和更新应用程序的业务需要。她补充说:"高级开发人员和架构师不得不跟上企业日益增长的需要,以更快地构建软件。用低代码平台突破代码阻碍,帮忙团队缩短重要构建的上市工夫,进步翻新的速度"。 简化工作流程和数据集成如果构建应用程序很容易,那么架构师如何防止应用程序孤岛?低代码如何帮忙集成应用程序、软件即服务和企业零碎之间的工作流程? Retool的开发者倡导者Chris Smith意识到了这种整合挑战。"商业软件世界越来越扩散,有数百个垂直特定的云应用程序,帮忙企业的每个功能区更无效地运作。随着这种状况的产生,这些应用程序须要整合到越来越多的业务工作流程中,这些工作流程是为每个企业定制的。开发人员拥戴低代码平台,因为它们提供了疾速、功能性的构建块,解决了这种零散的集成问题"。 这不仅仅是工作流程的整合。架构师还必须思考如何与越来越多的数据源对接。低代码能够成为连贯到多个数据源的简略办法。Silipo说,"数据源由不同的供应商领有,往往不提供规范的拜访模式。一个低代码工具可能会接手这个工作,并提供标准化的、容易拜访许多不同的数据源"。 实现更多业务流程的自动化在企业投资于改善员工体验和整合工作流程的同时,将业务流程中的步骤自动化也很重要。Cleo的首席执行官Mahesh Rajasekharan说,低代码是减少可自动化的内容和缩小人工流程的另一个抉择。 这场大风行是对许多企业和技术领导人的警醒。Rajasekharan说:"从COVID-19封闭中失去的一个重要教训是,意识到许多公司仍有许多手工业务流程,并看到在大风行期间这如何妨碍了他们的业务。为了实现新的自动化程度,公司将拥抱低代码技术,使他们可能主动解决任何事件,以打消外围创收流程中的危险和差距"。 通过解锁单体零碎减速数字化转型是什么在历史上妨碍了技术组织改善员工体验、简化工作流程、减少集成数据源的数量以及实现更多业务流程的自动化? 尽管个别的技术债权是一个挑战,但单体零碎是难以挪动的巨石。架构师如何确保明天开发的货色更容易保护、反对和扩大到将来的业务需要? 开发微服务和部署无服务器架构是可行的办法,但大多数组织无奈将这些架构利用于每个业务需要。OpenLegacy首席产品官Zeev Avidan示意,低代码提供了一种代替办法,能够成为IT的范式转变。 Avidan说:"低代码和无代码能够帮忙彻底改变IT的所有方面,从前端利用开发始终到最简单的传统集成。对于许多开发人员来说,数字化转型的一个次要阻碍是民主化地拜访驻扎在单体外围零碎中的数据和业务逻辑的挑战"。 毫无疑问,推动数字化转型的组织有越来越多的利用开发、集成和自动化需要。低代码平台容许架构师通过将反对代码选项用于最具战略性的商业案例,并将低代码作为其余业务需要的加速器,从而扩大企业的开发能力。

May 11, 2022 · 1 min · jiezi

关于架构师:开课吧WEB全栈架构师进阶指南30期

开课吧-WEB全栈架构师进阶指南(30期)download:网盘链接手把手教使用python实现人脸识别 什么是人脸识别人脸识别,是基于人的脸部特色信息进行身份识别的一种生物识别技术。用摄像机或摄像头采集含有人脸的图像或视频流,并主动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部识别的一系列相干技术,通常也叫做人像识别、面部识别。 目前的人脸识别技术已经非常成熟了,还发展成3D人脸识别。而且现在各大厂商也都提供了人脸识别的API接口供咱们调用,可能说几行代码就可能实现人脸识别。然而人脸识别的根本还是基于图像处理。在Python中最弱小的图像处理库就是OpenCV。 OpenCV简介OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可能运行在Linux、Windows、Android和Mac OS操作系统上。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。它轻量级而且高效——由一系列 C 函数和大量 C++ 类形成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。 OpenCV基本使用安装pip install opencv-python # 基础库pip install opencv-contrib-python # 扩大库pip install opencv-python-headless复制代码读取图片读取和浮现图片是最基本的操作了,OpenCV当中使用imread和imshow实现该操作 import cv2 as cv 读取图片,路径不能含有中文名,否则图片读取不进去image = cv.imread('1111.jpg') 浮现图片cv.imshow('image', image) 等待键盘输入,单位是毫秒,0示意有限等待cv.waitKey(0) 因为最终调用的是C++对象,所以使用完要开释内存cv.destroyAllWindows()复制代码 将图片转为灰度图OpenCV中数百中对于不同色彩控件之间转换的方法。目前最罕用的有三种:灰度、BGR、HSV。 灰度色彩空间是通过去除黑白信息来讲图片转换成灰阶,灰度图会大量缩小图像处理中的色彩处理,对人脸识别很无效。BGR每个像素都由一个三元数组来示意,别离代码蓝、绿、红三种色彩。python中还有一个库PIL,读取的图片通道是RGB,其实是一样的,只是色彩次序不一样HSV,H是色调,S是饱和度,V是光明的程度将图片转换为灰度图import cv2 as cv 读取图片,路径不能含有中文名,否则图片读取不进去image = cv.imread('1111.jpg') cv2读取图片的通道是BGR,PIL读取图片的通道是RGBcode抉择COLOR_BGR2GRAY,就是BGR to GRAYgray_image = cv.cvtColor(image, code=cv.COLOR_BGR2GRAY) 浮现图片cv.imshow('image', gray_image) 等待键盘输入,单位是毫秒,0示意有限等待cv.waitKey(0) 因为最终调用的是C++对象,所以使用完要开释内存cv.destroyAllWindows()复制代码 绘制矩形image = cv.imread('1111.jpg')x, y, w, h = 50, 50, 80, 80 绘制矩形cv.rectangle(image, (x, y, x+w, y+h), color=(0, 255, 0), thickness=2) ...

May 5, 2022 · 2 min · jiezi

关于架构师:Java架构师十项全能完结无密源码齐全

download:Java架构师-十项全能【完结无密源码齐全】Python 开发者可能都据说过鸭子类型和猴子补丁这两个词,即使没听过,也大概率写过相干的代码,只不过并不了解其背地的技术要点是这两个词而已。 我最近在面试候选人的时候,也会问这两个概念,很多人答的也并不是很好。然而当我向他们解释完之后,广泛都会恍然大悟:“哦,是这个啊,我用过”。 所以,我决定来写一篇文章,讨论一下这两个技术。 鸭子类型引用维基百科中的一段解释: 鸭子类型(duck typing)在程序设计中是动静类型的一种风格。在这种风格中,一个对象无效的语义,不是由继承自特定的类或实现特定的接口,而是由"以后方法和属性的会合"决定。 更通俗一点的说: 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可能被称为鸭子。 也就是说,在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。 咱们看一个例子,更形象地展示一下: 这是一个鸭子(Duck)类class Duck: def eat(self): print("A duck is eating...")def walk(self): print("A duck is walking...")这是一个狗(Dog)类class Dog: def eat(self): print("A dog is eating...")def walk(self): print("A dog is walking...")def animal(obj): obj.eat()obj.walk()if name == '__main__': animal(Duck())animal(Dog())复制代码程序输入: A duck is eating...A duck is walking...A dog is eating...A dog is walking...复制代码Python 是一门动静语言,没有严格的类型查看。只需 Duck 和 Dog 别离实现了 eat 和 walk 方法就可能间接调用。 再比如 list.extend() 方法,除了 list 之外,dict 和 tuple 也可能调用,只需它是可迭代的就都可能调用。 ...

May 5, 2022 · 1 min · jiezi

关于架构师:马SB-Java高级互联网架构师VIP课程17班2022最新

马SB Java高级互联网架构师VIP课程1-7班2022最新超清原画 残缺无密 包含所有视频课件以及源码 MP4格局 获取材料:网盘链接hashCode() 和 equals()的区别equals()equals() 方法用于比较两个对象是否相等,它与 == 相等比较符有着本质的不同。 在万物皆对象的 Java 体系中,零碎把判断对象是否相等的权力交给程序员。具体的措施是把 equals() 方法写到 Object 类中,并让所有类继承 Object 类。 这样程序员就能在自定义的类中重写 equals() 方法, 从而实现自己的比较逻辑。 hashCode()hashCode() 的意义是哈希值, 哈希值是经哈希函数运算后失去的后果,哈希函数能够保障雷同的输出能够失去雷同的输入(哈希值),然而不能够保障不同的输出总是能得出不同的输入。 当输出的样本量足够大时,是会产生哈希冲突的,也就是说不同的输出产生了雷同的输入。 暂且不谈冲突,就雷同的输出能够产生雷同的输入这点而言,是及其宝贵的。它使得零碎只需要通过简略的运算,在工夫复杂度O(1)的情况下就能得出数据的映射关系,根据这种个性,散列表应运而生。 一种支流的散列表实现是:用数组作为哈希函数的输入域,输出值通过哈希函数计算后失去哈希值。而后根据哈希值,在数组种找到对应的存储单元。当发生冲突时,对应的存储单元以链表的形式保存冲突的数据。 两者关系在大多数编程实践中,归根结底会落实到数据的存取问题上。 在汇编语言期间,你需要老诚恳实地对每个数据操作编写存取语句。 而随着期间发展到明天,咱们都用更便利灵活的高级语言编写代码,比如 Java。 Java 以面向对象为中心思想,封装了一系列操作数据的 api,升高了数据操作的复杂度。 但在咱们对数据进行操作之前,首先要把数据按照肯定的数据结构保存到存储单元中,否则操作数据将无从谈起。 然而不同的数据结构有各自的个性,咱们在存储数据的时候需要抉择合适的数据结构进行存储。 Java 根据不同的数据结构提供了丰富的容器类,便利程序员抉择适合业务的容器类进行开发。 通过继承关系图咱们看到 Java 的容器类被分为 Collection 和 Map 两大类,Collection 又可能进一步分为 List 和 Set。 其中 Map 和 Set 都是不容许元素重复的,严格来说Map存储的是键值对,它不容许重复的键值。 值得注意的是:Map 和 Set 的绝大多数实现类的底层都会用到散列表结构。 讲到这里咱们提取两个关键字不容许重复和散列表结构, 回顾 hashCode() 和 equals() 的个性,你是否想到了些什么货色呢?equals()力不从心下面提到 Set 和 Map 不存放重复的元素(key),这些容器在存储元素的时必须对元素做出判断:在以后的容器中有没有和新元素雷同的元素? ...

May 1, 2022 · 1 min · jiezi

关于架构师:奈学P8百万Java架构师3期

download:奈学P8百万Java架构师3期ZY复制下崽:https://www.zxit666.com/4520/React经典面试题-倒计时组件 闲聊对于面试大家经常吐槽:“面试造火箭,工作拧螺丝。”,从而表白了对工作内容和能力申请匹配不一的现状。 不排除有些公司想要探查候选人的技术下限或者说综合技术能力,心愿失去一个可拓展性更高的人才。也有些公司是不知道如何筛选候选人,所以随便找了一些网上的面试题,各种原理,细枝末节的货色。不是说这些货色不好,但我感觉首要考察候选人是否能够胜任该岗位,同时他假如能懂原理,还有细节,那天然是锦上添花。 闲话聊完了,对于React我感觉能考察实际能力一道题:怎么实现一个倒计时组件。 倒计时组件——需要描述:写一个函数式组件CountDown,设置一个传入最大值的属性,每一秒减一,直到为0。 问题怎么设计。import { useState } from "react"function CountDown({max = 10}){ const [count,setCount] = useState(max) useEffect(()=>{ if(count>0){ setTimeout(()=>{ setCount(count-1) },1000)}}) return <h1>{count}</h1>}export default CountDown复制代码如果我在父级改变了prop后要重置计数怎么做呢?咱们再用一个useEffect去进行处理: import { useState } from "react"function CountDown({max = 10}){ const [count,setCount] = useState(max) // 倒计时逻辑 useEffect(()=>{ if(count>0){ setTimeout(()=>{ setCount(count-1) },1000)}}) // 重置计数 useEffect(()=>{ setCount(max)},[max]) return <h1>{count}</h1>}export default CountDown复制代码setTimeout可能会造成内存泄露咱们怎么处理呢?通过useEffect的返回函数处理。 import { useState } from "react"function CountDown({max = 10}){ const [count,setCount] = useState(max) // 倒计时逻辑 useEffect(()=>{ ...

March 30, 2022 · 1 min · jiezi

关于架构师:如何成为阿里云P8架构师-当然是考取阿里云新版ACE认证啊

简介:阿里云新版云计算架构师ACE认证全面重构上线!为建设云计算生态畛域含金量第一的专家级人才规范和认证体系,影响泛云生态高层次技术人才,阿里云历时一年,组织近百位专家,对云计算架构师ACE认证进行了里程碑式降级重构!“如何成为阿里云P8架构师?”"当然是考取阿里云新版ACE认证啊!”阿里云新版云计算架构师ACE认证全面重构上线!为建设云计算生态畛域含金量第一的专家级人才规范和认证体系,影响泛云生态高层次技术人才,阿里云历时一年,组织近百位专家,对云计算架构师ACE认证进行了里程碑式降级重构! ------------------------------------------------------------------------------------------------------------- 阿里云新版云计算架构师ACE认证重构发布会&解读会-公布工夫-2022年3月28日 14:00 - 直播钉群-新版云计算架构师ACE认证解读群  31889256 -重磅嘉宾- 改革重点根据阿里云P8架构师能力模型进行设计,含金量大幅度晋升新增试验、面试环节,全副由阿里云P9技术专家组成考官团队新增阿里云技术专家寰球惟一编号-ACE00001开始排序新增配套证书&留念套装,蕴含定制化水晶杯,奖牌等新版ACE认证及相干学习内容将于发布会当天同步上线,敬请期待!!! 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

March 22, 2022 · 1 min · jiezi

关于架构师:2-月亚马逊云科技培训与认证课程精彩不容错过

备考训练营:AWS Certified解决方案架构师 — 助理级 2022年2月15日 | 10:00 – 12:00 课程介绍:本在线研讨会的内容是亚马逊云科技部署架构课程,面向筹备加入 AWS Certified Solutions Architect – Associate 考试的人员。 该考试用于测验考生在亚马逊云科技云上设计和部署可扩大、高度可用且具容错能力的零碎方面的技术专业知识。 指标客群: 筹备加入 AWS Certified Solutions Architect - Associate 考试的解决方案架构师学习过亚马逊云科技云部署架构课程(或具备等同程度的常识)具备至多一年的在 亚马逊云科技 平台上设计和部署可扩大、高度可用且具容错能力的零碎的实践经验至多在一种高级编程语言方面具备深厚的常识立刻报名:https://www.awsevents.cn/regi... 备考训练营:AWS Certified解决方案架构师 — 专业级 2022年2月22日 | 13:00 – 17:00 课程介绍:AWS Certified解决方案架构师 — 专业级认证验证了您在亚马逊云科技平台上设计分布式应用程序和零碎所需的高级技能和教训。该在线研讨会联合了亚马逊云科技高级架构培训课的内容来查看考试范畴,并指出特定的钻研畛域,从而帮忙您筹备考试。此外,每个学科畛域的样题能够帮忙您了解考试概念,您能够学习如何轻松地排除谬误答案。咱们建议您在加入在线研讨会之前实现亚马逊云科技上的高级架构课程。 指标客群: 筹备加入 AWS Certified Solutions Architect - Professional 考试的解决方案架构师立刻报名:https://www.awsevents.cn/regi... 尖峰学堂:亚马逊云科技云从业者根底课程——减速版 课程工夫:2022年2月15 | 14:00 – 18:00 课程介绍:本课程面向心愿全面理解 Amazon Web Services 服务的集体,学习本课程您无需受到特定技术角色的限度。 您将理解亚马逊云科技云概念、外围服务、安全性、架构、定价和反对,以构建您的云基础知识。在本课程中,您将学习: 定义云是什么以及它是如何工作的辨别云计算和部署模型形容 亚马逊云科技 云价值主张形容云的根本寰球基础设施比拟与 亚马逊云科技 交互的不同办法形容和辨别 亚马逊云科技 服务域给定场景,应用 亚马逊云科技 云服务确定适合的解决方案形容架构良好的框架形容根本的 亚马逊云科技 云架构准则解释独特责任模型形容应用 亚马逊云科技 云的平安服务定义 亚马逊云科技 平台的计费、账户治理和定价模型确定构建在云上的将来服务和开发指标客群: ...

February 10, 2022 · 1 min · jiezi

关于架构师:菜鸟架构师之路初入社会

接下来的文章,我会先回顾我从出校园踏入社会后的个人经历,从一个菜鸟的视角来看,如何一步步登堂入室。因为本人最近又有点飘了,所以文章是除了给大伙看,也更是给本人看的哈哈。可能大家更想看技术类的文章,然而其实自己比起很多人来说技术并没有相对的劣势,写的也不肯定比他人好,置信我的个人经历应该会给大家更大的收货。遐想当年,沉迷游戏不可自拔的我,挂科有数,甚至大四还在补考高数,最初勉强过了,否则可能连证都拿不到,毕设也是用的以前的我的项目。而后在招聘会上,还要靠导员带着找工作。这里真的要感激我的辅导员,过后对我这样的学生也不离不弃,最终帮我找到一份对我来说很不错的工作。然而当初想想真是可悲,过后的我甚至没意识到一个大学生还要被这样关照,是有多能干,像个巨婴一样。 入职9月份的第一天,终于是入职了。跟大部分大学生一样,刚进入公司的我,对所有都感到离奇,然而试用期考核成为了我的第一道难关。就是一个简略的练手类的带web页面的我的项目,基于公司现有的根底框架,期限是三个月。过后的我还是懵懵懂懂的,足足花了两个月,才大略明确是怎么回事,开始入手写,后果还没写完,就有一个项目组因为紧急缺人,就让我间接转正而后过来声援我的项目。对我来说算是运气不错,因为如果走最终的问难,我都没有把握能过。 第一个我的项目公司是给南方电网做信息管理系统。我加入的项目组,是这个大的信息管理系统下的一个子系统开发。过后其实零碎曾经上线了,客户又提出很多新的需要,工夫比拟紧急。那时候还没有什么前后端拆散,用的老式的 SSH(Spring+Struts+Hibernate),页面JSP+JQuery,所以开发要既写后盾又要搞前端。 我接到的第一个工作,是在一个数据表格上方增加一个下拉列表,作为筛选条件。其实就是一般的html的select标签,提交查问表单的时候,将下拉列表的值一并提交即可。 跟大伙一样,第一次接到正式工作,很冲动,想好好的体现本人,尽管只懂一点java,尽管不晓得jQuery是什么,然而我有一颗向上的心啊,只有致力,没有什么搞不定。于是埋头苦干了几天,期间还自学了jQuery,终于是把性能开发了进去,并且在没有告知导师的状况下,偷偷合并到当期要发版的版本中,筹备来个一举成名(过后公司的发版流程很不欠缺)。 最初的后果,的确是“一举成名”了,用户只有不点筛选条件还好,只有选了条件,就什么数据也查不进去。于是,该问题被定义为线上重大问题,连用户都投诉过去,我的导师临危受命,迅速修复了问题而后从新上线恢复正常。 起初,导师只是简略的跟我说了新人没教训很失常,当前改好之后要通过他评审,再公布,而后,就没有而后了。 总结尽管对导师和公司感激涕零,没有因为这个事件间接把我开了,然而当初回过头来看看,其实他们这样做并不齐全对。首先,咱们列一列这次事变的几宗罪: 作为一个菜鸟,自作主张的设计与开发,没有通过导师评审和测试组验收导师对于新人关注度不够,不晓得新人做了什么公司的开发流程制度不欠缺,开发的内容能够随便就上线没有预先总结,包含公司和本人,对于本人和其他人都没有意识到问题的严重性,导致后续仍然呈现过相似的恶性问题。咱们来看看在这个事件上,菜鸟同学应该怎么做才对? 1. 首先,作为新人,肯定要多跟本人的导师沟通,包含但不限于指标,设计,进度,成绩等。导师不只是一个陈设,而是公司提供给新人的一项重要的资源,你有短缺的权力去尽可能的利用这份资源来让本人成长起来,融入到公司。这里说一下集体对资源的了解,资源不只是物质(钱,文档资料),工夫、能力、人脉、公司里的领导共事等,都能够是你的资源,作为一个胜利的职场人,肯定是尽可能的抓住无限的资源,来实现自我贬值,尤其是在当下这么内卷的各行各业,资源更是弥足珍贵 2. 要敢于承担责任,并做好总结,以此为警示本人及别人不再犯反复的谬误。在下面这个栗子中,如果是当初的我,我会跟领导被动抵赖本人的谬误,并被动请缨修复,当然会借助导致的力量,而后在导师和测试的验收后再上线,同时预先写总结,并将此次事变中暴露出的问题报告给领导,尤其是流程制度,须要严格执行 明天的文章就先到这里了。初入社会就遭逢如此难关,咱们的菜鸟同学会如何应答呢?且听下回分解。

October 13, 2021 · 1 min · jiezi

关于架构师:友邦人寿引入阿里云PolarDB云数据库支撑保险业务系统加速上云

简介:友邦人寿日前减速重要业务零碎上云过程,包含保险出单、保单契约等在内的数十套业务零碎,开始采纳阿里云PolarDB云原生数据库,通过全面代替传统商业数据库,进一步晋升业务零碎性能,为最终用户提供最稳固、牢靠的服务。8月4日,记者采访获悉,友邦人寿日前减速重要业务零碎上云过程,包含保险出单、保单契约等在内的数十套业务零碎,开始采纳阿里云PolarDB云原生数据库,通过全面代替传统商业数据库,进一步晋升业务零碎性能,为最终用户提供最稳固、牢靠的服务。 友邦保险是一家领有100多年历史的国际化保险公司,2020年位列财产500强榜单第250名,在中国边疆、中国香港等亚太地区的18个市场开展业务。友邦人寿是友邦保险在中国边疆的寿险子公司,也是中国边疆首家获批的外资独资人身保险公司。 最近几年,友邦人寿放慢数字化转型步调,推动中国区业务零碎全面迁徙上阿里云。在上云过程中,友邦人寿减速采纳云数据库,以代替应用多年的传统商业数据库。截止目前,包含保险出单、保单契约等在内的数十套业务零碎曾经全面采纳阿里云PolarDB云原生数据库,大幅晋升了业务零碎性能,弹性应答“开门红”等业务顶峰。 以保险契约零碎为例,在整个保单销售的过程和每一笔保单正式生成之前,友邦人寿、营销员、最终客户等都须要进行大量的查问操作,每一单都须要成千盈百次的读申请。友邦人寿通过引入阿里云PolarDB云数据库,利用其优异的一写多读性能,轻松解决了此类问题。 友邦人寿云计算架构师罗林强示意,保险行业的“开门红”流动,相似电商的双十一大促,有典型的流量洪峰,对于这种业务特点,阿里云PolarDB云数据库能够轻松应答。随着公司减速全面上云,云数据库将会成为各类业务零碎的重要技术撑持。 据介绍,阿里云自研了PolarDB云原生数据库,性能比MySQL高6倍,老本只有传统商用数据库的1/10。过来十多年,阿里云在产品技术畛域停顿迅猛,取得市场宽泛认可,并作为中国惟一的科技厂商胜利进入Gartner寰球数据库领导者象限。目前已有超过15万数据库客户迁徙到阿里云上,蕴含政务、批发、金融、电信、制作、物流等多个畛域的龙头企业。 文章起源:财经头条 相干浏览: 删库跑路?别怕!PolarDB-X 轻松援救误删数据的你 阿里13篇论文入选数据库顶会 PolarDB翻新技术架构获认可 上海ACE同城会演讲实录|云原生分布式数据库PolarDB-X PolarDB-X 是如何用15M内存跑1G的TPCH 顶会点赞!PolarDB Serverless实现了哪些冲破? 云原生分布式数据库PolarDB技术深度解密 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

August 6, 2021 · 1 min · jiezi

关于架构师:架构实战营

download:极客大学-架构实战营public class Sort { public static <AnyType extends Comparable<? super AnyType>> void insertionSort(AnyType[] a) { insertionSort(a, 0, a.length - 1);} private static <AnyType extends Comparable<? super AnyType>> void insertionSort(AnyType[] a, int left, int right) { int j; // 记录第一个比tmp小的元素的后边一位的地位for (int p = left; p <= right; p++) { AnyType tmp = a[p]; for (j = p; j > left && tmp.compareTo(a[j - 1]) < 0; j--) { a[j] = a[j - 1]; } a[j] = tmp;}} ...

July 26, 2021 · 3 min · jiezi

关于架构师:架构之路数据库基础2-函数依赖与Armstrong公理

函数依赖: 依赖关系: 平庸依赖:本人确定本人(AB列推出A或者B)非平庸依赖:本人确定其他人(AB推出C或D)齐全依赖:多个列能查出某个列,缺一不可,(AB->C,AB缺一不可)关系式概念:(理解Armstrong的六大实践) 键 超键(汇合中蕴含没有用的键超出键、多余键):惟一值的汇合。比方(姓名,性别,年龄)惟一,所以是一个超键 //这个概念很多人都了解谬误,需重点留神主键:也能够是汇合,其中没有多余键。 明确“联结主键”候选键:都有资格当主键。外键:另一个关系中的主键。主属性/非主属性 主属性: 主键中的属性非主属性:非主键中的属性全码 关系中的属性都是主键,这个关系成为全码==ArmStrong公理==略。一共六条,均为根本的数学常识,不赘述。

July 26, 2021 · 1 min · jiezi

关于架构师:724-杭州站-阿里云-Serverless-Developer-Meetup

简介:收费报名加入阿里云 Serverless Developer Meetup 杭州站,与技术大咖一起玩转 Serverless !!流动报名链接:http://hdxu.cn/S6Qzf夏日限定,阿里云 Serverless Developer Meetup 来杭州啦!全新单元 Serverless Workshop 首次倒闭,招集 30 位 “爱入手” 的开发者! 本次沙龙特地邀请来自阿里云、初创互联网公司、开源中国 Gitee 的技术专家和独立开发者,分析 Serverless 的典型利用场景和案例,分享初创企业落地 Serverless 踩坑教训和播种,破解 Serverless 弹性伸缩和跨云部署难题,现场公布开源我的项目 Serverless Devs 全新性能。收费报名即可来现场与 Serverless 技术大咖实操 Serverless。让咱们一起把握云计算将来方向,共享 Serverless 带来的技术红利! 流动工夫:7 月 24 日 13:30 - 17:30 流动地点:浙江省杭州市良睦路 999 号乐佳国内 1-3-7 特洛伊星 流动亮点Serverless Devs 全新性能公布,像淘宝一样享受 Serverless初创互联网公司 Serverless 落地和踩坑全记录架构师视角:Serverless 利用典型场景及案例分析如何破解 Serverless 弹性伸缩和跨云部署难题?Serverless Workshop 首次倒闭报名形式形式 :点击链接关上报名页面:http://hdxu.cn/S6Qzf 现场福利流动议程 阿里云 Serverless Developer Meetup 上海站精彩回顾 https://mp.weixin.qq.com/s/cjIBcTYeOEVm3xUxxhYLHg 阿里云 Serverless Developer Meetup 北京站精彩回顾 ...

July 14, 2021 · 1 min · jiezi

关于架构师:深入理解领域驱动设计中的聚合

简介:聚合模式是 DDD 的模式构造中较为难于了解的一个,也是 DDD 学习曲线中的一个要害阻碍。正当地设计聚合,能清晰地表述业务一致性,也更容易带来清晰的实现,设计不合理的聚合,甚至在设计中没有聚合的概念,则相同。 作者 | 嵩华 起源 | 阿里技术公众号 聚合模式是 DDD 的模式构造中较为难于了解的一个,也是 DDD 学习曲线中的一个要害阻碍。正当地设计聚合,能清晰地表述业务一致性,也更容易带来清晰的实现,设计不合理的聚合,甚至在设计中没有聚合的概念,则相同。 聚合的概念并不简单。本文心愿能回到聚合的实质,对聚合的定义和实操给出一些有价值的倡议。 一 聚合解决的外围问题是什么咱们先来看一下在 DDD Reference 中对于聚合的定义。 将实体和值对象划分为聚合并围绕着聚合定义边界。抉择一个实体作为每个聚合的根,并仅容许内部对象持有对聚合根的援用。作为一个整体来定义聚合的属性和不变量,并把其执行责任赋予聚合根或指定的框架机制。这是典型的“模式语言”,阐明了聚合是什么,聚合根(aggregation root)是什么,以及如何应用聚合。然而,模式语言的问题在于适度精炼,如果读者曾经相熟了这种模式,很容易看懂,然而最须要看懂的、那些尚不够相熟这些概念的人,却容易感到不知所云。为了能深刻了解一个模式的实质,咱们还是要回到它试图解决的外围问题上来。 在软件架构畛域有一句名言: “架构并不禁零碎的性能决定,而是由零碎的非功能属性决定”。这句话直白的解释就是:如果不思考性能、健壮性、可移植性、可修改性、开发成本、工夫束缚等因素,用任何的架构、任何的办法,零碎的性能总是能够实现的,我的项目总是能开发实现的,只是开发工夫、当前的保护老本、性能扩大的容易水平不同罢了。 当然事实绝非如此。咱们总是心愿零碎在可了解、可保护、可扩大等方面体现良好,从而多快好省的达成零碎背地的业务指标。然而,在事实中,不合理的设计办法有可能减少零碎的复杂性。咱们先来看一个例子: 假如问题畛域是一个企业外部的办公用品洽购零碎。 企业的员工能够通过该零碎提交一个洽购申请,一个申请蕴含了若干数量、若干类型的办公用品(称为洽购项)。(1)主管负责对洽购申请进行审批。(2)审批通过后,零碎会依据提供商不同,生成若干订单。(3)对同一个问题,存在若干种不同的设计思路,例如以数据库为核心的设计、面向对象的设计和“正确的 OO”的 DDD 的设计。 如果采纳以数据库为核心的建模形式,首先会进行数据库设计——我的确看到还有许多团队依然在采取这种办法,破费大量的工夫进行数据库构造的探讨。为了防止图表过大,咱们仅仅给出了和洽购申请相干的表格。构造如下图所示: 图1 数据库视角下的设计 如果间接在数据库这么低的设计档次上思考问题,除了数据库的设计繁琐易错,更重要的是会面临一些比较复杂的业务规定和数据一致性保障的问题。例如: 如果洽购申请被删除,则相应的和该洽购申请相干的洽购项以及它们之间的关联都须要被删除——在数据库设计中,这种束缚能够通过数据库外键来保障。如果多个用户在对具备相干关系的数据进行并发解决,则可能波及到简单的锁定机制。例如,如果审批者正在对洽购申请进行审批,而洽购提交者正在对洽购项进行批改,则就有可能导致审核的数据是过期数据,或者导致洽购项更新的失败。如果同时更新某些相关联的数据,也可能面临局部更新胜利导致的问题——在数据库设计中,这类约束则须要通过 transaction 来保障。的确,每个问题都是有解决方案的,然而,第一,对于模型的探讨过早地进入了实现畛域,和业务概念脱开了分割,不便于继续地和业务人员合作;第二,技术细节和业务规定的细节纠缠在一起,很容易顾此失彼。有没有一种计划,能够让咱们更多的聚焦于问题畛域,而不是深陷到这种技术细节中? 面向对象技术和 ORM(对象-关系映射)有助于咱们进步问题的形象层级。在面向对象的世界中,咱们看到的构造是这样的: 图2 传统OO视角下的设计 面向对象的形式进步了形象层级,疏忽了不必要的技术细节,例如曾经不须要关怀外键、关联表这些技术细节了。咱们须要关怀的模型元素的数量缩小了,复杂性也相应缩小了。只是,业务规定如何保障,在传统的面向对象办法中并没有严格的实现束缚。例如: 从业务角度来看,如果洽购申请的审批曾经通过,对洽购申请的洽购项进行再次更新应该是非法的。然而,在面向对象的世界中,你却没法阻止程序员写出这样的代码: ...PurchaseRequest purchaseRequest = getPurchaseRequest(requestId);PurchaseItem item = purchaseRequest.getItem(itemId);item.setQuantity(1000);savePurchaseItem(item);语句 1 获得了一个洽购申请的实例;语句 2 获得了该申请中的一个条目。语句 3 和 4 批改了洽购申请条目并保留。如果洽购申请曾经审批通过,这种批改岂不是能够轻易冲破洽购申请的估算? 当然,程序员能够在代码中退出逻辑查看来保障一致性:在批改或保留申请条目前总是查看 purchaseRequest 的状态,如果状态不为草稿就禁止批改。然而,思考到 PurchaseItem 对象能够在代码的任何地位被取出来,且可能在不同的办法间传递,如果 OO 设计不当,就可能导致该业务逻辑扩散到各处。没有设计束缚,这种查看的实现并不是一件容易的事件。 ...

June 16, 2021 · 2 min · jiezi

关于架构师:为什么你应该关心领域模型

简介:畛域模型是DDD的外围,更是业务的深刻认知作者简介:张刚,软件工程博士,阿里云云效资深技术专家,ALPD方法学核心成员。 读者福利:返回: https://developer.aliyun.com/topic/course/alpd 收费支付阿里爆款架构师课程《DDD高手进阶12讲》(原价98元)。 引言畛域模型是重要的概念。然而,真正理解并能纯熟使用它的人并不多。这切实是殊为惋惜的一件事件。 软件开发中的许多问题,例如需要难于沟通,软件难以演变,都和畛域模型严密相干。更要害的是,把握这个概念并不难。通过练习,一个团队只须要一两个小时,就能够习惯畛域模型的建模思路,并且开始从中受害。 那么,什么是畛域模型?如何了解畛域模型的实质?为什么畛域模型能给软件开发带来微小帮忙?如何表白它,如何利用它?本文将顺次开展这些概念。 什么是畛域模型?首先咱们来看什么是畛域模型。 畛域模型定义了畛域内的要害的概念以及这些概念之间的关系。 为什么要强调“畛域内”?是因为模型(或者说概念)只在它所处问题空间中才有意义。这分为两种状况: 1)一个概念只在某个特定畛域有意义。例如,“应收账款”,就只是在财务畛域,更严格的说是会计畛域才有意义。 2)一个概念必须通过畛域限定,才有具体的意义。例如,“轨道”这个概念,它可能是天文学畛域的行星静止轨道,也可能是铁路畛域的火车轨道,必须得先限定畛域,这个概念才有真正的价值。 要害信息1:畛域模型最重要的是概念,畛域模型也被称为概念模型。 尽管有人说“畛域模型是畛域内的概念的可视化示意”,然而, “可视化”并不实质,尽管它也重要。相比较而言,“概念”才是基本。 要害信息2:“语言的边界就是思维的边界”—— 一个好的畛域模型,必然承载了有用的常识。 对一个不相熟特定畛域的人来说,了解概念,往往是进入一个畛域最快的形式。例如,小时候的儿歌:太阳大,地球小,地球绕着太阳跑。地球大,月亮小,月亮绕着地球跑。它就能够认为是一种概念模型的表白。在这个模型中,包含了3个概念实体:太阳,地球和月亮。而太阳和地球的关系是地球绕着太阳静止,地球和月亮的关系是月亮绕着地球静止。用一张图画下来就是: 这张图其实是UML的对象图,当然即便你不相熟UML,就是作为线框图,也能很容易了解。 同样,在各种业务畛域,都有本人的要害概念。这些概念的表白也不肯定是图。例如,方才所讲的会计畛域,咱们能够应用一张表来表白下列的几个要害概念: <span>会计主体(本方)->对方</span><span>应收账款</span><span>货物曾经发给对方,然而尚未收到货款</span><span>应付账款</span><span>曾经收到对方货物,然而尚未领取货款</span><span>预收账款</span><span>曾经收到对方货款,然而尚未发货</span><span>预付账款</span><span>曾经领取对方货款,然而尚未收到货物</span> 通过这样一张表格,置信即便对会计畛域不甚了解对小伙伴,也能疾速把握相干的常识。如果咱们更进一步,可能了解到,应收和预付,实质上是本方的债务,而预收和应酬,实质上是本方的债权。用一张图示意就是: 在这里咱们应用了UML类图来示意。对于不相熟UML的小伙伴,可能须要解释一下三角形箭头的意思,它代表“是一种”,例如,应收账款是一种债务。 更严格的,如果一笔应收账款的帐期曾经很长,例如5年,那么这种账款有很大概率曾经收不回来了,所以须要计提坏账。有一些通用的坏账计提策略,例如:一年以内5%,一到二年20%,二到三年50%,三年以上100%等。所以,面向方才的应收账款,咱们能够用上面的图来表白这样的概念: 图是一种视图,它不须要八面玲珑。例如,本图中,并没有显示所有和会计科目相干的信息,而只是集中于坏账的计提。其中,咱们在应付账款和坏账之间引入了一个新的符号,意识UML的小伙伴晓得咱们表白的是”应收账款中包含坏账“。图中的帐期、金额等,咱们成为“属性”,用于具体的阐明应收账款、坏账这些概念还包含哪些内容。因为畛域模型实质上传递的是概念,是知识性的信息,所以,对于软件开发的场景来说,把这些常识显式化,能疾速对齐不同角色、不同参与方之间的概念,减速沟通,防止误会。 # 畛域模型是重要的业务资产## 畛域概念积淀业务知识,而且十分稳固。 一家在某个畛域深耕多年的企业,和一个新入行的企业,差异是什么?差距可能是多方面的,然而最大的差距应该是“认知”。——所以咱们经常会看到,新入行的企业追赶深耕多年的企业的方法,经常是去成熟的的企业高薪“挖角”。按道理说,挖来的这些人既不能把原公司的客户带来,也不可能把原公司的零碎带来,那么实质上他们给新企业带来了什么呢?他们对新公司最大的帮忙,是对特定畛域的认知。在业务畛域,认知十分值钱,而且十分稳固。咱们也会看到,一些在某个畛域建设了劣势的企业,特地是征询类企业,单靠业务畛域的征询,就能给企业带来主观的支出。如果有良好保护的畛域模型,那么畛域模型就是这些认知积淀的最佳地位所在。 更重要的是,只管业务常新,然而畛域模型却相当稳固。咱们以商品交易为例。咱们晓得买家、买家、商品、交易这些概念,都是商品交易畛域的外围概念。这些概念并不会随着业务的演进产生激烈的变动,无论是B2C业务,C2C业务,C2M业务,拼团业务还是秒杀业务。不同的业务,体现的只是对这些业务概念的不同组织形式。当然,真正的畛域模型要远远比上述概念简单的多。咱们这里只是举一个简略的例子,阐明畛域概念的稳定性。 ## 畛域模型的跃迁和成长 当然,咱们说畛域模型稳固,并不是说它变化无穷。优良的畛域模型都肯定会继续成长,甚至有时候会产生实质的跃迁。 一旦一个模型被颠覆,咱们会认为,咱们对某个畛域的认知,肯定产生了十分实质的跃迁。例如,前述的儿歌“太阳大,地球小,地球绕着太阳跑。地球大,月亮小,月亮绕着地球跑。”并不是一开始就是这样认知的。无论中外,在几百年前,咱们都已经认为,地球是宇宙的核心,太阳、月亮都是绕着地球运行的。那么,这个模型画进去就是上面这个样子: 地心说对象图 地心说到日心说,是咱们宇宙认知到巨大进步,认为日心说模型彻底否定了地心说模型。在软件畛域也是这样。我已经经验过几次畛域模型跃迁的场景,每次都随同这业务认知的巨大进步。 当然,在现实生活中,跃迁并不多见。更多的时候都是在原有的模型上稳固倒退,逐渐增入各种新的概念和各种细节。模型的成长过程,实质上也是业务能力积攒的过程。 ## 稳固的畛域模型带来软件的适应性 需要是不稳定性的,而畛域模型是稳固的,这启发咱们,如果以畛域模型为核心去结构软件,那么咱们就会结构出很多稳固的积木块。新的需要,就可能通过这些稳固的积木块,通过不同的搭建形式,造成丰富多彩的利用。在这种状况下,咱们的软件对于变动的适应力最强,开发成本最低。 # 畛域模型存在于哪里 ## 用类图示意畛域模型 UML类图是表白畛域模型的十分好的工具,尽管并不存在如何表白畛域模型的规范。因为在UML中,“类”并不简略是软件设计中的“类”,它代表的其实是“概念”,所以,把类图用在畛域模型的表白上,是十分恰切的。而且,UML曾经约定了概念和概念之间的关系,例如:类、属性、关联、关联的多重性、泛化、聚合、组合、依赖等等。 对于不相熟UML的人来说,应用UML也齐全没必要有什么心理累赘。UML是一个高度灵便的构造,它具备渐近的能力。你没有必要把握所有简单的概念才开始工作,依据我的教训,只有一开始能把类(代表概念)、类的属性和它们的关系形容进去,最多再晓得多重性怎么示意,就足以应酬大多数的场景。有些小伙伴有面向对象的教训,在这里会纠结于要不要对“办法/操作”进行建模。在“畛域模型”是一种“业务概念”这个上下文中,办法是齐全多余的货色,临时不须要在这个阶段进行建模。我认为在实现阶段补足它们更适合。 ## 在交换和文档中应用畛域模型 畛域模型写在纸上并不是最要害的。作为概念模型,它反映了这个畛域的最重要的概念,也形成了表白业务概念的词汇。所以: 最好的畛域模型,应该时刻存在于团队成员的心中,存在于日常的交流活动中。为了做到这一点,我对本人的团队和辅导过的团队,都有一个要求,这个要求也被成为交流活动中的“对立语言”:任何在需要形容中呈现的概念,都必须呈现在畛域模型中。如果需要形容中存在概念之间的关系,畛域模型中也必须有这个关系 这个要求看似简略,理论做到会比拟艰难。特地在刚开始的时候,团队成员可能并不适应这种做法,经常就遗记了这个准则,须要常常纠正。然而一旦习惯,大家会发现,在日常交流活动中,因为所有的概念都曾经显式化,误会大大减少,共识更容易达成,导致的结果就是最初团队成员,都会十分盲目的保护“对立语言”的做法。 出于同样的起因,编写文档时,应用畛域模型作为对立语言也成了一个十分天然的后果。 ## 在代码中应用畛域模型 因为畛域模型曾经被显式化,所以如果可能在代码中应用畛域模型,那么代码就会取得更好的易读性。因为畛域模型和代码对应的更加统一,那么在畛域模型产生演进时,代码就会变得更容易演进。在这方面,畛域驱动设计给出了一组齐备的模式,能够帮忙架构师和开发人员天然地把畛域模型转化为代码。本文中咱们并不筹备开展这些模式。在此,临时先请读者们记住上面的论断,前面会有更深刻的探讨: 代码和问题域之间的示意差距应该尽量放大,畛域模型是连贯事实世界和数字世界的最佳桥梁。应用畛域模型作为代码中的业务概念的根本表白元素,能够大幅晋升代码的易读性,也能够更好的反对业务的演进。 # 畛域模型来自哪里 畛域模型反映了要害的业务认知,然而认知并不会凭空建设。可能一上来就洞悉所有实质的,要么是这个人是蠢才,要么阐明这个畛域曾经是一个十分成熟的畛域,曾经无需摸索和发现。大多数时候,认知都来自于业务场景的启发。所以,畛域模型建设的过程,往往是随同着需要剖析同步产生的。 我画了上面这张图,来阐明畛域模型和业务场景之间的关系: 也就是说,畛域模型是在业务场景的激励下逐步欠缺的。而且,反过来因为对畛域的认知更加粗浅,畛域模型还有助于新的业务场景的发现。 摸索和发现最好不要一个人单独进行。更多地时候,应该尽量进行个体建模。个体建模不仅仅利于摸索和发现,而且它也有助于达成对于要害业务概念的共识。 个体建模的最好工具并不是UML的电子化工具,应用白板,在凋谢空间中的探讨,往往可能收到最好的成果。 因为畛域模型表白的是概念,所以对于概念及时地合成和形象,是领域建模的基本功。当然,事实中受过严格的合成和形象训练的人并不多,特地是很多业务人员往往都不足这方面的能力。我在理论工作中,察看到具备面向对象教训的开发人员,通过肯定工夫的练习,能够很快把握这方面的技能。所以,如果有一些具备教训的开发人员参加建模,往往能够取得品质更高的模型。 # 常见误区 畛域模型的概念产生于90年代的面向对象社区。在那个时候,业务变动还不像明天这样频繁,迭代的思维也还没有齐全成熟,业务人员和技术人员也没有像明天这样密集的交换,所以,无论是从参考书上,还是实际上,畛域模型的概念都不免留下早年做法的影响。其中,有若干误区,在实践中是应该尽量避免的: ## 误区1:  从开发视角进行畛域模型的建模 经常有技术人员问:“畛域模型和ER图有什么关系?” 对这个问题最间接的答复就是:“没有关系”。诚然,我必定晓得在有了畛域模型之后,设计ER图会更简略,或者对于一个还不足畛域模型的遗留零碎,钻研数据库构造能够带来无效的输出,然而它们的立足点是齐全不一样的。 畛域模型肯定要从业务视角去看,因为畛域模型反映的是业务认知。一旦在畛域模型中掺杂了技术的概念,不仅仅是因为它不够纯正,更重要的是它曾经堵死了从业务视角对畛域模型进行演进和纠正的机会。因为没有软件背景的业务人员,是不可能去看一个充斥着技术概念的模型的。对立语言无奈建设,畛域模型带来的价值就曾经损失了一大部分。此外,从开发视角进行建模,往往还会漠视业务人员的参加。而实际一再表明,资深的业务人员在领域建模时,往往能提出深刻的洞察。所以,从开发视角对畛域模型进行建模相对不可取。 ## 误区2: 建设宏大的畛域模型 当咱们说“畛域”的时候,并没有限定一个“畛域”应该有多大。到底是“航空”作为一个畛域,还是“航空”中的“订票”是一个畛域? 当你思考到“畛域的外围是认知”,这个答案就变得十分分明了。畛域越大,越不利于建设认知和共识。咱们应该这问题域,把大的畛域划分为小的畛域,而后一一建设这些小的畛域的畛域模型。那种整整一面墙的畛域模型,往往都是不可取的。 ## 误区3: 重文档,轻交换和共识 畛域模型的外围在于建设独特的共识,所以,如果只是把畛域模型作为一种“制品”,作为某个阶段的“输入”,这是十分不适合的。畛域模型须要作为交换工具。“对立语言”是防止该误区的重要办法。 ## 误区4: 不把畛域模型显式化 很多人认为本人是有“认知”的,甚至是有“畛域模型”的,然而,如果你问他们模型在哪里,这些要么就是在某个我的项目已经有过一些探讨,然而当初曾经不知所踪,要么就是尽管文档还在,然而团队的概念表白仍旧凌乱。没有显式化,没有把畛域模型写下来,没有造成团队口口相传的常识,那么这种模型,并不真正存在。除了“对立语言”,咱们还有一个十分简便的测验办法,就是看这个团队如何给新人介绍本人的零碎。因为畛域模型反映了根本的业务概念,是一个十分好的新人造就工具,凡是真正有“畛域模型”的组织,是不可能不把畛域模型拿进去做介绍的。 # 总结 本文咱们次要介绍了畛域模型的基本概念及重要度,畛域模型对于“对立语言”的价值以及畛域模型利用的常见误区。 总结一下要点: * 畛域模型的实质是概念和认知,它定义了畛域内的要害概念以及这些概念之间的关系* 绝对于业务的多变,畛域模型绝对稳固,优质的畛域模型能够低成本的反对业务,畛域模型也是对立语言的根底,能无效晋升沟通效率* 畛域模型来自于业务滋润,畛域模型成长的过程,也是业务认知建设的过程,合作建模是更无效的建模办法 在你的团队中,有显式的畛域模型和独特的业务认知吗?它在领导日常的交换和开发工作吗?如果还没有,让咱们开始吧。 * 课程举荐:《DDD高手进阶12讲》 本文内容源自阿里云云效推出的《ALPD云架构师系列——DDD高手进阶12讲》。这是一门阿里外部的爆款课程,取得数千阿里工程师口碑举荐,值得每位开发者重复学习。 或PC端返回如下链接获取课程,收费支付阿里爆款架构师课程《DDD高手进阶12讲》(原价98元) https://developer.aliyun.com/topic/course/alpd > 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

June 11, 2021 · 1 min · jiezi

关于架构师:如何成为云原生时代的卓越架构师

简介:“软件开发须要面对实质艰难和从属艰难。云原生、DevOps大幅升高了从属艰难,使得架构师能够全力聚焦于业务复杂性,而DDD恰是治理业务复杂性的无效办法。”本文作者:张刚,阿里云云效资深技术专家,ALPD方法学核心成员。 立刻学习:https://developer.aliyun.com/topic/course/alpd 软件开发的实质艰难1986年,软件工程大师Frederick Brooks撰写了一篇驰名的论文《没有银弹》。他在文章的开篇写道: 在将来的10年以内,不存在任何繁多的办法和技术,可能10倍以上的进步软件开发的生产力。 这个论断在过后就引发了微小的争议。至今,《没有银弹》依然是一个被常常拿进去探讨的话题。不过,这篇论文的真正价值远不限于此,持续读上来,就会发现,。停留在是否存在10倍以上生产率的探讨是不够的。真正值得关怀的,是Brooks对起因的论断。我把其中的重要观点概括如下: 软件开发的艰难有两类,一类是实质(Essential)艰难,一类是附属性(Accidental)艰难。 实质艰难是和软件的实质紧密联系在一起的,所以这类艰难无奈通过工具或者语言等加以解决。例如,软件解决的问题是事实世界的问题,如果事实世界的问题原本就是简单的,那么无论任何工具,都不可能打消这种复杂性。 附属性艰难是和咱们采取的工具或者办法相干的。例如,软件须要被通过某种语言实现,软件须要被编译、被部署,软件可能被实现为缺点,这些都和具体的实现办法相干。这一类艰难,能够通过工具、办法和技术的晋升得以改善。 实质艰难包含软件的复杂性,不可见性、可变更性和合乎性(指软件开发还须要听从诸如法律法规、内部零碎等不受主观意志决定的因素) 作为一名在软件开发行业工作了20年的架构师,《没有银弹》对于实质艰难和附属性艰难的阐述给了我微小启发。 多年以来,我始终都把“治理实质艰难、打消从属艰难”作为软件开发流动的座右铭。特地有意思的是,最近我发现,作为一个次要工作在业务零碎上的架构师,在云原生渐成趋势的时候,架构师的职责未然产生了扭转。而这个变动,恰好和“治理实质艰难、打消从属艰难”密切相关。 业务架构当然也是架构师的重要职责。业务和技术曾经深度交融,业务对响应速度的要求和开发品质的要求越来越高,同时在云原生时代,服务化简直成为必然选择。而无论是业务响应能力、开发品质和服务化,都和业务布局能力密切相关。这不就是最重要的“治理实质艰难”的方面嘛! 畛域驱动设计,尽管Eric Evans的同名书籍写于2004年,多年以来,在技术社区也有较大影响。然而为什么最近几年热度忽然大幅回升,变得特地受关注呢?这是因为,咱们的业务终于越变越简单,到了如果没有失当的办法,就不能很好的治理的境地——这也恰好暗合了DDD一书的副标题“软件外围复杂性应答之道“。微服务和云原生在服务方面的划分等,也是要害的助推因素。 成为云原生时代的架构师在明天的业务环境下,能更好地利用好云原生基础设施,更好地进行业务布局、高效高质地剖析和治理畛域模型,用畛域模型领导架构设计和开发实际,是云原生时代架构师的重要技能。 这次云效和阿里云开发者学院联合推出的《ALPD云架构师系列——畛域驱动设计》课程也正是围绕着这个主题开展。 ALPD全称Advanced Lean product development,它是阿里云云效团队提出的云原生时代的研发新范式,它整合了技术、工程、合作、翻新4类实际,并提供高效解决方案。 下面2幅图别离是ALPD办法和支撑体系图,咱们心愿ALPD及其解决方案能够帮忙企业和开发者,实现10倍效力晋升——10倍的响应速度,10倍的过程品质,10倍的无效价值交付。 在本次课程中,咱们将为大家带来 ALPD办法体系中的畛域驱动的架构和实际 局部的内容。 能通过这一次的对外整顿,将常识和教训分享给社区开发者小伙伴,也是十分开心的事件。 ALPD云架构师系列课程——DDD高手进阶在课程整顿中,咱们把课程分成了如下章节: 01|畛域模型的实质是业务认知 02|案例剖析:高质量畛域模型晋升业务灵活性 03|高质量畛域模型源自继续演进 04|案例剖析:梳理业务概念,发现畛域模型 05|从模型到代码:畛域驱动设计的结构块 06|聚合:保障业务完整性的单元 07|畛域驱动设计的分层模型和代码组织 08|外围域、通用域和撑持域 09|基于业务能力和业务场景拆分子域 10|守护畛域边界,构建自治服务 11|限界上下文映射的模式 12|应用微服务构建畛域资产 其中每讲都放弃了15分钟左右的篇幅,以聚焦于一个比拟内聚的主题。 1-4讲,探讨畛域模型的一个根底概念,包含什么是畛域模型?为什么要关怀畛域模型?如何进行根本的领域建模? 5-7讲,次要关怀畛域模型为核心的软件实现,具体对应于畛域驱动设计的战术模式,例如实体对象、值对象,畛域服务、畛域事件结构块及聚合、资源库和工厂这些跟业务完整性密切相关的局部。 8-12讲,关怀畛域模型为核心的架构设计,具体对应于畛域驱动设计的策略模式,比如说子域、限界上下文、限界上下文映射等方面的话题。最初的12讲,咱们把微服务跟畛域资产之间的关系也做了探讨,微服务是以后一个重要话题,如果对畛域驱动设计关注有余,也会影响到微服务和云原生的施行。 在整个课程中,没有艰涩难懂的概念,我更心愿能通过扼要的案例让学员轻松了解畛域驱动设计的核心思想和要害实际。心愿你也能通过学习这个课程,能够从实质登程,更好地了解DDD并付诸理论我的项目施行。 点击下方图片或文末链接,退出《云架构师系列课程——DDD架构实战》的学习之路吧! 当然,领域建模和畛域驱动设计依然是须要长期刻意练习的技能,课程中的内容也还只是抛砖引玉,在后续的理论工作中心愿你能继续利用和晋升,一直精进,成为云原生时代的卓越架构师! 立刻学习:https://developer.aliyun.com/topic/course/alpd 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

June 11, 2021 · 1 min · jiezi

关于架构师:Flink-Forward-Global-2021-议题征集ing

简介:Flink Forward 寰球在线会议将在 2021 年 10 月 26 - 27 日再次重磅开启!现面向寰球用户征集议题!如果您对 Flink 的实际案例、深度技术、社区生态和 Stateful Functions 等方向有本人的心得和积攒,欢送投递议题,向寰球的开发者分享本人的教训!GitHub 地址 https://github.com/apache/flink 欢送大家给 Flink 点赞送 star~ 作为专门针对 Apache Flink 和流解决社区的寰球在线会议,Flink Forward Global 旨在将寰球的 Apache Flink 社区用户在线汇集在一起,交换 Flink 的故事和用例。 随着流解决成为各行各业许多公司的首选数据处理范例,继 2020 年两次胜利的举办后,Flink Forward 寰球在线会议将在 2021 年 10 月 26 - 27 日 [1] 再次重磅开启!现面向寰球用户征集议题!如果您对 Flink 的实际案例、深度技术、社区生态和 Stateful Functions 等方向有本人的心得和积攒,欢送投递议题,向寰球的开发者分享本人的教训! 退出 Flink Forward Global,同寰球 1500 多个软件开发人员、数据工程师、软件架构师、DevOps 业余人员,以及寰球 Apache Flink 的社区用户,探讨流解决的最新动静。与 Apache Flink 的爱好者,committers,以及 PMC members 建立联系,并学习如何开发无关实时事件驱动利用的最佳实际。 ...

June 10, 2021 · 1 min · jiezi

关于架构师:40万奖金-阿里云天池第三届数据库性能大赛广邀英才挑战创新上云

简介:日前,“第三届数据库大赛--翻新上云性能挑战赛”在阿里云天池官网正式开赛。据悉,本次大赛由阿里云、英特尔联袂主办,聚焦数据库核心技术场景,摸索新介质极致性能,挑战海量数据高效上云,全程将有资深技术专家提供技术领导。日前,“第三届数据库大赛--翻新上云性能挑战赛”在阿里云天池官网正式开赛。据悉,本次大赛由阿里云、英特尔联袂主办,聚焦数据库核心技术场景,摸索新介质极致性能,挑战海量数据高效上云,全程将有资深技术专家提供技术领导。 大赛现已面向全社会凋谢报名,集体开发者、高等院校、企业、科研单位等人员均可报名参赛,为宽广数据库技术爱好者以及相干的科研企业提供挑战平台。 点击这里进入大赛官网理解更多 “高性能剖析型查问引擎”赛道报名 “海量数据高效上云” 赛道报名 首度开启双赛道比拼 聚焦外围业务场景难题自2018年以来,“阿里云数据库大赛”曾经间断胜利举办两届,吸引了国内外数千支队伍和集体加入,参赛者遍布11个国家和地区。沉闷队伍不仅笼罩了国内所有大型互联网公司,各大出名院校组成的队伍亦参加其中。 本届大赛突破性地采纳双赛道机制,聚焦剖析型查问引擎、海量数据迁徙等数据库外围业务场景难题,分设“高性能剖析型查问引擎”和“海量数据高效上云”两大赛道。 其中,“高性能剖析型查问引擎”赛道,赛题来自云原生数据仓库AnalyticDB的剖析型查问场景,基于采纳英特尔®傲腾™长久内存(PMem)的平台,选手将设计并且实现指定的数值剖析函数,在保障正确性和鲁棒性下,疾速实现指定的数据导入,及若干次数值计算查问。 “海量数据高效上云”赛道,将数据传输服务DTS的海量数据迁徙技术构建于Aliyun Linux操作系统之上,采纳英特尔®傲腾™长久内存 (PMem)。赛题从数据高效迁徙场景切入,选手们须要设计并实现将海量数据从本地传输到云上的程序,反对存量和增量数据迁徙,具备肯定的鲁棒性,同时领有良好的性能。 大赛炽热报名中40万奖金等你来挑战 本届大赛从即日起——6月25日均可报名,赛事总奖金池高达40万元,通过初赛、复赛两轮比试后,各赛道复赛成绩排名TOP11的参赛队伍选手代表,将别离受邀加入9月举办的决赛问难。 本届大赛尤其激励企业选手参赛,代表企业参赛并进入复赛的优胜选手,将有机会成为阿里云数据库的合作伙伴, 重点包装迁徙上云的实操案例并在开发者社区全网流传,减少企业曝光。 除了惯例奖项,为广罗数据库高技能人才,体现优良的参赛选手还可取得极客奖和阿里云数据库产品事业部优先内推名额,与行业精英共建“数据库上云”新生态。 超奢华评审阵容 技术专家全程护航领导第三届数据库大赛全程将有资深技术专家为参赛选手们提供最业余的技术答疑和领导,大赛还领有奢华评审阵容,包含:阿里巴巴团体副总裁、阿里云数据库产品事业部负责人李飞飞博士,阿里云研究员占超群、阿里云研究员林亮、阿里云资深技术专家陈长城、阿里云资深技术专家付大超、英特尔公司傲腾产品事业部中国技术创新核心工程部经理吴国安、英特尔公司数据中心部门软件架构师斯佩峰等。 评委们均是数据库畛域的资深专家,具备丰盛的钻研和实战经验,他们对赛题的解读和评审,也是吸引选手们参赛的一个亮点。 阿里巴巴团体副总裁、阿里云数据库产品事业部负责人李飞飞示意:“本届大赛首次推出双赛道,别离聚焦剖析型查问场景和海量数据迁徙上云的最佳实际,联合了最新的英特尔傲腾长久内存技术。赛题须要选手对云原生数据库和软硬件联合有充沛认知,并设计出最优的数据结构。 阿里云数据库始终致力于造就创新型技术人才,为英才们搭建成长“快车道”。在大赛的促成下,将有越来越多数据库爱好者取得新的时机、拓展技术边界,期待大家获得好问题!” “阿里云与英特尔是长期的策略合作伙伴,特地是在云原生数据库畛域基于英特尔傲腾技术获得了创新性的冲破“,英特尔公司市场营销团体副总裁兼中国区数据中心销售总经理陈葆立示意,“咱们十分荣幸再次与阿里云的相干团队单干独特举办此次数据库大赛,衷心期待通过本次大赛吸引更多的开发者退出,独特摸索新的计算及存储技术在阿里云平台的利用,挑战极致性能,激发并产生更多数据库畛域高效上云的翻新。‘’ 强劲硬件与云原生反对 挑战数据库性能极限“高性能剖析型查问引擎”赛道的焦点——阿里云自研云原生数据仓库AnalyticDB,是交融数据库、大数据技术于一体的云原生企业级数据仓库服务,反对高吞吐的数据实时增删改、低延时的实时剖析和简单ETL,兼容上下游生态工具,可用于构建企业级报表零碎、数据仓库和数据服务引擎。 “海量数据高效上云”赛道采纳的阿里云自研数据传输服务DTS,专一解决数据上云和RDBMS、NoSQL、OLAP等同异构数据传输,集数据迁徙、订阅、同步于一体,帮忙用户构建平安、可扩大、高可用的数据架构。通过技术革新,一直晋升海量数据迁徙性能和稳定性。 据悉,本届赛事的两大赛道联合英特尔® 傲腾™ 长久内存(PMem),可将高性价比的大容量内存与对数据持久性的反对奇妙地联合在一起,减速大内存计算,放慢数据库重启工夫并缩小I/O, 升高大内存节点的功耗,并在断电时爱护数据。这也补救了传统SSD和DRAM之间的空白,满足针对各种工作负载的需要,助力从更大的数据集中获取更深刻的洞察。 阿里云弹性计算长久内存型实例产品(re6p),深度交融了长久内存相干技术,将英特尔傲腾长久内存嵌入到云服务器中对外提供服务,在OLAP型利用(如云原生数据仓库AnalyticDB)中,极大的升高了用户的老本及试用门槛。 报名入口及赛题详情欢送各路数据库精英亮出技术风采,点击下方链接即可报名 理解赛事介绍及赛题详情,请拜访大赛官网: https://tianchi.aliyun.com/specials/promotion/3rddatabase2021 “高性能剖析型查问引擎”赛道报名: https://tianchi.aliyun.com/competition/entrance/531895/introduction “海量数据高效上云” 赛道报名: https://tianchi.aliyun.com/competition/entrance/531896/introduction 更多信息请扫码退出第3届数据库大赛选手问答钉钉群:31284752,最新告诉将会第一工夫在群内同步。 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

June 8, 2021 · 1 min · jiezi

关于架构师:想要成为架构师先看看这些条件满不满足

摘要:本文次要介绍软件架构的定义,以及要成为一个软件架构师所需具备的一些技能,让你对软件架构师这一职位有一个更深的理解。本文分享自华为云社区《想要成为架构师?先看看这些条件满不满足!》,原文作者:元闰子 。 前言当你点开一个招聘APP,筛选条件抉择互联网技术,在列出来的一大堆职位上,往往有那么几个带有“架构师”三个字眼的高薪职位。当你被它的高薪所吸引而点击查看职位详情时,又会被它的高要求所劝退。它们往往要求工作年限在5年以上,须要求职者有过3年以上的零碎设计教训,精通各种架构模式和零碎框架,反观本人却一个条件都不满足。 软件架构师就是这么一个让人向往,但又让人望洋兴叹的一个职位。就像修建设计师总有成为总设计师的幻想,航天工作者总有成为总工程师的壮志,置信每一个软件工程师都有过成为软件架构师的想法。援用维基百科里的定义,软件架构师的职责就是在软件系统研发中,负责根据需要来确定次要的技术抉择、设计零碎的主体框架结构,并负责搭建施行。然而,架构师所需的技能远远不止于技术抉择和零碎设计。本文次要介绍软件架构的定义,以及要成为一个软件架构师所需具备的一些技能,让你对软件架构师这一职位有一个更深的理解。 文中大部分的观点来自于《Fundamentals of Software Architecture》一书,想理解更多详情举荐浏览原书。 软件架构的定义对于软件架构(Software Architecture),咱们通常将它看成是软件系统的蓝图(blueprint),然而如果要给出一个准确的定义,往往很难。维基百科里对软件架构的定义为,无关软件整体构造与组件的形象形容,用于领导大型软件系统各个方面的设计。然而,这种定义也是全面的,软件架构并不仅仅是零碎的整体构造和组件,光有这些还不足以领导设计出好的软件系统。 Mark Richards和Neal Ford在书中,从四个维度上对软件架构进行了形容,别离是Structure、Architecture characteristics、Architecture decisions和Design principles。 StructureStructure形容的是软件系统所应用的架构格调,比方最常见的分层架构(layered architecture)、事件驱动架构(event-driven architecture)、微核架构(microkernel architecture)、微服务架构(microservices architecture)等等。当你去问架构师一个软件系统应用什么架构时,如果他通知你,“零碎应用的是微服务架构”,那么也他仅仅说明了零碎的架构格调而已。若想理解整个零碎的软件架构,对architecture characteristics、architecture decisions和design principles都要有深刻的意识。 Architecture characteristicsArchitecture characteristics也就是咱们常说的非性能需要,比方有可用性(Availability)、可扩展性(Scalability)、可靠性(Reliability)等。Architecture characteristics往往容易被软件老手所疏忽,然而它对于软件系统而言却是十分的重要。如果说性能需要决定了一个软件系统的上限,那么非性能需要则决定了它的下限。 Architecture decisionsArchitecture decisions形容了开发软件系统时所必须遵循的规定,比方图中例子,对于一个分层架构格调的零碎而言,开发工程师须要遵循以下规定:只有业务层能力间接拜访服务层,体现层不能间接拜访服务层。Architecture decisions更多的只是一种束缚,违反了这种束缚可能并不会对系统的性能造成影响,然而却是零碎架构腐化的源头。 Design principlesDesign principles指的是零碎设计的准则,用于疏导开发团队抉择更合乎零碎特点的技术计划。Design principles只会给出一个方向,而不是具体的实现计划。比方图中例子给出的零碎设计准则就是:微服务之间应该尽可能通过异步通信来晋升零碎的性能。至于开发团队通过REST或者RPC的形式进行异步通信实现,设计准则并未进行限度。 成为架构师所需的技能就像软件架构不仅仅是零碎的整体构造和组件一样,要成为一个软件架构师,只会技术选型是远远不够的。一个合格的软件架构师应该具备以下的几种技能: 进行架构决策An architect is expected to define the architecture decisions and design principles used to guide technology decisions within the team, the department, or across the enterprise. 这是一个架构师所需具备的最根本的技能,须要为开发团队给出零碎设计的准则和零碎开发的束缚。架构师在这里的角色更多的是一个引导者,而不是具体技术计划的制定者。比方,开发团队要进行前端框架的选型,作为架构师应该给出的倡议是抉择Reactive格调的前端框架(疏导团队在React.js、Angular、Vue.js或者其余Reactive格调的前端框架之间进行抉择),而不是间接倡议抉择React.js框架。前者属于架构决策,而后者则是技术决策。 继续对系统架构进行剖析An architect is expected to continually analyze the architecture and current technology environment and then recommend solutions for improvement. ...

May 29, 2021 · 1 min · jiezi

关于架构师:如何写出高质量的技术文章

简介:为什么要写文章?什么是好的技术文章?如何写好技术文章?如果你是一个不喜爱语文、不喜爱浏览、作文很少及格的理科生,想要写好一篇技术文章,请肯定要往下看。 对于一个从小不喜爱语文、不喜爱浏览、作文很少及格的理科生来说,做梦也没想到,有一天我会写一篇文章教人如何写文章:) 一 为什么要写文章懂了,不肯定能说进去,说的进去,不肯定能写进去。这就是写文章最大的益处,官网术语叫“费曼教学法”。写文章是一个逼迫本人深刻了解问题、把问题想分明,整顿好思路,并能清晰表达出来的过程。其本质是一种自我学习、自我晋升、构建常识体系的最佳办法。 除此之外,写文章还有一个副产品——帮忙咱们扩充影响力。就拿我来说,我大略是在4年前,开始有布局地搭建本人的常识体系,包含浏览、记笔记、写文章、分享。 在这期间,我间断3年获得最佳年度作者,上头条的文章也不少。另外,阿里技术公众号,也发表了我10篇左右的文章,其中有2篇入选了创刊最佳文章,很多篇文章都有3万+浏览的不错体现。 基于这些总结积淀,我在人民邮电出版社出版了一本书《代码精进之路:从码农到工匠》,我自己也凭借本书取得了人邮IT类年度最佳作者。 二 什么是好的技术文章对于优质文章的规范,有一个对好文章的判断是:“文章框架残缺、思考深刻清晰、注释至多80%以上为原创技术干货。”这引起了不少的争议。 有争议很失常,没有争议才奇怪呢,好的技术文章,就和好的技术绩效一样,主观性太强......很难有一个主观规范。 如果硬要对文章品质进行量化的话,有些指标可能有帮忙。 比方文章的浏览量、点赞数、评论数、珍藏数等指标。有用,但也只是参考作用,最初还是须要人的评判。 所以抛开这些因素不看,我认为好的技术文章至多应该满足两个条件: 一个是要传播有价值的信息。另一个是要构造和逻辑清晰,具备肯定可读性和可了解性。在此基础之上,如果能做到有文采、够有趣那就更好了。 三 如何写好技术文章内容有用一篇好文章,一本好书,最重要的是要让读者有取得感,要对读者有用,要言之有物。 这里的“物”可大可小,不肯定非要是一个很大的命题,恰恰相反,一篇文章的篇幅无限,能把一件“小事件”说分明就曾经很不错了。 我已经发表过一篇文章——《阿里缩写和专业术语大全》,做的事件很简略,就是把我在阿里碰到的缩写全都整顿成册。就这么一篇“小文章”,却成了我最火的一篇文章,有将近100K的浏览,3K的点赞。 为什么大家会如此关注这篇没有“技术含量”的文章?很简略,很多人都有好奇心,大家都心愿理解缩写背地的全称和来历,这正是这篇文章的价值所在。 相似的,像云原生技术介绍、前端技术体系大全、新人入职手册、《马总演讲集》等都属于这种信息整合类的文章。 除此之外,那些有本人技术见解和思考,敢说真话的文章,也会受到大家的欢送。 比方,我感觉很多技术团队不应该有架构师这个岗位,所以写了《人人都是架构师:架构是一种能力,不是title!》。我感觉很多的软件复杂度来自于工程师的乱作为,比方滥用流程引擎,治理复杂度的基本是抽象思维和结构化思维,于是写了《一文教会你如何写简单业务代码》。 这些文章之所以受到欢送,是因为引起了很多同学的共鸣,对他们有帮忙。 构造清晰有了好的内容,还要留神文章的构造。就像一道菜,要考究色香味俱全,即便有了最好的食材,然而做进去的样子一团糟,也会影响食欲,称不上是一道好菜。 对于构造,我举荐你去看一本书——《金字塔原理》,我自己也写过不少对于结构化思维的文章。金字塔原理教诲咱们在写作、表白的时候,要构建清晰的构造。 对于一篇文章来说,金字塔的顶点是核心论点——通常就是文章的题目。围绕着这个核心论点,咱们能够用多个观点去撑持核心论点,如果表白的内容很多,观点还能够进一步往下细分。造成一个“以上统下、逻辑递进”的金字塔构造。 通过这种模式写出的文章,就会显得逻辑清晰,结构紧凑。 对于技术文章来说,咱们能够思考应用3W2H模型来帮忙咱们构建构造。比方我要写一篇对于形象能力的文章,就能够通过以下角度去说: What:什么是形象;Why:形象为什么重要;How:如何进行形象;Where:形象能够用在什么中央;How much:形象到什么水平;同样,我当初正在写的这篇文章,我也是通过这种形式来搭建构造的: 刻意练习开篇说过了,我以前没有写作的习惯,小时候语文作文也常常不及格。前面居然出版了本人的书,阐明写作作为一项技能,是能够习得的,是能够通过练习进步的。 因为写的多了,练习的多了,程度天然就会进步。然而,所谓的《刻意练习》(也是一本书),不是简略地反复,而是要给本人阶段性的设定更高的指标,这样才会继续地提高。 比方,我当初曾经能比拟流畅地写作,我就会去谋求如何把文章写的更加引人入胜。在《格调感觉:21世纪写作指南》外面提到一篇文章,它的结尾是这样写的:“咱们都会死,咱们是侥幸的...”,像这种抵触感和悬念,就会很天然地吸引读者持续浏览上来。 我这篇文章也借用了同样的手法 :) 迭代优化写文章和写代码有十分多类似的中央。我会常常拿写文章和写代码做类比。比方,文章和代码都须要构造清晰。又如,好的零碎不是设计进去的,是迭代进去的。好的文章也是如此,须要一直的打磨、批改,我的很多文章都是通过屡次批改,从新编排构造,补充删除信息,调整措词,直到我感觉称心为止。 就拿当初这篇文章来说,也是批改了好几版,第一遍的时候内容很散点,构造也不清晰,有点纠结,不晓得要如何写下去,前面想到一个“言传身教”的办法,即这篇文章自身应该就能够作为一个sample来介绍如何写文章。带着这个思路,迭代几次之后,就逐步成了一篇像样的文章了。 所以,重要的是要敢于去“动笔”,不要放心一开始的粗心大意,万事开头难,写着...写着... 你就有感觉了。 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

March 17, 2021 · 1 min · jiezi

关于架构师:对技术架构的理解与架构师角色的思考

2014 年退出阿里,在阿里通信工作了近两年。2016 年年底退出业务平台团队,过后 Leader 找我的第一件事就是要解决大促的问题,第二件事就是解决平安生产的问题。 ===================================================================================== 我带着这个命题进入业务平台,开始了前面的故事。明天趁这个机会,和大家分享一下对于这件事和这件事背地的一些想法,以及我对架构师的一些思考。 我对技术架构的了解第一点是顶层设计。国家每 5 年有五年计划,这其实就是在国家整个层面的一个十分清晰的顶层架构设计,这里面对国民经济重大建设项目和生产力进行宏观的架构设计,实质上也是一种架构设计。在这外面,要做什么事要定义的十分分明,要达到什么样的后果也要定义的十分分明。 双 11 的保障也是须要设计的。双 11 自身是一个业务的流动事件,因为规模比拟大,所以须要很多的技术来撑持这个货色。技术外面咱们可能要思考低成本、高效率、高稳固,并且还要引入一些更多的新技术来撑持,也要把这些货色整合好,架构设计好,让架构能够流畅地撑持业务。 第二点是物理架构。咱们有单元化架构,当然很多公司也有相似的架构。然而阿里的单元化架构与其余架构相比有一些实质的区别。 阿里目前单元化架构达到一个什么指标呢?通过部署异地单元将生产流量残缺运行在千里之外的独立机房,从而连续性的运行业务。这几句话外面蕴含了十分多的关键点,一个是异地,第二个是千里之外,第三个是独立,第四个是连续性。 单元化架构的总设计师是毕玄,因为咱们这块业务跟单元化的架构十分相干,所以要对它齐全把握和吃透能力往下走。 第三大点是利用架构,目前中台外面做的比拟多的叫星环,星环想达到架构的实质目标是将单纯的代码共建模式,形象成横向和纵向的业务包模式,做到业务与业务隔离,业务与平台隔离。 这背地带来的问题是什么?咱们原来产生用共建的形式撑持了 50 多个 BU 的会员、商品、交易、营销、资金、领取、库存逆向等业务,其实每个外面都是遍地开花的 if  else,这就导致代码的合并也难,开发也难,测试也难,上线也难,整个过程都很苦楚。所以在 2015 年做星环的架构时,就是让这些货色不那么苦楚,缓缓的解决这些问题。 架构师角色对于架构师的角色,我来说说本人的想法。 第一点是形散而神不散。架构其实是每个业务线都有,有些技术同学自身也是架构师的角色。阿里很早以前是专门有架构师岗位,专门的去做架构,然而做着做着架构师就做没了。因为很不接地气,它没有解决具体、实在、理论的问题。但当初,阿里的架构师岗位逐步减少了,他们的价值在于形象这些技术问题,解决这些问题。所以第一点是形散神不散。优良的技术同学始终在用架构的意识,解决理论的技术和业务问题,这就跟一般的技术同学有实质的区别。他不光是解决这一个问题,他可能解决这一类问题,用架构的思维去解决问题。 第二点是前瞻性。为什么你能解决这个问题,并且能解决这一类问题?肯定是须要你看的多,想的多,这背地是大量的实际和常识的积攒,并且是站在过来的肩膀上。 阿里电商零碎很早就建设了,咱们这一代一代人在外面去做架构,都是站在前一代人的肩膀上。要去看前一代人为什么要这么设计,去想或跟他去聊,汲取他好的中央。当初可能遇到新的问题,通过其余的办法来解决一些新的问题,须要有实际和常识的积攒。 接触更多的人和事,用新办法解决新问题,这个很要害。不能只看代码看一个月,要找实在的业务方,你的上游、上游、合作伙伴。比如说做双 11,我是 2016年12月到业务平台,我花了整整三个月,跟每年双 11 的大队长、重要人去聊双 11。他们是怎么了解,怎么来思考的,他们认为什么中央有问题。我再找他们要一些倡议:我应该怎么去做。跟他们聊的过程中才晓得咱们须要做什么样的大促,要把握什么是关键点,这都是一些贵重的财产。 第三点是解决简单问题。好的架构师都在解决简单的问题。只有简单的问题,它才须要更多不一样的技术或更新的技术来彻底解决。高并发高可用是阿里电商面临的根本问题,然而架构师要有不一样的高并发和高稳定性的解决思路。 以后最紧急的问题,比如说用户体验、晋升效率、低成本等,这些问题其实是非常复杂的。很多同学都想解决这个问题,很多种办法都在解决,然而整体来说成果不是特地显著。因为它链路太长了,链路长代表影响的业务和影响的人更多,你必须得换一种新的思路来思考这个问题。同时用户分层,外部的技术人员增多,这就倒逼咱们去把简单的问题简化,所以我会把解决简单问题定义为架构师的一个典型角色。 架构师须要什么样的能力架构师须要什么样的能力?我参考了里面一些同学的分享,总结进去其实就是发现问题、剖析定义问题、解决问题。 发现问题对部分和全局的问题须要有发现的眼光,更应该有发现未产生问题的能力,哪些须要治本,哪些须要治标,这是发现问题的根本判断力。当初零碎可能没什么大问题,但你要有发现的眼光,这些问题如果不解决,将来业务可能遇到更重大的问题。架构师看问题的眼光和他人不一样,不要只看见眼前这一个问题,还要看见这个问题背地是什么,这一类问题背地是什么,我怎么能用形象的办法解决一类问题。想好了当前,我就把以后的这个问题先解决掉,其余的问题用形象的形式去解决它。 定义和剖析问题阿里不缺解决问题的同学,然而缺定义问题的同学。你怎么晓得这是个问题,并且把这个问题定义分明。须要将发现的问题进行形象和演绎,定义出问题的基本要素,同时定义出问题的短期和长期计划,推动技术整体的提高。 定义问题这个要求十分高。大家平时在解决业务技术问题的时候,也须要具备剖析和定义问题的能力,把一个问题定义分明了,能够真正推动业务往后退。 解决问题须要施行门路和解决方案,协同团队和上下游,推动问题的解决。架构要解决的问题肯定不是一个部分问题,肯定是一个全局问题。架构师肯定会碰到各种各样的角色和链路,他要有这个能力去定义问题的解决方案和施行门路,同时要协同团队。他不能闷头做事,真的要低头,并且要有良好的沟通能力,跟所有的同学达成共识能力往后退。 第一点就是沟通能力十分要害。你怎么把这个问题说分明,切中问题的点,同时也能帮忙上下游带来理论的成果。第二点是架构师须要能救火,但不仅仅是救眼前的火,应该救将来的火,架构师救火能力要很强。 我来阿里之前在做一个 CRM 零碎。起初我要解决很多业务的问题,要把它形象进去,去做业务问题上面的根底平台。再起初发现根底平台的问题如果要解决得更彻底,还要做上面的中间件,这样层层深刻就会把整个链路买通看懂。 从 2017 年到业务平台当前,我学到了很多,包含它的零碎链路是什么样的,数据链路是怎么样的,整个调用链路是怎么样的,它和底层的关系是什么样的,可能遇到什么样的问题?当初可能呈现这个问题,再往后运行是不是会呈现其余的问题。通过救火的过程,一次次积攒对系统的理解。所以,每一次过来的积攒对于解决当初的问题还都有很大的帮忙,每一次问题的解决又能让本人对全局有更深的了解。 架构师的挑战 第一点是全局式的视角。比方看到“会员”这个业务性能,你不能仅仅看到这个性能自身,你要看到会员下面的业务是什么,谁在用会员,这叫全局。同时,会员用得最多的是导购和交易,登录仅仅是会员自身一个很小的业务性能而已。基于会员,咱们有导购、有交易,把这些货色要串起来看明确,就能残缺的意识到会员到底提供了什么,肯定要有一个全局视角。 第二点是技术广度。阿里的技术特地简单,能入职到阿里来,把阿里的整个技术栈残缺摸一遍的同学真的是很了不起。以单元化架构为例,咱们可能须要理解端,有 iOS、安卓、PC,还要理解 CDN、网络、接入层、服务发现、服务路由、HSF 等。数据库包含贮存同步、多点写,还有消息中间件等。这些技术和产品其实平时同学们都在用,但架构师不仅在用,架构师真的是要去把玩,彻底理解透彻这些货色,这是关键点。 给大家举个例子,像数据库组成的强同步,对咱们后续技术架构演进和业务的改良都有极大的影响,这个时候大家要对数据库有一个全局的意识。 2009 年 Oracle 数据库用得十分多。我过后不是做数据库相干的,然而为了把 Oracle 数据库钻研透,去学了十分多 Oracle 数据库相干的内容。理解外面的逻辑,晓得它的开发态、运行态、治理态等。常识都是有连续的,起初到了阿里,可能花很短的几个小时就能把当初阿里的数据库吃透。 技术的广度十分依赖于积攒。你肯定要带着问题去想,这个时候你才有记忆力,有了积攒,缓缓的你技术的广度就会越来越深。你要理解数据库,你必须对上层的网络理解,所以咱们要对网络、CDN 有更进一步的意识。 ...

February 2, 2021 · 1 min · jiezi

关于架构师:中国架构师大会活动预告即构受邀分享实时音视频服务架构实践

今年年初,受所服务的线上利用爆炸式增长的影响,即构作为底层音视频服务商,平台数据节节攀升,高达数千万的并发,日均音视频互动时长冲破20亿分钟。要扛住千万级的高并发,首先要有一个反对千万级并发的底层架构。即构的外围开创团队来自腾讯,团队成员少数参加了QQ产品实现用户量从百万级到上亿级的跨越式倒退,在大规模高并发分布式系统架构设计和实际方面有着丰盛教训。在成熟的大规模高并发底层架构之外,针对服务零碎的可用性保障伎俩,寰球用户接入品质问题,实时音视频云服务的调度零碎和散发网络建设等内容,也是音视频后盾服务质量的要害。即构作为寰球当先的实时音视频云服务商,服务超过70%的社交直播、在线教育行业TOP 50客户,累计帮忙寰球200多个国家/地区的近4000家企业客户取得语音视频能力,那么即构在实时音视频服务架构搭建过程中遇到过什么难点问题?积攒了哪些教训?10月22-24日,第十二届中国零碎架构师大会(SACC2020)将在云端进行网络直播。自2009年以来,SACC架构师大会已胜利举办了十一届,星散了国内CTO、研发总监、高级零碎架构师、开发工程师和IT经理等技术人群,与会规模超千人。本次大会为期3天,波及20+专场,近120个主题。 即构科技后盾架构负责人&高级技术专家祝永坚,受邀加入大会的音视频架构与算法专场流动。基于主导映客、花椒、一直播、好将来、作业帮等行业头部客户流媒体服务的丰盛教训,将在大会上进行音视频云服务零碎架构实际方面的深度分享。 分享专场音视频架构与算法 分享主题ZEGO 实时音视频服务架构实际 分享嘉宾祝永坚即构科技后盾架构负责人;高级技术专家 直播工夫10月24日11:00-11:40 除了即构科技外,本次中国零碎架构师大会音视频架构与算法专场还邀请到了苏宁、阿里云、Intel的多位技术专家进行分享,感兴趣的小伙伴能够点击“这里”报名观看。

October 21, 2020 · 1 min · jiezi

关于架构师:做好分库分表其实很难之二

为什么分在正式开始之前,菜菜还是要强调一点,你的数据表是否应该分,须要综合思考很多因素,比方业务的数据量是否达到了必须要切分的数量级,是否能够有其余计划来解决以后问题?我不止一次的见过,有的leader在不思考综合状况下,自觉的进行表拆分业务,导致的状况就是大家不停的加班,间断几周996,难道leader你不掉头发吗?还有的架构师在一个小小业务初期就进行表拆分,大家为了配合你也是快马加鞭的加班赶进度,上线之后反而发现业务数据量很小,然而代码上却被分表策略牵制了太多。拆表引起的问题在特定的场景下,有时候代价真的很大。数据库表的拆分解决的问题次要是存储和性能问题,mysql在单表数据量达到一定量级后,性能会急剧下降,相比拟于sqlserver和Oracle这些免费DB来说,mysql在某些方面还是处于弱势,然而表的拆分这个策略却实用于简直所有的关系型数据库。 数据库进行表拆分不要太自觉分表策略表的拆分和数据库的拆分有相似之处,然而拆分的规定也有不同。以下的拆分规定针对的是拆分一个表。 横向切分横向切分是诸多业务中最罕用的切分形式,实质是把一个表中的数据行依照规定扩散到多个表中,比方最常见的依照ID范畴,依照业务主键的哈希值等。至于表数据达到什么数量级之后进行切分,这和表中存的数据格式无关,比方一个表只有几列的int字段必定要比几列text类型的表存储的极限要高。权且认为这个极限是1000万吧。然而作为一个零碎的负责人或者架构师来说,当表的数据量级达到千万级别要引起器重,因为这是一个零碎性能瓶颈的隐患。 绝对于数据表的横向切分,在合乎业务优化的场景下我更偏向于做表分区,依照规定把不同的分区调配到不同的物理磁盘,这样的话,业务里的sql语句简直能够不必改变。我司的一个sqlserver数据库,某个业务的表做了表分区之后,曾经达到几十亿级别的数据量,然而查问和插入速度还是能满足业务的需要(优化一个零碎还是要花精力优化业务层面)。 垂直切分说到垂直拆分,表也能够依照业务来拆分,比方一个数据库中有用户的信息,依据业务能够划分为根底信息和扩大信息,如果对业务无利,齐全能够拆分为根底信息表和扩大信息表。当然也能够依照别的规定来拆,比方把拜访频繁的信息拆分成一个表,其余不频繁的信息拆分成一个表,具体的拆分规定还是要看过后要解决的问题是什么。垂直拆分可能会引入肯定复杂性,比方原来查问一个用户的根底信息和扩大信息能够一次性查问出后果,分表之后须要进行Join操作或者查问两次能力查问出后果。 分表代价数据表垂直切分之后,原来一次查问有可能会变为连表的join查问,在肯定水平上会有性能损失。数据表横向切分须要肯定的规定,罕用的次要有两种规定:范畴切分和哈希值切分。范畴切分是指依照某个字段的范畴来切分,比方用户表依照用户ID来切分,id为1到10万的位于User表1中,100001到200000万的位于User2中,这样切分的劣势是,能够有限的扩容上来,不必思考数据迁徙的问题,劣势就是新表和旧表数据分布不平均,而且分表的范畴选取有肯定难度,范畴太小会导致表太多,太大会导致问题基本上没有解决的困惑。另外一种分表策略就是把某一列依照哈希值来路由到不同的表中,同样以用户ID为例,如果咱们一开始就布局了10个数据库表,路由算法能够简略地用 user_id %10的值来示意数据所属的数据库表编号,ID为985的用户放到编号为 5的子表中,ID为10086的用户放到编号为 6 的字表中。这种切分规定的劣势是每个表的数据分布比拟平均,然而前期扩容会设计到局部数据的迁徙工作。表拆分之后如果遇到有order by 的操作,数据库就无能为力了,只能由业务代码或者数据库中间件来实现了。当有搜寻的业务需要的时候,sql语句只能是Join多个表来进行连表查问了,相似的还有统计的需要,例如count的统计操作。你在业务中进行过表拆分吗? 更多精彩文章 分布式大并发系列架构设计系列趣学算法和数据结构系列设计模式系列

October 9, 2020 · 1 min · jiezi

关于架构师:作为一个架构师我是不是应该有很多职责

每一个程序员都有一个架构梦。下面其实实质上是一句富裕事实哲理的废话,要不然也不会有这么多人关注你的公众号。这些年随着“企业数字化”转型的口号,一大批企业奔跑在转型的路上,心愿当先一步对手将企业IT部门从单纯的老本核心转变为业务驱动者,而这个过程中,企业的架构师起着无足轻重的作用。架构师的工作在很多撸码的开发者眼中是很一项很神圣的工作,而且富裕挑战性。 然而事物都有两面性,很多管理者和技术人员都认为架构师的薪酬不符合实际,有很多架构师的确只会用PPT和大幅海报来应酬了事,而且会依仗着在公司位置把本人的一些想法强加给公司其余共事,有的架构师甚至会谋求一些无关紧要的概念,在高层和底层灌输一些谬误的思维,从而导致做出一些不可逆转的蹩脚决策,使公司陷入危险顺境。 很多时候,公司给予架构师这个角色太多的责任,管理者心愿他们能在突发性能问题时能疾速解决问题,还能推动企业疾速转型,甚至能帮忙企业文化的疾速建设,作为一个架构师是不是要抗下这些职责呢? 我不是项目经理架构师的日常工作常常会面临并行处理多个不同维度的问题,这些问题可能是不同的主题,甚至在做决策的时候也须要思考人员的调配,我的项目时间表的排期,须要用的核心技术以及组件等。有很多高层领导喜爱间接在架构师这里获取我的项目的详细信息以及技术计划,尽管架构师角色波及这些信息并且很理解这些信息,然而这并不是架构师的职责所在,甚至很多状况下令架构师处于项目经理的难堪角色。 我不是开发人员我想很多人看过那篇文章:作为架构师该不该写代码?很多架构师是出身于开发人员,这也难怪会呈现这样的疑难。然而,架构师其实和资深开发是两条不同的职业路线,我认为两者没有高下之分。杰出的开发人员须要很深的开发功力,须要最终交付出可运行的软件。而架构师则须要更广大的知识面,更好的组织战略思想,更好的沟通能力。在一个产品的开发流水线上,架构师可能会负责一部分外围代码的编写,然而最次要的工作还是保障这条流水线的失常运行。 我不是救火员因为架构师这个角色在公司的位置,很多管理者认为架构师要随时随地的能剖析并解决任何突发的问题,不瞒各位,这种景象在很多大厂仍然存在,包含我司(尽管只是一个四线小厂)。如果一个架构师每天都忙着“救火”这种工作,基本没有工夫去做真正的架构工作,真正的架构设计须要思考,是不可能在短短工夫内实现的。然而架构师必须承受呈现的产品问题,因为这些问题的产生有可能和架构有着间接关系,在很大水平上能反馈架构的缺点或者问题。 写在最初架构师作为企业中很重要的一环,在很多重大技术问题中都作为决策者而存在。很难用代码的多少或者品质来掂量一个架构师的好坏,如果一个零碎在失常运行5年后仍然能良好运行并且能够接受肯定的变更能力,阐明这个零碎的架构师的工作是很杰出的。如果非要给架构师定义一个KPI规范的话,以下这些工作兴许能成为一个参考 定义IT策略。小到一个零碎的组件列表可行性的确定,大到公司技术的倒退方向,乃至将来10年公司技术的预测与大胆尝试。这些技术策略都须要架构师依据本身教训来制订。落实对IT蓝图的管控,以实现协调一致,升高复杂度,保障公司所有零碎井井有条的失常工作,架构师的工作之一就是要把复杂度升高,化繁为简,这须要架构师很强的形象能力。关注我的项目的理论落地状况,并依据我的项目施行中反馈的问题进行策略的适当调整。一个合格的架构师从来不会疏忽来自理论我的项目中的问题反馈。架构师肯定要防止和打消那些零碎设计中不可逆转的谬误决策起源参考:架构师应该晓得的37件事 更多精彩文章 分布式大并发系列架构设计系列趣学算法和数据结构系列设计模式系列

September 10, 2020 · 1 min · jiezi

关于架构师:JWT认证看这一篇就够了

基于Token的认证通过上一篇你大体曾经理解session和cookie认证了,session认证须要服务端做大量的工作来保障session信息的一致性以及session的存储,所以古代的web利用在认证的解决方案上更偏向于客户端方向,cookie认证是基于客户端形式的,然而cookie毛病也很显著,到底有哪些毛病能够跳转上一次的文章。那有没有一种比拟折中的计划呢?有的 把认证信息保留在客户端,关键点就是平安的验证,如果能解决认证信息的安全性问题,齐全能够把认证信息保留在客户端,服务端齐全无认证状态,这样的话服务端扩大起来要不便很多。对于信息的平安解决方案,当初广泛的做法就是签名机制,像微信公众接口的验证形式就基于签名机制。 签名,就是只有信息的发送者能力产生的他人无奈伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个无效证实。当用户胜利登陆零碎并胜利验证无效之后,服务器会利用某种机制产生一个token字符串,这个token中能够蕴含很多信息,例如起源IP,过期工夫,用户信息等, 把这个字符串下发给客户端,客户端在之后的每次申请中都携带着这个token,携带形式其实很自在,无论是cookie形式还是其余形式都能够,然而必须和服务端协商一致才能够。当然这里我不举荐cookie。当服务端收到申请,取出token进行验证(能够验证起源ip,过期工夫等信息),如果非法则容许进行操作。 基于token的验证形式也是古代互联网一般应用的认证形式,那它有什么长处吗? 反对跨域拜访,Cookie是不容许垮域拜访的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.无状态:Token机制在服务端不须要存储session信息,因为Token本身蕴含了所有登录用户的信息,只须要在客户端的cookie或本地介质存储状态信息.解耦 不须要绑定到一个特定的身份验证计划。Token能够在任何中央生成,只有在你的API被调用的时候,你能够进行Token生成调用即可.适用性更广:只有是反对http协定的客户端,就能够应用token认证。服务端只须要验证token的平安,不用再去获取登录用户信息,因为用户的登录信息曾经在token信息中。基于标准化:你的API能够采纳标准化的 JSON Web Token (JWT). 这个规范曾经存在多个后端库(.NET, Ruby, Java,Python,PHP)和多家公司的反对(如:Firebase,Google, Microsoft).那基于token的认证形式有哪些毛病呢? 网络传输的数据量增大:因为token中存储了大量的用户和平安相干的信息,所以比单纯的cookie信息要大很多,传输过程中须要耗费更多流量,占用更多带宽,和所有的客户端认证形式一样,如果想要在服务端管制token的登记有难度,而且也很难解决客户端的劫持问题。因为token信息在服务端减少了一次验证数据完整性的操作,所以比session的认证形式减少了cpu的开销。然而整体来看,基于token的认证形式还是比session和cookie形式要有很大劣势。在所知的token认证中,jwt是一种优良的解决方案 jwtJSON Web Token (JWT)是一个凋谢规范(RFC 7519),它定义了一种紧凑的、自蕴含的形式,用于作为JSON对象在各方之间平安地传输信息。该信息能够被验证和信赖,因为它是数字签名的。一个JWT实际上就是一个字符串,它由三局部组成,头部、载荷与签名。 头部header典型的由两局部组成:token的类型(“JWT”)和算法名称(比方:HMAC SHA256或者RSA等等)。 { "alg": "HS256", "typ": "JWT"}PayloadPayload 局部也是一个JSON对象,用来寄存理论须要传递的数据。JWT 规定了7个官网字段,供选用。 iss (issuer):签发人exp (expiration time):过期工夫sub (subject):主题aud (audience):受众nbf (Not Before):失效工夫iat (Issued At):签发工夫jti (JWT ID):编号除了以上字段之外,你齐全能够增加本人想要的任何字段,这里还是揭示一下,因为jwt的规范,信息是不加密的,所以一些敏感信息最好不要增加到json外面 { "Name":"菜菜", "Age":18}Signature为了失去签名局部,你必须有编码过的header、编码过的payload、一个秘钥(这个秘钥只有服务端晓得),签名算法是header中指定的那个,然对它们签名即可。 HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)算出签名当前,把 Header、Payload、Signature 三个局部拼成一个字符串,每个局部之间用"点"(.)分隔,就能够返回给用户。须要揭示一下:base64是一种编码方式,并非加密形式。 写在最初基于token的认证形式,大体流程为: 客户端携带用户的登录凭证(个别为用户名明码)提交申请服务端收到登录申请,验证凭证正确性,如果正确则依照协定规定生成token信息,通过签名并返回给客户端客户端收到token信息,能够保留在cookie或者其余中央,当前每次申请的时候都携带上token信息业务服务器收到申请,验证token的正确性,如果正确则进行下一步操作 这里再反复一次,无论是token认证,cookie认证,还是session认证,一旦他人拿到客户端的标识,还是能够伪造操作。所以采纳任何一种认证形式的时候请思考退出起源ip或者白名单,过期工夫,另外有条件的状况下肯定要应用https。 更多精彩文章 分布式大并发系列架构设计系列趣学算法和数据结构系列设计模式系列

September 2, 2020 · 1 min · jiezi

程序员转型架构师推荐你读这几本书

从CRUD的程序员,到系统的架构师,进阶推荐读这几本书。架构师书单分为两部分,第一部分是关于系统架构的方法论,包括领域驱动设计,微服务,整洁架构,第二部分介绍各大互联网大公司是如何做系统架构落地实践。 程序员书单会做成一个系列,会推荐面试,职业规划,软技能等不同主题的书单,同时我会在博客和公众号「架构进化论」中,对书单中推荐的好书做解读,欢迎持续关注。 一、方法论《领域驱动设计》 这本书可以帮助我们理解用代码呈现真实世界的重要性,并且告诉我们如何更好地进行建模。 简而言之,这本书提供了深入的架构洞察力,并帮助你在不断变化的环境中创建强大的系统,最重要的是,Eric Evans用开发人员可以理解的语言来描述,非常难得。 书中给出了领域驱动设计的系统化方法,并将人们普遍接受的一些实践综合到一起,融入了作者的见解和经验,展现了一些可扩展的设计新实践、已验证过的技术以及便于应对复杂领域的软件项目开发的基本原则。 《架构整洁之道》 来自传奇人物Robert C. Martin的实用软件架构解决方案,作者还有另外一本非常经典的书《代码整洁之道》。 干净的架构对于每一个软件架构师、系统分析师、系统设计师和软件管理人员来说都是必不可少的,想要成为软件架构师,这本书一定是必不可少的。 《微服务设计》 这是一本了解现代分布式软件设计和体系结构的好书,特别是微服务,如Uber,Facebook,NetFlix等的实践。 本书全面介绍了微服务的建模、集成、测试、部署和监控,通过一个虚构的公司讲解了如何建立微服务架构。主要内容包括认识微服务在保证系统设计与组织目标统一上的重要性,学会把服务集成到已有系统中,采用递增手段拆分单块大型应用,通过持续集成部署微服务等。 作者和译者都来自ThoughtWorks,值得信赖,除了系统化地论述了微服务的方方面面以外,书中推荐的技术博客、工具软件等对增强感性认识都很有帮助。对关于COTS的集成,作者提出的在自己可控的平台进行定制化的核心思想尤其值得牢记。 《架构即未来:现代企业可扩展的Web架构、流程和组织》 作者还有另外一本《架构真经》,一起推荐。本书汇聚了作者从eBay、VISA、Salesforce.com到Apple超过30年的丰富经验,全面阐释了经过验证的信息技术扩展方法,对所需要掌握的产品和服务的平滑扩展做了详尽的论述。 任何一个持续成长的公司最终都需要解决系统、组织和流程的扩展性问题,作者详尽地介绍了影响扩展性的各个方面,包括架构、过程、组织和技术。阅读本书,可以学习到以最大化敏捷性和扩展性来优化组织机构的新策略,以及对云计算(IaaS/PaaS)、NoSQL、DevOps和业务指标等的新见解。利用其中的工具和建议,可以系统化地清除扩展性道路上的障碍,更好的开展技术和业务。 二、架构落地实践《淘宝技术这十年》 生动形象的介绍了淘宝从小到大的技术发展历程,是企业架构发展的一个缩影,对思考技术发展有较好的帮助。 《淘宝技术这十年》从工程师的角度讲述淘宝这个超大规模互联网系统的成长历程,及其所有主动和被动的技术变革的前因后果。书中有幕后故事、产品经验、架构演进、技术启蒙,也有大牛成长、业内八卦、失败案例、励志故事。《淘宝技术这十年》文风流畅,有技术人员特有的幽默感;内容积极正面,有现场感,全部是作者亲身经历。 作者子柳,创办“淘宝技术大学”,培养内外部工程师众多,人称“校长“,微博上也有他很多关于互联网的思考。 《分布式服务框架:原理与实践》 这本书对分布式服务框架做了拆解,依托工作实践,从分布式服务框架的架构设计原理到实践经验总结,涵盖了服务化架构演进、订阅发布、路由策略、集群容错和服务治理等多个专题,全方位剖析服务框架的设计原则和原理,结合大量实践案例与读者分享作者对分布式服务框架设计和运维的体会。同时,对基于Docker部署微服务以及基于微服务架构开发、部署和运维业务系统进行了详细介绍。 作者具有丰富的分布式服务框架、平台中间件的架构设计和实践经验,主导设计的华为分布式服务框架已经在全球数十个国家成功商用。 《大型网站技术架构:核心原理与案例分析》 一本国内不错的关于软件架构实践的书,销量和评价都挺好。这本书通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计案例,呈现了一幅包括技术选型、架构设计、性能优化、Web 安全、系统发布、运维监控等在内的大型网站开发全景视图。 《大型网站系统与Java中间件实践》 阿里系技术图书,对分布式系统的演进做了较好的介绍,围绕大型网站和支撑大型网站架构的 Java 中间件的实践展开介绍。本书从分布式系统的知识切入,让读者对分布式系统有基本的了解;然后介绍大型网站随着数据量、访问量增长而发生的架构变迁;接着讲述构建 Java 中间件的相关知识;最后介绍支撑大型网站架构的 Java 中间件系统的设计和实践。 通过本书可以了解大型网站架构变迁过程中的较为通用的问题和解法,并了解构建支撑大型网站的 Java 中间件的实践经验。 《企业IT架构转型之道:阿里巴巴中台战略思想与架构实战》 看这本书,帮助你了解阿里的中台设计,也就是阿里巴巴的共享服务理念以及企业级互联网架构建设的思路。 本书从阿里巴巴启动中台战略说起,详细阐述了共享服务理念给企业业务发展带来的业务价值。接着会分享阿里巴巴在建设共享服务体系时如何进行技术框架的选择,哪些重要的技术平台支撑起了共享服务体系,这也是迄今为止对阿里巴巴集团中间件体系对外最全面系统的介绍。除了技术层面之外,本书还分享了阿里巴巴内部的一些经验和实践,如组织的架构和体制如何更好地支持共享服务体系的持续发展。 《尽在双11:阿里巴巴技术演进与超越》 这本书是阿里巴巴集团双11技术团队出品,集合了各个事业部对双十一的复盘,全面阐述双11八年以来在技术和商业上演进和创新历程的书籍。内容涵盖在双11背景下阿里技术架构八年来的演进,如何确保稳定性这条双 11 生命线的安全和可靠,技术和商业交织发展的历程,无线和互动的持续创新与突破,以及对商家的赋能和生态的促进与繁荣。 推荐做业务架构的工程师阅读,特别是双十一全链路压测,稳定性保障的篇幅。 本文作者:邴越 阅读原文 本文为云栖社区原创内容,未经允许不得转载。

October 17, 2019 · 1 min · jiezi

阿里架构师推荐给程序猿们的15款常用开发工具

从人工到自动化,从重复到创新,技术演进的历程中,伴随着开发者工具类产品的发展。 阿里巴巴将自身在各类业务场景下的技术积淀,通过开源、云上实现或工具等形式对外开放,本文将精选了一些阿里巴巴的开发者工具,希望能帮助开发者们提高开发效率、更优雅的写代码。 由于开发者涉及的技术领域众多,笔者仅从自己的视角盘点平时可能用得到的工具。每个工具按照以下几点进行介绍: 工具名称和简介使用场景使用教程获取方式一、Java 线上诊断工具 ArthasArthas 阿里巴巴2018年9月开源的一款Java线上诊断工具。 工具的使用场景: 1、这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? 2、我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? 3、遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗? 4、线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现! 5、是否有一个全局视角来查看系统的运行状况? 6、有什么办法可以监控到JVM的实时运行状态? Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。 使用教程:基础教程: https://alibaba.github.io/art... 进阶教程: https://alibaba.github.io/art... 获取方式:(免费)开源地址: https://github.com/alibaba/ar... 二、IDE 插件 Cloud ToolkitCloud Toolkit 是一款 IDE 插件,可以帮助开发者更高效地开发、测试、诊断并部署应用。通过 Cloud Toolkit,开发者能够方便地将本地应用一键部署到任意机器(本地或云端),并内置 Arthas 诊断、高效执行终端命令和 SQL 等,提供 IntelliJ IDEA 版,Eclipse 版,PyCharm 版和 Maven 版。 工具的使用场景: 1、每次修改完代码后,是否正在经历反复地打包? 2、在 Maven 、Git 以及其他运维脚本和工具的之间频繁切换? 3、采用 SCP 工具上传?使用XShell或SecureCRT登陆服务器?替换部署包?重启? 4、文件上传到服务器指定目录,在各种 FTP、SCP 工具之间频繁切换 ? 使用教程: IntelliJ IDEA版: https://help.aliyun.com/docum... Eclipse 版: ...

October 15, 2019 · 2 min · jiezi

开源项目几点心得Java架构必会几大技术点

Java架构必会几大技术点 关于学习架构,必须会的几点技术 列表项目java反射技术xml文件处理properties属性文件处理线程安全机制annocation注解设计模式代理机制(aop)serlvet基础(过滤器等等)几样比较实用的技术:  - 1. 模板语言freemarker  - 2. ognl  - 3. gson json工具类   大家对于几大框架望而生畏,实际上只要明白他的原理,就会触类旁通,在这里我说说自己的几点拙见!架构QQ交流群: 39596137MVC层(Struts,Springmvc):非常简单就是采用一个servlet实现统一跳转,配置文件保存了请求、处理类、转发请求的关系(通过xml文件或者注解)操作流程:页面触发请求,框架通过读取配置文件获取到处理类,然后通过反射实例化该类,进行对应的业务处理(现在流行的零配置,更是简化了mvc层的编写)持久层(Mybatis/Hibernate):     mybatis其实就是sql+mybatis逻辑标签     逻辑标签的理解如何大家用过模板语言freemarer或者velocity应该会很容易理解,就是自定义的规则标签     Hibernate略显高级,也很简单,他是采用注解或者配置的方式将实体字段和表字段进行一个配置,在启动的时候动态生成sql; 大家可以看下开源项目minidao,就会知道持久层原来写很简单;所以架构可以简单理解为:     配置+反射+设计模式+脚本+AOP     配置常用做法:       1.xml文件       2.annocation注解       3.properties属性文件       4.零配置思想 脚本处理方法:      可以自己写,也可以采用模板语言freemarker等等

June 8, 2019 · 1 min · jiezi

RPC框架是啥?

本博客 猫叔的博客,转载请申明出处在我刚刚了解分布式的时候,经常对RPC和分布式有些混淆,甚至一直以为两者对等,所以我们先看看他们有什么区别?RPC实现了服务消费调用方Client与服务提供实现方Server之间的点对点调用流程,即包括了stub、通信、数据的序列化/反序列化。且Client与Server一般采用直连的调用方式。而分布式服务框架,除了包括RPC的特性,还包括多台Server提供服务的负载均衡、策略及实现,服务的注册、发布与引入,以及服务的高可用策略、服务治理等等。那么RPC是什么呢?百度百科是这样表示的:RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。它甚至给出了工作原理,这一点很惊喜。1.调用客户端句柄;执行传送参数2.调用本地系统内核发送网络消息3.消息传送到远程主机4.服务器句柄得到消息并取得参数5.执行远程过程6.执行的过程将结果返回服务器句柄7.服务器句柄返回结果,调用远程系统内核8.消息传回本地主机9.客户句柄由内核接收消息10.客户接收句柄返回的数据我喜欢搜查更多的信息资料,所以我又找到了知乎上的回答。知乎1.7k的点赞,应该还是可以参考的。恰如回答提到的,RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。至于为什么使用RPC?答主也提到,无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同系统间的通讯,甚至不同组织间的通讯。这里再说一下关于Netty,Netty框架不局限于RPC,更多的是作为一种网络协议的实现框架,比如HTTP,由于RPC需要高效的网络通信,就可以选择Netty作为基础。除了网络通信,RPC还需要有高效的序列化框架,以及一种寻址方式,如果是带会话(状态)的RPC调用,还需要有会话的状态保持的功能。好了,让我们再来整理一下,什么是RPC?RPC(远程过程调用)一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远端系统资源。一般来说,RPC框架实现的架构原理都是类似的。可以这样说,客户端调用:负责发起RPC调用,为调用方用户提供使用API。服务端响应:主要是服务端业务逻辑实现。序列化/反序列化:负责对RPC调用通过网络传输的内容进行序列化与反序列化,不同的RPC框架有不同的实现机制。一般分为文本(XML、JSON)与二进制(Java原生的、Hessian、protobuf、Thrift、Avro、Kryo、MessagePack),需要注意的是,不同的序列化方式在可读性、码流大小、支持的数据类型及性能等方面都存在较大差异,我们可以根据需要自行选择。Stub:我们看成代理对象,它会屏蔽RPC调用过程中的复杂的网络处理逻辑,使其透明简单,且能够保持与本地调用一样的代码风格。通信传输:即RPC的底层通信传输模块,一般通过Socket在客户端与服务端之间传递请求与应答消息。公众号:Java猫说学习交流群:728698035现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不定期干货。

April 20, 2019 · 1 min · jiezi

腾讯云“智能+互联网TechDay”: 揭秘智慧出行核心技术与创新实践

在当前形势下,以移动互联网、人工智能、大数据、云计算、新能源等新一代技术为主导的新技术革命悄然来临 ,并在改变着出行市场。随着移动出行业务的高速发展,数据的不断积累,大数据技术成为出行行业的看家本领。很多行业公司也取得了丰富的实战经验。 本次闭门交流活动由腾讯云与msup公司联合举办,通过邀请腾讯云、东南亚最大的打车软件Grab、摩拜单车公司的技术负责人,一起谈谈在云计算架构、出行安全、大数据地图等面临的实战经验。如对本次活动感兴趣,扫描上图二维码报名即可,欢迎一起交流探讨。报名链接:https://www.huodongxing.com/e…欢迎CEO、CIO、CTO、架构师、开发主管等出行领域及互联网领域的负责人参加。

April 12, 2019 · 1 min · jiezi

详解服务器端的项目框架

导读我一直相信这句话,他山之石可以攻玉。在自己能力不够时,多学习别人的东西。这样,对自己只有好处,没有坏处。因而,经过将近一年的工作,研读了公司所使用的框架。我本想往架构师的方向靠近,但,自己的能力可能还不够,因而,不断地给自己充电。公司的项目是前后端分离的,前端使用HTML5,css3、jquery、vue.js、bootstrap等,以SVN做代码托管。后端采用maven构建项目,以git lab做代码托管。肯定有人会问,这两个都是版本库,但它们有什么区别?如果想要了解的话,可以参考该文档:Svn与Git的区别。现在几乎所有的公司都采用maven构建项目,很少会采用导入jar包的方式依赖第三方框架。maven介绍maven构建的项目有很多好处,首先其可以统一管理jar包,也就是说,我们在项目中不用手动导入jar包,我们只要添加依赖即可,如代码所示:<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${jdbc.version}</version></dependency>添加依赖之后,maven就会导入该jar包,导入jar包的顺序为:首先查找本地仓库,如果本地仓库没有,进入下面步骤。maven settings profile中的repository;pom.xml中profile中定义的repository。profile激活配置文件,比如正式环境的配置文件prd.properties和开发环境的Dev.properties文件。这也是打包的依据,是打开发环境的包,还是打正式环境的包,如图所示:pom.xml中的repositorys(定义多个repository,按定义顺序找);如果经过上面的步骤,没有找到相应的jar包,最后到我们的镜像(mirror)中查找。如果mirror中存在该jar包,从mirror中拷贝下来,存储到本地仓库中,进入到最初一步。如果mirror中也没有,maven就会报相应的错误。maven报出相应的错误时,也许,是我们本地没有该jar包,远程仓库也没有该jar包,我们可以参考这篇博客:在maven的pom.xml中添加本地jar包。它会教你如何创建本地仓库,并导入创建好的本地仓库。【备注】这篇博客以架构师的角度来讲解maven,所以,不具体讲解maven各个标签的含义。如果你想了解pom的各个标签的含义,可以参考这篇文档:pom.xml详解,或者,参考这篇教程:maven教程|菜鸟教程上面解说只是配置jar文件,但是,maven的功能远不止这些,从我们创建maven项目时,就已经进入到maven的开发环境中。maven项目有人和我说过,学一项知识,什么方式最快?那就是通过做项目。你在做项目的过程中,肯定会遇到很多问题,而你不得不去查找资料,从根源上认识到这个问题。因而,我以公司所做的某个项目为例,来讲解maven的依赖、继承、聚合等关系。我们所说的maven中的关系,其实就是pom的关系,即项目对象模型(Project Object Model)的简称。maven聚合首先,我们在创建cloudCodeSale项目时,就已经创建了父pom文件,如图所示:上图就是我们的父pom文件,你很清楚的看到gav坐标。同时,你从这张图上,也能得到其他信息,其打包方式是 pom,其还关联其他module,module名称和左边的列表名称一样。这就是我们所说的maven的聚合。父类同时聚合其子类。聚合的条件有两个:修改被聚合项目的pom.xml中的packaging元素的值为pom在被聚合项目的pom.xml中的modules元素下指定它的子模块项目既然所有的子模块的pom都继承父pom,为什么父pom要聚合子模块的pom文件?这个问题很好。因为对于聚合而言,当我们在被聚合的项目上使用Maven命令时,实际上这些命令都会在它的子模块项目上使用。这就是Maven中聚合的一个非常重要的作用。在实际开发的过程中,我们只需要打包(mvn install)父pom文件。我们在父pom上使用mvn celan、mvn compile和mvn package,其会自动对子模块:platform-core、platform-core-controller、portal/member-portal、portal/platform-portal、platform-cms、platform-cms-controller、platform-custom执行mvn celan、mvn compile和mvn package。没必要一个一个地打包,这样极容易出现错误,如图所示:maven继承机制如果很多模块都需要相同的jar包,我们可以单独写在一个pom中,其他模块使用该模块的公共部分,这就是我们常说的父类。不论是java语言,还是c++语言,或者现在的pom,其都体现这个思想。我们在上文也提到了子模块,现在模块platform-core讲解。继承父类的结构一般是这样的:<parent> <groupId>parent.groupId</groupId> <artifactId>parent.artifactId</artifactId> <version>parent.version</version> <relativePath>../pom.xml</relativePath> </parent> relativePath是父pom.xml文件相对于子pom.xml文件的位置,针对被继承的父pom与继承pom的目录结构是不是父子关系。如果是父子关系,则不用该标签;如果不是,那么就用该标签。因为在当前项目中,platform-core模块的目录的pom在父目录的pom中,其和父pom的目录结构是父子关系,因而可以省略relativePath该标签,如图所示:parent标签中的groupId、artifactId、version要和父pom中的标签中一致。maven的依赖关系正如我们所知道的,maven构建项目,不仅是因为其能够管理jar包,其还使模块化开发更简单了。因而,我们在开发的过程中,一般都分模块化开发。模块与模块之间的信息是不通的,但是,我们想要模块间的之间能够通信,这时,我们就想到了java中的依赖关系。比如,我们有一个模块,这个模块封装好了微信支付、支付宝支付、处理json格式、操作文件、ResultUtil、lambdaUtil、commonUtil等工具类,还有附件、头像、用户等实体类。这些工具类在任何项目中不会轻易改变,如果为了满足某些需求而不得不得修改,需要得到架构师的同意。因而,我们可以把它拿出来,单独定义为一个模块,也就是platform-core模块。但是,我们还有一个模块,在这个模块中,根据不同的项目,其定义不同的实体类、dao层类、事务层类、枚举类、接收前端传来参数封装成的query类、从数据库中取出的数据封装成的data类,到事务层可能会调用模块plateform-core中的方法,比如调用第三方系统接口的HTTPClientUtil.doPost(String url, Map<String, String> param),判断处理lambda表达式的LambdaUtil.ifNotBlankThen(String value, Consumer<String> function) ,等等。这个自定义类的模块,我们可定义为plateform-custom。plateform-custom需要用到platform-core中的方法,因而,这时,我们就需要考虑依赖关系,怎么添加对platform-core的依赖呢?如代码所示:<dependency> <groupId>com.zfounder.platform</groupId> <artifactId>platform-core</artifactId></dependency>我们这边是前后台分离的,后台用来录入数据,前台用来展示数据,因而,我们有一个portal目录,该目录下有两个子模块。一个是member-portal模块,一个是platform-portal模块,前者接收前台的接口参数,后者接收后台的接口参数。但不论哪个模块,都需要依赖plateform-custom中的事务层方法,同时,我们传的参数,可能信息分发的platform-cms-controller中的接口,也可能是核心接口platform-core-controller中的接口。因而,我们这里以member-portal模块来举例,依赖其他模块的代码如下:<dependencies> <dependency> <groupId>com.zfounder.platform</groupId> <artifactId>platform-core-controller</artifactId> </dependency> <dependency> <groupId>com.zfounder.platform</groupId> <artifactId>platform-cms-controller</artifactId> </dependency> <dependency> <groupId>com.zfounder.platform</groupId> <artifactId>platform-custom</artifactId> <version>1.0-SNAPSHOT</version> </dependency></dependencies>这些模块你会在上面的图片找得到。同时,我们来看member-portal的pom文件继承的父pom是怎么写的:补充上面的继承关系。这里面用到了<relativePath>../../pom.xml</relativePath>你会奇怪的是,为什么这里面用到了呢?其和父pom不是父子关系,而是孙子关系。这里使用到了两次点点,这是什么意思呢? ..表示上级目录。举个例子说明:比如,在我的服务器上的www目录中,有三个文件,分别是rsa_private_key.pem, rsa_private_key_pkcs8.pem, rsa_public_key.pem,还有一个testDir目录,testDir目录中还有目录testDir,现在我们通过cd ../testDir/testDir进入到子目录中,现在,我们想返回到www的根目录中,并查看rsa_public_key.pem文件的内容,因而,我们可以用cat ../../rsa_public_key.pem命令,其首先返回两级目录,然后找到rsa_public_key.pem文件并打开该文件。“被继承的父pom与继承pom的目录结构是不是父子关系”也不是绝对的,主要是选择继承者的pom中的子目录和父目录之间的关系,其中间隔了几层目录。maven激活文件激活文件在上文也提到了,我们为什么需要激活文件?如下面的两个配置文件,一个是测试环境的配置文件,名为platform-dev.properties,一个是正式环境的配置文件,名为platform-prd.properties。两个配置文件中都存在与数据库的连接,但是呢,数据库的ip地址是不一样的。如一下的代码所示:正式服的platform-prd.properties配置文件jdbc.url=jdbc:mysql://localhost/prd_databasejdbc.username=prd_usernamejdbc.password=prd_passwordjdbc.validationQuery=select 1 from dualjdbc.removeAbandonedTimeout=180jdbc.initialSize=10jdbc.minIdle=30jdbc.maxActive=100jdbc.maxWait=30000。。。测试服的platform-dev.properties配置文件jdbc.url=jdbc:mysql://intranet_ip/dev_databasejdbc.username=dev_usernamejdbc.password=dev_passwordjdbc.validationQuery=select 1 from dualjdbc.removeAbandonedTimeout=180jdbc.initialSize=10jdbc.minIdle=30jdbc.maxActive=100jdbc.maxWait=30000。。。我们的在配置文件中配置好了数据项,但是呢,我们怎么切换不同的配置文件呢?换句话说,我们怎么想要打正式服的包放到正式服上,怎么选择platform-prd.properties的配置文件呢?反之,怎么选择platform-dev.properties配置文件?这时,我们就用到了maven当中的profile标签,如下代码所示: <profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <build> <filters> <filter>../../platform-dev.properties</filter> </filters> </build> </profile> <profile> <id>prd</id> <build> <filters> <filter>../../platform-prd.properties</filter> </filters> </build> </profile></profiles>这些配置文件时写在member-portal、platform-portal、plateform-core和plateform-cms、plateform-customer模块的pom中的。但是,plateform-core和plateform-cms的配置中的filter和上面连个略有差异,其filter是这样的 <filter>../platform-dev.properties</filter>和 <filter>../platform-prd.properties</filter>,这就涉及到目录点的问题。maven依赖第三方包maven项目除了依赖本项目的,其还会依赖第三方包,比如自动生成set和get方法的lombok包,处理json格式的阿里巴巴下的fastjson包等等,我们也可以使用这种格式的依赖:<!–mysql jdbc驱动包 开始–><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${jdbc.version}</version></dependency><!–mysql jdbc驱动包 结束–>开发常用的jar包lombok<!– lombok驱动包 开始–><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version></dependency><!– lombok驱动包 开始–>我们在没有使用lombok之前,经常手动创建javabean的set个get方法,使用这个框架之后,其以注解的方式,可以自动生成set和get方法。同时,其强大的功能远不止这些,也可以生成无参构造器、全参构造器,指定参数构造器、重写toString方法、重写Hashcode、equals方法等等。如代码所示:/** * Created By zby on 17:37 2019/1/30 /@AllArgsConstructor@NoArgsConstructor@Data@ToString@EqualsAndHashCodepublic class Address { /* * 收货人 / private String consignee; /* * 手机号码 / private String phone; /* * 所在地区 / private String area; /* * 详细地址 / private String detail; /* * 标签 / private AddressTagEnum addressTag;}想要更深层次的了解这个框架,可以参考这个博客:Lombok使用详解fastjson<!– fastjson驱动包 开始–><dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.28</version></dependency><!– fastjson驱动包 结束–>fastjson是阿里巴巴开源的框架,其用来处理服务器端的json格式的数据。比如,我们需要将服务端的对象以json(JavaScript object Notation,js对象标记)格式传输到前端,但是,如果自己手动创建的话,势必会非常的麻烦,于是,我们借助这个框架,帮助我们生成json格式的对象。同时,如果我们要调用第三方接口,比如调用连连绑定银行卡的接口,其返回给我们的也是json对象的数据。但是,我们需要将其转化为我们定义的对象,调用其save方法,保存到数据库中,对账所用。对于,将对象转化为json格式的对象,如代码所示:@Testpublic void test() {// 地址 Address address = new Address(); address.setAddressTag(AddressTagEnum.ADDRESS_TAG_COMPANY); address.setArea(“杭州市….”); address.setConsignee(“zby”);// 用户 User user = new User(); user.setHobby(HobbyEnum.HOBBY_DANCING); user.setGender(“男”); user.setUserName(“蒋三”);// 订单 OrderSnapshot orderSnapshot = new OrderSnapshot(); orderSnapshot.setAddress(address); orderSnapshot.setId(1L); orderSnapshot.setName(“复读机”); orderSnapshot.setOrderNo(Long.valueOf(System.currentTimeMillis()).toString() + “1L”); orderSnapshot.setUser(user); System.out.println(JSON.toJSON(orderSnapshot));}其输出结果如图所示:但是,类似于解析json格式的数据,不只有fastjson框,还有org.json框架、Jackson框架。但经过有人验证呢,还是fastjson的效率更高一些。可以参考这篇博客:Gson、FastJson、org.JSON到底哪一个效率更高,速度更快org.json也是通过maven配置的,如代码所示:<!– json驱动包 开始–><dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20140107</version></dependency><!– json驱动包 开始–>如果想要深层次了解org.json,可以参考这篇博客:Java使用org.json.jar构造和解析Json数据想要更深层次的了解fastjson,可以参考这篇博客:Fastjson 简明教程spring相关配置如果从事java-web开发,一般会用到spring框架,这方面的教程太多了,笔者就不在这介绍,但我们会用到spring的这些框架:<!–spring 相关配置开始–><dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId></dependency>spring会集合很多框架,比如具有拦截效果的shiro框架,持久层的hibernate和mybatis框架等等。spring通过配置文件通过注解或者配置文件的方式,实现依赖注入(dependency injection)和控制反转(inversion of control)。通过@controller遍历相应的接口,实现前后端的接口对接。spring可以实现面向切面编程,实现某个业务点的单一执行。比如,专门处理事务的业务点。spring并不难,很快就能掌握到其精髓。如果想深入了解,可以参考这篇教程:Spring教程hibernate框架hibernate框架就类似于mybatis框架,其专门处理持久层的技术。我们将瞬时状态的对象存储到数据库中,变成持久状态的对象。我们也可以从数据库中取数据,以瞬时态的对象返回到前端。这就是一存一取的框架。其可以使用注解的方式创建数据表,也可以通过配置文件创建瞬时态的对象。但就目前为止,在很多情况下,我们都是通过注解的方式,实现数据表的创建。导入hibernate相关的框架,如下所示:<!–hibernate相关配置 开始–><!–hibernateh核心框架–><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId></dependency><!–hibernateh验证器–><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId></dependency><!–hibernateh缓存技术–><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId></dependency> <!–Java Persistence API ORM映射元数据 查询语言–><dependency> <groupId>org.hibernate.java-persistence</groupId> <artifactId>jpa-api</artifactId></dependency><!–hibernate相关配置 结束–>hibernate和mybatis具有同样的功能,如果想要了解mybatis,可以参考这篇教程:mybatis教程想要深入理解hibernate,可参考这篇教程:hibernate教程_w3cschooljbdc驱动包我们上面说了hibernate框架,但前提是,我们需要导入jdbc的框架包,如代码所示: <!– 数据库驱动包相关 开始–><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId></dependency><!– 数据库驱动包相关 结束–>这个驱动包主要处理java与数据库的连接,实现数据的增、删、改、查。我们没有用到这个包,但是hibernate用到了这个包,因而,我们需要导入这个包,以免数据库报错。alibaba的Druid包这个包有什么用吗?我们既然通过hibernate实现与数据库的交互,那么就需要在初始化时创建连接池。现在连接池有很多种,我们为什么选择了它Druid。<!– Druid驱动包相关 开始–><dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId></dependency><!– Druid驱动包相关 结束–>它是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。Druid是阿里巴巴开发的号称为监控而生的数据库连接池!时代在变化,我们也应该应世而生,与时俱进,才不会和时代脱轨。我们使用Druid来实现数据的配置,如代码所示: <bean id=“dataSource” class=“com.alibaba.druid.pool.DruidDataSource” init-method=“init” destroy-method=“close”> <property name=“driverClassName” value=“com.mysql.jdbc.Driver”/> <property name=“url” value="${jdbc.url}"/> <property name=“username” value="${jdbc.username}"/> <property name=“password” value="${jdbc.password}"/> <property name=“maxActive” value="${jdbc.maxActive}"/> <property name=“initialSize” value="${jdbc.initialSize}"/> <property name=“removeAbandoned” value=“true”/> <property name=“removeAbandonedTimeout” value="${jdbc.removeAbandonedTimeout}"/> <property name=“testOnBorrow” value=“true”/> <property name=“minIdle” value="${jdbc.minIdle}"/> <property name=“maxWait” value="${jdbc.maxWait}"/> <property name=“validationQuery” value="${jdbc.validationQuery}"/> <property name=“connectionProperties” value=“clientEncoding=UTF-8”/></bean>你们可以看到,value值是形参,而不是具体的值。因为我们根据不同的打包方式,其传入形参对应的实参不同。这也就是我们上文提到的,platform-dev.properties和platform-prd.properties配置文件,以及maven配置的激活文件。如果想要深入了解阿里巴巴的Druid框架,可以参考这篇博客:DRUID连接池的实用 配置详解阿里云短信短信业务一般固定不变,由架构师封装好,其他人直接调用即可,因而,该框架可以写进plateform-core模块中,其配置的代码如下所示:<!– 阿里短息驱动包配置 开始 –><dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-dysmsapi</artifactId></dependency><dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId></dependency><!– 阿里短息驱动包配置 结束 –>日志相关配置我们在开发的过程中,经常会使用到日志,来记录相应的错误、警告、信息。比如,我在使用连连支付做提现业务时,提现成功后其会回调我们的接口,从而显示在服务端的Tomcat页面中。再比如,我们在登录时,其会在Tomcat中显示相关信息,如图所示:我们都知道日志分为几种级别。这里就不再赘述了。日志分为好多种,我们推荐使用slf4j+logback模式。因为logback自身实现了slf4j的接口,无须额外引入适配器,另外logback是log4j的升级版,具备比log4j更多的优点,我们可以通过如下配置进行集成:<!– 日志驱动包配置 开始 –><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version></dependency><dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.7</version></dependency><dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.7</version></dependency><!– 日志驱动包配置 结束 –>我们这时就用到了plateform-prd.properties文件和plateform-dev.properties文件,因为,我们需要在这里面配置日志的输出位置。然后,在logback.xml中以参数的形式,调用文件中的输出位置,如图所示:如果想要了解更多的配置文件信息,请参考这篇博客:使用 logback + slf4j 进行日志记录commons家族我们在开发的过程中,经常用到Commons家族的驱动包,比如文件操作的io包,MD5加密和解密用的codec包。当然,我们也会用到java自带的local_policy驱动包,但有时需要替换替换该驱动包,否则,就会报出Illegal Key Size的错误。文件上传下载的fileupload驱动包,操作字符串类型的lang3包,配置的驱动包如下所示:<!–comon包相关配置–><commons-io.version>2.4</commons-io.version><commons-lang3.version>3.4</commons-lang3.version><commons-codec.version>1.10</commons-codec.version><commons-fileupload.version>1.3.1</commons-fileupload.version><!– apache common 开始 –><dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version></dependency><dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>${commons-io.version}</version></dependency><dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>${commons-codec.version}</version></dependency><dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons-fileupload.version}</version></dependency><!– apache common 结束 –>lang3包我们可以用其分割字符串,判断字符串是否为空格,判断字符串是否为空等等。如以下代码所示:public static void main(String[] args) { String keyword = “1-1-2”; if (StringUtils.isNotBlank(keyword)) { System.out.println(“keyword = " + keyword); } String[] keys = StringUtils.split(keyword, “-”); for (String key : keys) { System.out.println(“key=” + key); }}我们有时还会用其操作时间类,比如格式化时间等等,入一下代码:@Testpublic void testDate(){ String date1= FastDateFormat.getInstance(“yyyy-MM-dd”).format(System.currentTimeMillis()); System.out.println(“System.currentTimeMillis:"+date1); String date2= FastDateFormat.getInstance(“yyyy-MM-dd”).format(new Date()); System.out.println(“new Date:"+date2);}其功能远不止这些,具体可以参考这篇博客:commons-lang3工具包io包见名知意,IO即input和output的简写,即输入流和输出流。因而,我们经常使用到java自带的InputStream或FileInputStream的字节输入流,以及OutputStream或FileOutputStream的输出流。如果更高级的话,那么,就使用到了带有缓存效果的bufferReader输入流和bufferWrite输出流。这里面用到了装饰设计模式。什么是装修设计模式,可以自行学习。上面的操作比较复杂,我们就用到了apache下的io驱动包。这里就当做抛砖引玉了,想要有更深的了解,可以参考这篇博客:io包工具类codec包codec包是Commons家族中的加密和解密用的包,这里不做任何解释,具体可以参考这篇博客:Commons Codec基本使用fileupload包我们如果做java-web开发,经常会有文件上传和文件下载的功能。这时,我们就考虑到了Apache下面的 fileupload包,这可以完成文件的上传和下载。这里的文件不单单是指doc文件,也会指图片和视频文件。具体想要有更多的理解,可以参考这篇文档:commons-fileupload上传下载shiro包我们在web开发时,经常会涉及到权限问题,比如哪些页面不需要登录就能看,而哪些页面只能登录才能看。当用户在打开该页面之前,就进入到相应的过滤器中,来做相关业务的判断。如果通过,就进入到controller层;不通过,则抛出相应的异常给前端。这里就需要相应的权限控制。说到权限控制,我们不得不提到shiro框架。其有三大核心组件Subject, SecurityManager 和 Realms。这个百度百科上也说了,可以查看其解说内容:java安全框架 <!– shiro驱动包 开始 –><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId></dependency><!–shiro驱动包 结束 –>公司也会做相应的配置,配置如下:<?xml version=“1.0” encoding=“UTF-8”?><beans xmlns:util=“http://www.springframework.org/schema/util" xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xmlns=“http://www.springframework.org/schema/beans" xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!– 缓存管理器 –> <bean id=“cacheManager” class=“com..shared.framework.SpringCacheManagerWrapper”> <property name=“cacheManager” ref=“springCacheManager”/> </bean> <bean id=“springCacheManager” class=“org.springframework.cache.ehcache.EhCacheCacheManager”> <property name=“cacheManager” ref=“ehcacheManager”/> </bean> <bean id=“ehcacheManager” class=“org.springframework.cache.ehcache.EhCacheManagerFactoryBean”> <property name=“configLocation” value=“classpath:ehcache.xml”/> </bean> <!– 凭证匹配器 –> <bean id=“credentialsMatcher” class=“com.*.RetryLimitHashedCredentialsMatcher”> <constructor-arg ref=“cacheManager”/> <property name=“hashAlgorithmName” value=“md5”/> <property name=“hashIterations” value=“2”/> <property name=“storedCredentialsHexEncoded” value=“true”/> </bean> <!– Realm实现 –> <bean id=“userRealm” class=“com..shared.web.listener.MemberSecurityRealm”> <!–<property name=“credentialsMatcher” ref=“credentialsMatcher”/>–> <property name=“cachingEnabled” value=“false”/> <!–<property name=“authenticationCachingEnabled” value=“true”/>–> <!–<property name=“authenticationCacheName” value=“authenticationCache”/>–> <!–<property name=“authorizationCachingEnabled” value=“true”/>–> <!–<property name=“authorizationCacheName” value=“authorizationCache”/>–> </bean> <!– 会话ID生成器 –> <!–<bean id=“sessionIdGenerator” class=“org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator”/>–> <!– 会话Cookie模板 –> <bean id=“sessionIdCookie” class=“org.apache.shiro.web.servlet.SimpleCookie”> <constructor-arg value=“platform-portal-sid”/> <property name=“httpOnly” value=“true”/> <property name=“maxAge” value=“7200”/> </bean> <!– 会话管理器 –> <bean id=“sessionManager” class=“org.apache.shiro.web.session.mgt.DefaultWebSessionManager”> <property name=“globalSessionTimeout” value=“43200000”/> <property name=“deleteInvalidSessions” value=“true”/> <property name=“sessionIdCookieEnabled” value=“true”/> <property name=“sessionIdCookie” ref=“sessionIdCookie”/> </bean> <!– 安全管理器 –> <bean id=“securityManager” class=“org.apache.shiro.web.mgt.DefaultWebSecurityManager”> <property name=“realm” ref=“userRealm”/> <property name=“sessionManager” ref=“sessionManager”/> <property name=“cacheManager” ref=“cacheManager”/> </bean> <!– 相当于调用SecurityUtils.setSecurityManager(securityManager) –> <bean class=“org.springframework.beans.factory.config.MethodInvokingFactoryBean”> <property name=“staticMethod” value=“org.apache.shiro.SecurityUtils.setSecurityManager”/> <property name=“arguments” ref=“securityManager”/> </bean> <!– Shiro的Web过滤器 –> <bean id=“shiroFilter” class=“org.apache.shiro.spring.web.ShiroFilterFactoryBean” depends-on=“securityManager,memberShiroFilerChainManager”> <property name=“securityManager” ref=“securityManager”/> </bean> <!– 基于url+角色的身份验证过滤器 –> <bean id=“urlAuthFilter” class=“com.zfounder.platform.core.shared.web.filter.UrlAuthFilter”> <property name=“ignoreCheckUriList”> <list> <value>//common/enums/</value> <value>//security/</value> <value>//common/dd/</value> <value>//pictures/</value> <value>//common/sms/</value> <value>//wx/</value> </list> </property> </bean> <bean id=“memberFilterChainManager” class=“com.zfounder.platform.core.shared.web.listener.CustomDefaultFilterChainManager”> <property name=“customFilters”> <util:map> <entry key=“roles” value-ref=“urlAuthFilter”/> </util:map> </property> </bean> <bean id=“memberFilterChainResolver” class=“com..shared.web.listener.CustomPathMatchingFilterChainResolver”> <property name=“customDefaultFilterChainManager” ref=“memberFilterChainManager”/> </bean> <bean class=“org.springframework.beans.factory.config.MethodInvokingFactoryBean” depends-on=“shiroFilter”> <property name=“targetObject” ref=“shiroFilter”/> <property name=“targetMethod” value=“setFilterChainResolver”/> <property name=“arguments” ref=“memberFilterChainResolver”/> </bean> <!– Shiro生命周期处理器–> <bean id=“lifecycleBeanPostProcessor” class=“org.apache.shiro.spring.LifecycleBeanPostProcessor”/></beans>想要对其有更深的理解,请参考这篇博客:Shiro讲解工具类<!–汉字转拼音开源工具包–> <dependency> <groupId>com.github.stuxuhai</groupId> <artifactId>jpinyin</artifactId></dependency><!–网络爬虫的驱动包–><dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId></dependency><!–验证码生成工具包–><dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId></dependency><!–发送邮件–><dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId></dependency>因为篇幅的限制,这里就不再细说了,如果想要更深层次的了解,可以参考以下博客:汉字转拼音开源工具包Jpinyin介绍爬虫+jsoup轻松爬知乎使用kaptcha生成验证码使用javax.mail发送邮件图片验证码的配置文件如下:<?xml version=“1.0” encoding=“UTF-8”?><beans xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xmlns=“http://www.springframework.org/schema/beans" xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init=“true”> <bean id=“captchaProducer” class=“com.google.code.kaptcha.impl.DefaultKaptcha”> <property name=“config”> <bean class=“com.google.code.kaptcha.util.Config”> <constructor-arg> <props> <prop key=“kaptcha.border”>${kaptcha.border}</prop> <prop key=“kaptcha.border.color”>${kaptcha.border.color}</prop> <prop key=“kaptcha.textproducer.font.color”>${kaptcha.textproducer.font.color}</prop> <prop key=“kaptcha.textproducer.char.space”>${kaptcha.textproducer.char.space}</prop> <prop key=“kaptcha.textproducer.font.size”>${kaptcha.textproducer.font.size}</prop> <prop key=“kaptcha.image.width”>${kaptcha.image.width}</prop> <prop key=“kaptcha.image.height”>${kaptcha.image.height}</prop> <prop key=“kaptcha.textproducer.char.length”>${kaptcha.textproducer.char.length}</prop> <prop key=“kaptcha.textproducer.char.string”>1234567890</prop> <prop key=“kaptcha.textproducer.font.names”>宋体,楷体,微软雅黑</prop> <prop key=“kaptcha.noise.color”>${kaptcha.noise.color}</prop> <prop key=“kaptcha.noise.impl”>com.google.code.kaptcha.impl.NoNoise</prop> <prop key=“kaptcha.background.clear.from”>${kaptcha.background.clear.from}</prop> <prop key=“kaptcha.background.clear.to”>${kaptcha.background.clear.to}</prop> <prop key=“kaptcha.word.impl”>com.google.code.kaptcha.text.impl.DefaultWordRenderer</prop> <prop key=“kaptcha.obscurificator.impl”>com.google.code.kaptcha.impl.ShadowGimpy</prop> </props> </constructor-arg> </bean> </property> </bean></beans>里面的占位符来源于plateform-dev.properties或者plateform-prd.properties,这就是我们maven激活的配置文件的作用。测试依赖包我们在开发完一个功能后,首先会想到测试它走不走得通。我们可能会在main方法中测试,一个项目类中可以写多个main方法。如果每个功能类中都写一个main方法,未免会造成代码的混乱,一点都不美观和儒雅。java为什么一直推崇面向对象,任何在现实中真实的、虚拟的事物,都可以将其封装为为java中的对象类。对象与对象之间以方法作为消息传递机制,以属性作为数据库存储的机制。如果我们在每个功能中都写一个main方法,势必会破坏这种对象的美观性。因而,我们把测试的数据以对象的方式操作,这样,将其封装为一个测试包,比如,在我写的spring框架中,就把测试类单独拿出来,如图所示:<!– 测试依赖包 开始–><!– spring test –><dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version></dependency><!– 路径检索json或设置Json –><dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>${jsonpath.version}</version> <scope>test</scope></dependency><!– testng –><dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>${testng.version}</version></dependency><!– 单元测试的powermock –><dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-testng</artifactId> <version>${powermock.version}</version></dependency><dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>${powermock.version}</version></dependency><!–测试相关 结束–>以上是几种测试包的依赖,一个是spring的测试包,这里由于篇幅的限制,就不做详细的介绍了,网上有很多这方面的教程,想要深入的了解,可参考这篇博客:Spring-Test(单元测试)我们有时也会用到TestNG框架,它是Java中的一个测试框架,类似于JUnit 和NUnit,功能都差不多,只是功能更加强大,使用也更方便。测试人员一般用TestNG来写自动化测试,开发人员一般用JUnit写单元测试。如果你是测试人员,想对其有更全面的了解,可以参考这篇教程:TestNG教程,或者这篇博客::testNG常用用法总结如果想要更深层次的了解powermock,可以参考这篇博客:PowerMock从入门到放弃再到使用如果想要更深层次的了解JsonPath,可以参考这篇博客:JsonPath教程图片处理我们在开发的过程中,会把图片存放到服务器的某个文件夹下,即某个磁盘上。如果图片过大,会占用服务器的磁盘,因而,我们需要将图片缩略,来减少对内存的占用。这时,我们如果使用java原生的图片缩略图,是非常复杂的,因而,我们可以使用以下框架对图片进行操作。<!–图片处理驱动包 开始–><dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId></dependency><!–图片处理驱动包 结束–>这里不再细说,想要有更多的了解,可以参考这篇博客:Thumbnailator框架的使用Excel操作我们在工作的过程中,经常会将数据导出到Excel表,或将Excel表的数据导入数据库。我们以前使用poi框架,但是,超过一定量的时候,会占用大量的内存,从而降低导入的效率。阿里巴巴现在开放出操作Excel表的easyexcel框架,对百万级的导入影响不是很大。以下是maven配置两个驱动依赖:<!–阿里巴巴的easyexcel驱动包 –><dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>{latestVersion}</version></dependency><!–poi驱动包 –><dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>${poi.version}</version></dependency><dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${poi-ooxml.version}</version></dependency>这两个就不再细说,如果想要对easyexcel更深的了解,可以参考这篇博客:alibaba/easyexcel 框架使用。如果想要对poi有更深的了解,可以参考这篇博客:Apache POI使用详解guava包我们在开发的过程中,有时会用到guava驱动包。它是为了方便编码,并减少编码错误,用于提供集合,缓存,支持原语句,并发性,常见注解,字符串处理,I/O和验证的实用方法。使用它有以下好处:标准化 - Guava库是由谷歌托管。高效 - 可靠,快速和有效的扩展JAVA标准库优化 -Guava库经过高度的优化。同时,又有增加Java功能和处理能力的函数式编程,提供了需要在应用程序中开发的许多实用程序类的,提供了标准的故障安全验证机制,强调了最佳的做法等等。它的宗旨就是:提高代码质量、简化工作,促使代码更有弹性、更加简洁的工具。我们在项目中的配置包为:<!–guava驱动包 开始–> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId></dependency><!–guava驱动包 结束–>如果想要对其有更深的了解,可以参考这篇教程:guava入门教程freemarker包我们在开发的过程中,也许会用到这个框架。为什么要用到这个框架呢?我们有时需要动态地将xml文件转为doc文件,这个时候,就用到了freemarker包,如图所示:截图不是很全面,你会看到画红框的部分,这是一种占位符的标记,就相当于java中的形参一样。 当用户点击前端的下载按钮时,有些数据是无法直接转换成doc的,因为我们先把数据写进xml中,再将xml转化为doc。具体如何转换的可以参考该博客:Java将xml模板动态填充数据转换为word文档我们可以引用这个包: <!–freemarker驱动包 开始–><dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>${freemarker.version}</version></dependency><!–freemarker驱动包 结束–>由于篇幅限制,想要详细了解,可以参考这篇手册: freemarker在线手册servlet驱动包我记得当时在学java-web开发时,最开始用的就是servlet。接收客户端的输入,并经过一系列DB操作,将数据返回给客户端。但使用纯servlet不利于可视化界面。后来,使用了JSP开发,其是可视化界面。但是,当我们启动Tomcat后,JSP通过JSP引擎还是会转为servlet。从本质上来说,JSP和servlet是服务端语言。我最初用servlet和JSP开发的源码地址:图书馆项目后来,工作了以后。后端就用了springMVC,hibernate框架等,前端使用的是HTML、jQuery等。慢慢地脱离了JSP和servlet。但是,并没与完全与servlet分隔开,我们还时不时会用到servlet的一些类,比如HttpServletRequest,HttpServletResponse等类。既然使用了spring MVC框架,为什么还要用servlet的东西,比如,我们在导入和导出时,一个是接收前端导入的请求,一个是响应前端导出的请求。响应前端导出的代码,这里就用到了响应private static void downloadExcel(HttpServletResponse response, File newFile, String fileName) throws IOException { InputStream fis = new BufferedInputStream(new FileInputStream( newFile)); String substring = fileName.substring(fileName.indexOf(”/”) + 1); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); response.reset(); response.setContentType(“text/html;charset=UTF-8”); OutputStream toClient = new BufferedOutputStream( response.getOutputStream()); response.setContentType(“application/x-msdownload”); String newName = URLEncoder.encode( substring + System.currentTimeMillis() + “.xlsx”, “UTF-8”); response.addHeader(“Content-Disposition”, “attachment;filename="” + newName + “"”); response.addHeader(“Content-Length”, "” + newFile.length()); toClient.write(buffer); toClient.flush();}接收前端导入的请求 public static LinkedHashMap<String, List<JSONObject>> importMultiSheetExcel(HttpServletRequest request, LinkedHashMap<Integer, Integer> sheetDataStartRowMap, LinkedHashMap<Integer, String> sheetDataEndColMap) { LinkedHashMap<String, List<JSONObject>> resMap = new LinkedHashMap<>(); try { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; ifNullThrow(multipartRequest, ResultCodeEnum.ILLEGAL_PARAM); MultipartFile file = multipartRequest.getFile(“file”); Workbook work = getWorkbook(file.getInputStream(), file.getOriginalFilename()); ifNullThrow(work, ResultCodeEnum.ILLEGAL_PARAM); 。。。}虽然我们现在使用了spring MVC,还是用到了servlet,而且shiro里面要使用到,以下是代码的配置:<!–servlet 开始–><!–shiro里面要使用到–><dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version></dependency><!–servlet 结束–><dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version></dependency><!–servlet 结束–>如果想要了解servlet的话,可以参考该文档:Java Servlet API中文说明文档Lucene全文检索有时,我们在开发的过程中,需要做全文检索数据,就比如,我在Word文档中,全文检索某个词、某句话等,如图所示:这就是web端的全文检索。但是我做Java,当然,也需要全文检索。因而,我们就想到了Lucene。它是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里,它是一个成熟的免费开源工具。就其本身而言,它是当前以及最近几年最受欢迎的免费Java信息检索程序库。我们在java的maven库中的配置为: <!– lucene 开始 –><dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>${lucene.version}</version></dependency><dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-highlighter</artifactId> <version>${lucene.version}</version></dependency><dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-common</artifactId> <version>${lucene.version}</version></dependency><!– lucene 结束 –>想要对其有更深的了解,可以参考这篇笔记:Lucene学习笔记Quartz任务调度我们在开发的过程中,总想着要在某个时间,执行什么样的事情,于是呢,我们就相当了任务调度,比如:每天八点按时起床每年农历什么的生日每个星期都要爬一次山我们就可以用到Quartz这个框架,我们需要做一些配置,如图所示:我们可以在maven中的配置为:<!– quartz驱动包 开始–><dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>${quartz.version}</version></dependency><!– quartz驱动包 结束–>想要对其有根深多的了解,可参考这篇博客:Quartz使用总结zxing二维码我们经常使用到二维码,比如,添加微信好友的二维码,支付二维码、扫一扫二维码等等,那么,这是怎么实现的呢,其实,这有一个工具包,就是zxing工具包。它是谷歌旗下的工具类,我们可以用它来生成我们想要的二维码,但是,我们先要在maven项目中配置它。如代码所示:<!– 二维码驱动包 开始–><dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>${zxing.version}</version></dependency><dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>${zxing.se.version}</version></dependency><!– 二维码驱动包 开始–>想要对其有根深的了解,可以参考这篇博客:zxing实现二维码生成和解析WSDL包这个我也不大懂,也没有操作过,如果想要了解的话,可以参考这篇文档:WebService中的WSDL详细解析我们在maven中的怕配置为:<!– WSDL驱动包 开始–> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>${wsdl4j.version}</version></dependency><!– WSDL驱动包 结束–>配置文件配置文件来源于框架中的以下文件,如图所示:所有的配置文件都来源于资源包。这里就不再细说。总结要想成为架构师,首先学习别人的东西,他山之石,可以攻玉。 ...

March 30, 2019 · 5 min · jiezi

通过Spring Boot中的手动Bean定义提高启动性能

原文:https://blog.csdn.net/qq_4288…使用Spring Boot时你不想使用@EnableAutoConfiguration。你应该怎么做?Spring本质上是快速且轻量级的,但是如何让Spring更快?其中一条建议是可以改善启动时间,那就是考虑手动导入Spring Boot配置,而不是自动全部配置。对所有应用程序来说,它不是正确的做法,但它可能会有所帮助,理解选项是什么肯定不会有害。在本文中,我们将探讨各种手动配置方法并评估其影响。完全自动配置:Hello World WebFlux作为基准,让我们看一下具有单个HTTP端点的Spring Boot应用程序:@SpringBootApplication@RestControllerpublic class DemoApplication { @GetMapping("/") public Mono<String> home() { return Mono.just(“Hello World”); } public void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}这个应用启动大约一秒钟,或者更长一些,具体取决于您的硬件。它在这段时间内做了很多工作 - 设置日志系统,读取和绑定配置文件,启动Netty并侦听端口8080,提供到@GetMapping应用程序的路由,还提供默认的错误处理。如果Spring Boot Actuator在类路径上,你还会得到一个/ health和/ info端点(由于这个原因,启动它需要更长的时间)。@SpringBootApplication注释实际包含@EnableAutoConfiguration功能,能够自动提供所有有用的功能。这就是Spring Boot流行的原因,所以我们不想丢弃这个功能,但我们可以仔细看看实际发生的事情,也许可以手动完成一些,看看我们是否学到了什么。注意:如果你想尝试这个代码,很容易从Spring Initializr获得一个空的WebFlux应用程序。只需选中“Reactive Web”复选框并下载项目即可。手动导入自动配置虽然@EnableAutoConfiguration可以轻松地为应用程序添加功能,但它也可以控制启用哪些功能。大多数人都乐意做出妥协 ,但是过度追求易用性也会失控,可能存在性能损失 , 应用程序可能会启动时慢一点,因为Spring Boot必须做一些工作才能找到所有这些功能并安装它们。事实上,找到正确的功能并没有太大的努力:首先类路径扫描,经过仔细优化后,实现有条件的评估非常快。其中应用程序的批量启动时间(80%左右)其实是由JVM加载类时间,因此实际上使其启动更快的唯一方法是通过安装更少的功能来让JVM加载更少。我们可以在注释@EnableAutoConfiguration中使用exclude属性禁用自动配置。一些单独的自动配置也有自己的布尔配置标志,可以在外部设置,例如我们可以使用的JMX spring.jmx.enabled=false(例如, 作为系统属性或在属性文件中)。我们可以走这条路并手动关闭我们不想使用的所有东西,但是这有点笨拙,并且如果类路径改变也不会阻碍其他组件功能被发现。现在我们只是使用我们想要使用的那些功能,我们可以将其称为“点菜”方式,而不是“完全自动配置autoconfiguration”中的“所有的你必须吃进去”。自动配置也其实自动寻找@Configuration标注的类,我们可以使用@Import替代@EnableAutoConfiguration,例如,以下是上面的应用程序,具有我们想要的所有功能(不包括执行器):@SpringBootConfiguration@Import({ WebFluxAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class, ErrorWebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, ConfigurationPropertiesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class})@RestControllerpublic class DemoApplication { @GetMapping("/") public Mono<String> home() { return Mono.just(“Hello World”); } public void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}此版本的应用程序仍将具有我们上面描述的所有功能,但启动速度更快(可能大约30%左右)。那么我们为了更快的启动而放弃了什么呢?这是一个快速的概述:Spring Boot自动配置的完整功能包括实际应用程序中可能实际需要的其他内容,而不是特定的小样本。换句话说,30%的加速并不适用于所有应用程序,您的情况可能会有所不同。手动配置很脆弱,很难猜到。如果您编写了另一个执行稍微不同的应用程序,则需要进行不同的配置导入。您可以通过将其提取到便利类或注释中并重新使用它来缓解此问题。@Import行为方式与 @EnableAutoConfiguration配置类的排序方式不同。@Import在某些类具有依赖于早期类的条件行为的情况下,顺序很重要,如果你的配置类有前后依赖顺序关系,你必须要小心。在典型的实际应用中存在另一个排序问题。要模仿@EnableAutoConfiguration,首先需要处理用户配置,以便它们可以覆盖Spring Boot中的条件配置。如果使用@ComponentScan而不是@Imports,则无法控制扫描的顺序,或者处理这些类的处理顺序,您可以使用不同的注释来缓解这种情况(参见下文)。Spring Boot自动配置实际上从未被设计为以这种方式使用,使用这种方式可能会在您的应用程序中引入细微的错误。对此的唯一缓解方式就是是详尽的测试,让它以您期望的方式工作,并且对升级持谨慎态度。增加Actuators如果我们也可以在类路径上添加Actuator:@SpringBootConfiguration@Import({ WebFluxAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class, ErrorWebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, ReactiveManagementContextAutoConfiguration.class, ManagementContextAutoConfiguration.class, ConfigurationPropertiesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class})@RestControllerpublic class DemoApplication { @GetMapping("/") public Mono<String> home() { return Mono.just(“Hello World”); } public void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}与完整@EndpointAutoConfiguration应用程序相比,此应用程序启动速度更快 (甚至可能快50%),因为我们只包含与两个默认端点相关的配置。Spring Boot使用自动配置则默认地会激活所有端点,但不会将它们暴露给HTTP,如果我们只关心/ health和/ info,使用自动配置可能有些浪费,但自动配置也会在表中留下许多非常有用的功能。Spring Boot可能会在将来做更多工作,以禁用未曝光或未使用过的执行器。有什么不同?手动配置的应用程序有51个bean,而完全引导的自动配置应用程序有107个bean(不计算执行器)。所以它启动起来可能并不令人意外。在我们采用不同的方式实现示例应用程序之前,让我们先看看我们遗漏了什么,这样才能更快地启动它。如果在两个应用程序中都列出bean定义,您将看到所有差异来自我们遗漏的自动配置,以及Spring Boot不会有条件地排除这些自动配置。这是列表(假设您使用spring-boot-start-webflux时没有手动排除):AutoConfigurationPackagesCodecsAutoConfigurationJacksonAutoConfigurationJmxAutoConfigurationProjectInfoAutoConfigurationReactorCoreAutoConfigurationTaskExecutionAutoConfigurationTaskSchedulingAutoConfigurationValidationAutoConfigurationHttpMessageConvertersAutoConfigurationRestTemplateAutoConfigurationWebClientAutoConfiguration这就是我们不需要的12个自动配置(无论如何),并且在自动配置的应用程序中导致了56个额外的bean。它们都提供了有用的功能,所以我们可能希望有一天再次将它们包括在内,但是现在让我们假设我们更愿意在没有他们的情况下使用。spring-boot-autoconfigure有122个自动配置(还有更多spring-boot-actuator-autoconfigure)和完全引导的自动配置的示例应用程序上面只使用了其中的18个。计算使用哪些是非常早的,并且在任何类甚至加载之前,大多数都被Spring Boot丢弃,这种计算非常快(几毫秒)Spring Boot自动配置导入可以通过使用不同的注释来部分地解决与用户配置(必须最后应用)和自动配置之间的差异相关联的排序问题。Spring Boot为此提供了一个注释:@ImportAutoConfiguration来自Spring Boot Test附带spring-boot-autoconfigure的 测试切片功能。因此,您可以替换上面示例中的注释@Import, @ImportAutoConfiguration效果是推迟自动配置的处理,直到所有用户配置加载(例如,通过@ComponentScan或接收@Import)。如果我们准备将自动配置列表整理成自定义注释,我们甚至可以更进一步。不仅仅是直接使用@ImportAutoConfiguration,我们可以写一个自定义注释:@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@ImportAutoConfigurationpublic @interface EnableWebFluxAutoConfiguration {}此注释的主要特征是它带有元注释 @ImportAutoConfiguration。有了这个,我们可以在我们的应用程序中添加新的注释:@SpringBootConfiguration@EnableWebFluxAutoConfiguration@RestControllerpublic class DemoApplication { @GetMapping("/") public Mono<String> home() { return Mono.just(“Hello World”); } public void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}并列出实际的配置类/META-INF/spring.factories:com.example.config.EnableWebFluxAutoConfiguration=\org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration这样做的好处是应用程序代码不再需要手动枚举配置,而且现在由Spring Boot处理排序(属性文件中的条目在使用之前会进行排序)。缺点是它仅对需要精确这些特征的应用程序有用,并且需要在想要做一些不同的事情的任何应用程序中进行替换或扩充,当然它仍然会很快 - Spring Boot为排序做了一些额外的工作,但实际上并不是很多。在合适的硬件上,它可能仍然会在不到700毫秒的时间内启动,并带有正确的JVM标志。函数Bean定义在前面的文章中,我提到函数bean定义将是使用Spring启动应用程序的最有效方法。我们可以通过重新编写所有Spring Boot自动配置为ApplicationContextInitializers来将这个应用程序额外挤出10%左右。您可以手动执行此操作,或者您可以使用已为您准备的一些初始化程序,只要您不介意尝试某些实验性功能即可。目前有2个项目正在积极探索基于函数bean定义的新工具和新编程模型的概念:Spring Fu和 Spring Init。两者都提供至少一组函数bean定义来替换或包装Spring Boot自动配置。Spring Fu是基于API(DSL)的,不使用反射或注释;Spring Init具有函数bean定义,并且还具有用于“单点”配置的基于注释的编程模型的原型。其他地方都有更详细的介绍。这里要注意的要点是函数bean定义更快,但如果这是你主要考虑的问题,请记住它只有10%的效果。只要将所有功能放回到我们上面剥离的应用程序中,您就可以重新加载所有必需的类,并重新回到大致相同的启动时间。换句话说,@Configuration本身运行时处理的成本 并不是完全可以忽略不计,但它也不是很高(在这些小应用程序中可能只有10%左右,或者可能是100毫秒)。总结Spring Boot自动配置非常方便,但可以称之为“吃进所有你可以吃的东西”。目前(从2.1.x开始)它可能提供比某些应用程序使用或要求更多的功能。在“菜单单点”方法中,您可以使用Spring Boot作为准备和预测试配置的便捷集合,并选择您使用的部件。如果你这样做,那么@ImportAutoConfiguration是工具包的一个重要部分,但是当我们进一步研究这个主题时,你应该如何最好地使用它。Spring Boot的未来版本以及可能的其他新项目(如Spring Fu或Spring Init)将使得在运行时使用的配置选择变得更加容易,无论是自动还是通过显式选择。注意,@Configuration本身在运行时处理并不是免费的,但它也不是特别昂贵(特别是使用Spring Boot 2.1.x)。您使用的功能数量越少,加载的类越少,启动速度越快。最后,我们不希望 @EnableAutoConfiguration失去其价值或受欢迎程度。写在最后:既然看到这里了,觉得笔者写的还不错的就点个赞,加个关注呗!点关注,不迷路,持续更新!!! ...

February 28, 2019 · 1 min · jiezi

关于公司架构管控的思考

假想背景:现状是,各子系统的新建及重大迭代都会形式化地走架构审批流程,但应用架构是否设计以及是否合理,信息技术部门不能掌握。而架构规划部门的架构师人屈指可数,面对总人数达数百人的开发团队所负责的几十子系统、每个月数十个迭代特性,无法做到直接帮助开发团队详尽的进行架构设计。由此提出:架构审批流程不代表架构设计、架构规划部门要加强架构管控。要做好架构管控,需要能够回答几个问题:架构管控的目的是什么?架构管控的目标是什么?架构管控需要管控什么内容?如何进行管控?一、目的一个稳定发展、创新发展的企业,支援业务发展的信息系统的稳定与效率同等重要。架构管控的目的,要指导各团队技术负责人设计出合理的系统,能够满足稳定与开发效率的要求,能够满足功能与非功能的需求,能够考虑到各级相关者的意见;并且还要有考察开发过程及运营过程的机制,以确定最终交付的软件系统复合架构设计及开展架构设计的持续改善工作。二、制定目标为了达到这些我们架构管控的目标又是什么呢?发布一份指导意见?发布一份制度说明?发布一份评分表?我认为这些应该归属于如何进行管控,而不是目标。我们需要梳理现状,找出主要矛盾,量化主要矛盾,形成目标(SMART原则别忘记~~)(一)、主要生产问题、客户投诉及分类从客户反馈中可以抓住主要矛盾。(二)、信息技术方面的主要矛盾外购产品 vs 二次改造早期从外部采购的产品一般会使用比较老旧的开发框架,进行二次改造困难,常带来较多故障,并且开发效率低下。系统解耦 vs 互相影响分布式带来较好的伸缩性等非功能特性的同时,也带来了复杂度 —— 系统间相互影响较难控制,给设计和开发增大了难度。开发团队对科技公共平台的不熟悉 vs 强制使用业务数据模型混乱 vs 新需求5、控制 vs 创新(三)、形成架构管控目标控制新增外购系统的架构方案的合理性、梳理既存外购系统的架构、提升开发效率。降低分布式系统的开发难度、提升分布式系统的交付质量。降低科技公共平台的使用难度。引导、规范新技术的引入。

January 22, 2019 · 1 min · jiezi

【福利来袭】你们期盼已久的Linux架构师全套书籍,免费领!

今天学神的老师们送福利啦:《Linux云计算架构师》 四册书籍1套(1400页)书籍福利活动规则参与人群:关注了微信公众号【学神IT教育】的小伙伴活动福利:《Linux云计算架构师》四册书籍赠送,共3个名额参与方式①分享此文至朋友圈,截图发至公众号后台②留言内容:说说想要获得此书的理由(字数不限)③留言区留言点赞,排名前三(即获赞最高)即可获得书籍三者都要满足,才会获得哦活动时间:1月17日-21日晚18:00温馨提示:该活动在「学神IT教育」公众号举行,请扫描下面二维码进行关注(打开历史文章,在最新一篇文章留言参与) 额外福利:没有获奖的小伙伴可以添加下方老师微信,均可获得5G学习资料大礼包一份添加下方老师微信,可获取5G学习大礼包老师QQ:1514460659 感谢大家一直以来对学神的关注和支持,能够看到这篇文章的小伙伴肯定是已经了解过学神,甚至很多人都听过学神的Linux,Python,RHCE,网络工程师,大数据方向的课程也相信大家对MK老师,CD老师,While老师 For老师Django老师不陌生。精选课程为什么那么多人想要此书?1. 本书区别于以往你们所看过的Linux方面的书籍,介绍了一种与传统学习方式不同的深度学习方式,主要以实际动手操作为主、理论为辅的形式教学。2. 书中所讲述的CentOS 7版本操作系统内容,适用人群广,特别零基础的读者,从零基础到入门、到精通。以实战、实例讲解教学,更为容易学、容易理解、容易上手。3. 书中覆盖了所有Linux在企业中运用的知识点架构,Kubernetes,Devops,Openstack,Docker,MySQL、KVM虚拟化、集群、存储、调优、安全等内容全覆盖4. 本书为珍贵版套装教程书,不对外进行售卖,仅支持内部学员学习使用,与书籍的商业价值相比,学神更看重的是它的技术价值与文化价值!什么样的人适合学习此书?1> 云计算工程师2> 运维工程师3> 程序架构师4> 系统开发工程师5> 准备考取RHCERHCA的人员6> 想转行从事Linux云计算方向的人员7> 其他对Linux感兴趣的人员作者简介MK(申建明)学神IT教育校长,教学总监,8年Linux使用及管理经验,5年IT在线教育培训经验。拥有RHCE、RHCA及Openstack证书。精通Linux、思科、C++等技术。曾任职神州数码、新浪Linux高级运维工程师和高级运维总监。拥有丰富的服务部署、维护及监控经验。对基于linux下开源程序LB、Openstack,Docker,K8S集群等技术颇有研究。MK老师RHCARHCEOpenstack证书作者简介CD(王磊)学神IT教育Linux课程高级讲师,具有8年Linux使用及管理经验,5年企业linux运维经验,3年IT教育培训经验。拥有RHCE、RHCA证书、红帽官方讲师RHCI认证。曾负责中国联通公有云项目及光大银行,民生银行网上银行项目,并参与高并发网站架构设计。拥有丰富的一线运维经验,擅长系统服务搭建、维护、调优、自动化运维等。对于开源软件Lvs,Keepalived,Openstack,Docker,Jenkins,Ansible等技术都有使用及维护的经验。 CD老师RHCARHCE证书你能从书中学到什么?第一册:Centos7操作系统管理入门到精通内容概要:部署虚拟环境、安装Linux系统;常用的Linux命令;与文件读写操作有关的技术;使用Vim编辑器编写和修改配置文件;用户身份与文件权限的设置;磁盘设备分区、格式化以及挂载等操作;部署RAID磁盘阵列和LVM;网络相关命令;shell脚本基础到实战等……第二册:Linux常见服务管理入门到精通-含MySQL高级DBA内容概要:SSHD服务搭建管理和防止暴力破解;Rsync+sersync实现数据实时同步;搭建DHCP服务和NTP网络时间同步;搭建FTP服务器实现文件共享和NFS服务器配置;搭建DNS服务器实现域名解析;使用Apache搭建Web网站服务器;搭建无人执守安装服务器;配置iptables防火墙基础;iptables -案例实战讲解;Visio如何制作基本流程图;MySQL高级DBA(共11章);Zabbix服务搭建使用;使用自动化运维工具Ansible集中化管理服务器等……第三册:Linux资深知识:集群-存储-调优-安全内容概要:使用LVS搭建集群实现负载均衡;keepalived+LVS-DR集群;使用nginx-haproxy实现七层负载均衡;CentOS 7部署 Ceph分布式存储架构;部署Hadoop高性能集群;Linux操作系统调优;使用Sentinel实现Redis集群高可用部署;使用Varnish为网站加速;实战Aache调优;实战Apache调优进阶;实战nginx调优;md5-sha1-哈希算法使用方法-数字证书;CA认证过程及https实现方法;webshell-防止DDOS-暴力破解-自动劫持密码;搭建jumperserver堡垒机管理及实战分解等……第四册:Linux前沿技术:虚拟化-openstack私有云-docker内容概要配置KVM网络桥接功能;解决centos6系统上shutdown关不了虚拟机的问题;KVM虚拟机克隆和快照;部署kvm;OpenStack部署方法;使用本地yum源在Centos7.4系统部署OpenStack Pike版本;外网安装openstack需要配置的yum源;openstack-allinone-使用方法;使用fuel的web界面安装多结点openstack;openstack镜像制作方法;部署docker容器虚拟化平台;配置docker静态IP地址-配置docker私有仓库;搭建Kubernetes容器集群管理系统;使用kubectl管理Kubernetes容器平台;基于k8s搭建redis集群等……①你获得的可是1400页的四册书籍1套, 并且是学神独家出版的内部书籍, 不对外进行售卖,是珍藏版书籍, 想要获得此书,还得拼点实力的哦!② 除此之外,点击下方“阅读原文” 报名Linux免费课程, 直播间内也会不定期举办抽奖活动!重要的事情说三遍活动真实有效中奖结果会在22日「学神IT教育」公众号发文公布

January 18, 2019 · 1 min · jiezi