• 架构师的快速成长 lcl


    一、架构师成长指南

      1、架构师成长关键

        想成为架构师,必须系统的学习架构方法论和技术。

        架构思维 VS 程序思维:程序思维是指翻译、逻辑、实现的叠加,也就是将业务逻辑翻译成为代码实现;架构思维是指判断、取舍、创新的叠加,也就是判断业务复杂度,对架构进行取舍和创新

        架构师的成长路线:工程师  ->  高级工程师  ->  技术专家  ->  初级架构师  ->  中级架构师  ->  高级架构师

          架构师的能力模型:架构师需要从技术、业务、管理三个方面进行提升,技术指的是技术深度、技术宽度、技术广度,级别越高,对应的业务理解要求也会越高,另外就是团队管理和业务管理。

        对于架构师来说,本质还是做技术,因此这三个的优先级为技术 > 业务 > 管理

      2、架构师成长经验教训

        工程师:

          P5,一般是工作 1~3 年,在这一阶段,主要是基础,例如自己使用的环境、工具、流程等等。

          学习:碎片化时间,系统化学习,例如通过经典书籍系统学习:运行环境、编程语言、网络基础

          常见的错误做法:概括就是三大坑,直接看编译原理、xxx内核代码、XX算法代码,这种跟自己的实际工作没有什么关联,且会占用大量的时间

        高级工程师:

          P6,一般是工作 2~5 年,通过学习经验,可以独立自主的完成功能,在这一阶段就需要知道所用技术的原理,常见的套路,最终来实现自己的功能

          学习:掌握基础原理,例如JVM、开源软件等,同时需要学习套路,例如分库分表、缓存、SOLID、设计模式、MVP等

          常见的错误做法:贪大求全,看了很多,但都是蜻蜓点水

        技术专家:

          P7,一般是工作 4~8 年,是一个技术团队的技术专家,要有技术宽度、技术深度,同时可以负责一个子业务,这里对于技术深度要求更多一些。

          学习:链式学习法、比较学习法,同时需要熟悉核心源码,成熟的开源中间件,例如:Redis、Nginx、Netty等 

           常见的错误做法:生搬硬套,直接拷贝大厂技术

        初级架构师:

          P7+/P8,一般是工作 5~10 年,是一个领域的专家,且对领域技术精通,同时了解业界的技术,掌握响应的方法论,且要了解端到端业务

          学习:掌握架构方法论,例如风险驱动、面向复杂度、DDD,同时需要多业界交流,例如参加技术大会,关注大厂技术等

          常见的错误做法:过度依赖以往的成功经验

        中级架构师:

          P8+/P9,一般工作 8 年以上,所做的系统复杂,了解技术本质,同时要修炼内功,对技术广度和行业有很深的了解

          学习:内外兼修,提升技术内功,例如FLP、Paxos、CPU局部性,同时多参与业界交流,输出经验和方法,扩大业界影响力

          常见的错误做法:好大喜功、过度设计、炫技式设计

        高级架构师:

          P10,10年+,主要是架构模式以及创造力

      架构师层级结构:

            

     二、架构师如何避免从入门到忘记

      架构师能力提升的主要困境

      (1)学不动

        没有时间,要求高:主要体现在架构师对于技术宽度和广度有更多要求;新技术层出不穷,不学怕错过,学了怕浪费

      (2)记不住

        不成体系,陷入细节:主要体现在没有整理成体系,迷信源码,以为不懂源码就不能用;总觉得自己没有动手写过代码,心里没底

      (3)用不上

        没有机会,理解不深:主要体现在业务目前看不到应用场景;自己不是架构师,没有决策权

      那么如何避免从入门到放弃呢?

        针对上面提到的学不动、记不住、用不上,分别对应以下学习方法。

            

      常见的疑惑:

        用的时候学还是先准备着?机会是留给有准备的人

        技术太多,学那些?工作相关,级别相关

        架构师要学到什么程度?技术本质、优缺点、应用场景

      举个例子,要不要学人工智能?

        P5/P6:Android App 业务功能开发,那么用不着学人工智能

        P7/P8:P7/P8 Android 开发的 Team Leader,团队规划和技术演进需要学习,包括人工智能的原理和应用场景。

        P9:P9 级别,不管是什么技术方向都要学,人工智能的基本原理、行业的发展现状、成功和失败的案例、相关的产业链信息。

      学习方法:

        1、海绵学习法(不要用学校的学习方法来应对职场的学习!)

          海绵学习法:时间就像海绵里面的水,挤挤总是有的。

          具体技巧:碎片化时间,系统化学习(书籍、专栏、课程);贵在坚持:二十英里法则,不要突击,也不要考验人性。

          应用场景:如何找到学习的时间。

          时间是“挤出来”,3 个 30 分钟,利用或者节省路途时间,周末 4 小时:地铁来回 1 个小时、每天早晚 30 分钟、上班第一个 30 分钟、周末 4 小时

          常见的疑惑:

          (1)碎片化时间学习感觉效率不高怎么办?职场提升不是学校考试,积累比效率更关键!

          (2)有的内容看不下去怎么办?1. 换一本;2. 飞轮效应。

          (3)感觉学习效率很低怎么办? 飞轮效应。

          飞轮效应:为使静止的飞轮转动起来,已开始你必须使很大的力气,飞轮转的越来越快,达到某一临界点后,你无需再费更大的力气,飞轮依旧会快速转动,而且不停的转动。也就是说积累越多,学得越快。

        2、play学习法

          paly学习法:通过模拟实践中的场景来进行学习和训练。

          具体技巧:主动创造 Do 的机会来提升自己对新技能的理解和记忆。

          应用场景:学习新技术。

          Play学习法原理:

            

           常见场景:

            

           play落地场景:

            自己没有好的机器怎么办?工作环境的机器上创建自己的账号。

            每个都 Play 感觉投入很大?1. 不要急于求成;2. 组队打怪。

            性能测试对环境和数据要求很高,特别费时间怎么办? 拿来主义,上网找结果,自己真的要用的时候再结合业务详细测试。
        3、Teach 学习法

          Teach学习法:通过给别人讲解来提升自己的理解。

          具体技巧:1. 写作;2. 培训;3. 演讲。

          应用场景:学习新技术。

          Teach 学习法的核心作用

           (1)体系化:梳理思路和体系。无论培训还是写文章,会强迫自己去思考先讲什么,后讲什么,为什么重点讲这些……这就是体系化的过程。

          (2)完善细节:用他人的输入完善自己的盲区。每个人都会有一些经验和关注点,文章的评论,培训的讨论,都可以帮助自己弥补盲区,完善细节。

          (3)加深记忆:写过、讲过、讨论过的内容,印象更深刻。写作、讨论、培训过程中,大脑大量神经元被激活,记忆和理解更深刻。

          (4)锻炼能力:锻炼自己的临场反应和抗压能力。克服面对多人时的恐惧,提升临场反应和抗压能力,为晋升和面试打好基础。

          Teach 落地的一些技巧:

            我没有文学天分,写作水平很差怎么办?技术文章的写作不是文学创作,关键在于逻辑。

            我没有彻底掌握某项技术,不敢培训怎么办?永远都没有彻底掌握这个说法,迭代学习。

            每次学习新技术都要写作和培训么,感觉时间不够? 工作强相关的自己写,纸上得来终觉浅。

    三、架构师如何高效学习技术

       技术能力的三个维度:技术深度、技术宽度、技术广度

        技术深度:单项技术的纵深掌握程度。例如:1. Redis;2. Java 并发;3. Vue。

        技术宽度:同领域多个类似技术的掌握程度。例如:1. Redis、Memcached;2. Java 并发、Go 并发;3. Vue、React。

        技术广度:跨领域的技术掌握程度。 例如:1. 大数据、人工智能;2. 电商、支付;3. 前端、后端。

      架构师能力变化模型

             

       1、链式学习法:

        链式学习法:自顶向下,逐步深入,一环扣一环。

        具体技巧:领域分层:自顶向下、层层关联;细节分层:由表及里、层层深入。

        应用场景:晋升或者面试的时候“追命连环问”,例如:Netty → Reactor →Java NIO → epoll → 多路复用。

        链式学习法的两类深度分层图:

            

        领域分层:上层依赖下层,比如 Netty 依赖 Java 网络编程,Java 网络编程在 Linux 上又依赖 Linux 提供的网络编程接口;下层是上层的应用和实现,比如 TCP/IP 是原理,而 Linux 网络调优和工具是 TCP/IP 的具体应用。

        细节分层:基本上按照这个分层来划分:接口设计 → 设计原理 → 设计方案 → 实现源码。

          链式学习法步骤:

          (1)画出分层图

            不要期望一下就能画出完整且正确的分层图,而应该思考如何迭代改进;可以参考已有的文章整理。

          (2)明确分层深度

            根据工作相关度来判断需要学到哪一层,例如 JVM 的相关知识和源码,不同岗位要求不一样。

          (3)确定学习方法

            在上层投入更多时间,更关注细节和熟练使用,在下层投入相对少的时间,更加关注原理和应用。

      2、比较学习法:

        比较学习法:横向比较同一个领域中类似的技术,梳理它们的异同,分析它们各自的优缺点和适用场景。

        应用场景:晋升或者面试的时候“为什么”问题,例如:为什么选择 Redis,为什么不用 Memecached?为什么选择 MySQL 而不是 Redis?选择 Flink 的理由是什么?

        比较学习法步骤

          (1)链式学习法

            两个类似的技术,领域分层图和细节分层图会很类似,大部分可以复用。

          (2)明确对比维度

            用表格或者思维导图明确列出对比维度

          (3)思考 Why

            技术本质、技术原理、优缺点是核心点。

        比较学习法样例:

            

             

         比较学习法的优点:

          学的块:先重点学一个,后面主要关注差异点,相当于重用

          学的全:整理对比维度有利于系统理解

          学的深:对比会大大加深对技术深度的理解

      3、环式学习法

        环式学习法:按照技术或者业务的维度,构建一个完整的闭环过程,将多个领域的“鱼”一网打尽。

        应用场景:明确提升技术广度的范围,避免广撒网捞不到鱼的陷阱。学习业务,拓展业务领域。

        具体技巧:功能环:代表某个功能的处理过程,用于提升技术广度。业务环:代表某个业务的实现逻辑,用于提升业务能力。

        环式学习法案例:

          功能环:一个业务功能经过哪些技术处理环节。 业务环:业务的实现逻辑。

            

         环式学习法步骤:

          (1)画出具体的环:按照流程、过程、处理逻辑等来画图。

          (2)由近及远:从离自己最近的模块或者系统开始,由近及远拓宽技术广度。

          (3)学习核心内容:技术学习:架构和基本原理,避免陷入细节甚至源码;业务学习:主要职责和处理步骤。

        环式学习法案例 - 如何提升全局业务能力

             

       4、不同级别如何应用不同学习方法

            

    四、如何学习和应用开源系统

      开源系统学习误区:

        只有开发这些开源项目的人才能真正理解,我没法参与这个项目开发,因此我很难深入理解。

        我的项目现在没有用 Redis,不用的话很难深入理解,先不学了吧。

        因为数据结构和算法很重要,所以我只要研究其数据结构和算法就够了,例如 Nginx 用的是红黑树。

        “Talk is cheap, show me the code”,一头扎进源码逐行阅读。

       正确的做法:

        学以致用:业务和团队“可能”有用的。避免追逐热点,避免广撒网;自己团队可能用到的;你的上级管理范围内的团队已经用到的。

        循序渐进:迭代学习,循序渐进,不要期望一次就学精;隔一段时间再学记忆会更深

        事半功倍:掌握高效的学习方法。应用“链式学习法”、“比较学习法”、“Play 学习法”、“Teach 学习法” 等高效的方法。

      开源系统学习步骤:

            

        1、概要学习:

          目的:初步掌握基本信息、技术本质、应用场景。

          方法:看文档、看文章。

          技巧:官方文档的 Introduction 和 Get started。

        2、安装运行:

          目的:熟悉基本使用,包括安装配置、架构模式。

          方法:对照官方文档搭建简单的环境。

          技巧:研究命令行和配置项。

        3、模拟场景:

          目的:通过模拟案例掌握如何应用。

          方法:模拟不同的业务场景,设计对应的方案,能写Demo的就写Demo尝试。

          技巧:结合自己的业务;微信、微博、秒杀、红包等。

          案例:如何在不同的场景应用 Redis?Redis 缓存自己的业务数据,应该怎么做?使用 Redis 存储粉丝列表如何做?微博如何使用 Redis 缓存微博?

        4、深入研究:

          目的:从技术深度和技术宽度两个维度来全方位的学习。

          方法:看文档、看源码、看文章等。

          技巧:链式学习法;比较学习法。

          案例:以Redis为例

            

          源码怎么看:

            跨语言的看不懂就别看:不懂对应的语言的别去看源码。

            带着目的去看:先按照链式学习法学习相关的原理和方案,再去看源码是如何实现原理或者方案的。

            看核心实现:不要逐行去看,看关键实现;先看网上已有的文章

            案例:Redis 的 RDB 复制方式实现原理:“快照” → fork → Copy on write;Nginx 多进程 accept 避免惊群,用互斥锁,但是进程间怎么用锁呢?实际上是用“共享内存 + 原子变量”来实现。

        5、分享知识

          目的:通过分享帮助自己体系化和加深理解,增强记忆。

          方法:写文章、培训、演讲。

          技巧:梳理补充、提炼总结官方文档;对比类似系统。

          案例:总结 Redis Replication、Sentinel、Cluster 的优缺点和关联关系。对比 Redis 和 Memcached。

       开源系统落地技巧:

        选 - 如何选择合适的开源系统:

          适应性:聚焦是否满足业务。按照“合适原则”和“简单原则”挑选,基于业务量级和团队水平进行选择。

          成熟度:聚焦是否成熟。从“版本号”、“哪些公司在用”、“社区活跃度”等维度判断是否成熟。

          可运维:聚焦运维能力。开源项目日志是否齐全;是否有命令行、管理控制台等维护工具;是否有故障检测和恢复的能力,例如告警、切换等。

         用 - 如何使用开源系统:

          深入研究,仔细测试:研究合理的配置项,避免默认配置踩坑;性能测试:计算机器数量;压力测试:应急处理。案例:Elasticsearch 默认配置导致经常挂掉。

          小心应用,灰度发布:小心驶得万年船,先用非核心业务试点再推广。案例:Tokyo Tyrant 的教训。

          做好应急,以防万一:存储系统做好应急,例如双写。案例:MongoDB 丢数据。Tokyo Tyrant 数据损坏。

        改 - 如何基于开源项目做二次开发:

          保持纯洁,加以包装:不要改动原系统,而是要开发辅助系统:监控、报警、负载均衡、管理等。案例:Twitter 的 Twemproxy 就是这样做的,而 Redis 到了 3.0 版本后本身提供了集群功能,原有的方案简单切换到Redis 3.0 即可。

          发明你要的轮子:没有完全适合你的轮子,等开源系统又太慢了。案例:投入2~4个人花了大约2个月时间基于LevelDB 的原理,自己做了一套缓存框架支持存储、备份、集群的功能,后来又在这个框架的基础上增加了跨机房同步的功能。

    五、架构师面试与晋升技巧

       1、如何考察架构能力:

        (1)面试与面评的三项能力:

          判断能力:是否能够准确的分析业务需求中隐含的复杂度问题。

          拆解能力:是否有足够的技术深度或者技术宽度,能否设计合适的架构来解决复杂度问题。

          取舍能力:是否能够挑选合适的落地方案,决策和取舍是否有逻辑,逻辑是否正确。

            

        (2)如何展现架构方案 - 架构设计复杂度

          业务复杂度:业务固有的复杂度,主要体现为难以理解、难以扩展,例如业务数量多(微信)、业务流程长(支付宝)、业务之间关系复杂(例如ERP)。

          质量复杂度:高性能、高可用、成本、安全等质量属性的要求。业务复杂度和质量复杂度是正交的

            

       2、架构面评技巧有哪些

        (1)STAR 方法:

          Situation:概括性的总结业务背景和挑战。

          Task:介绍你负责的任务以及需要达成的目标。

          Action:项目中你采取的关键行动,例如用了微服务拆分,引入了Flink、规则引擎,设计了整体异地多活方案等等。

          Result:最终的架构方案,以及落地后的实际结果,一般三个维度以上,尽量用量化结果描述,例如日活、转化率、留存率等。

         (2)STAR 如何写/讲架构

            

           STAR 案例 - 阿里游戏异地多活架构

            Situation:XX 业务1个月4次故障,持续时间n分钟,造成***万的损失,严重影响平台口碑。

            Task:攻坚项目负责人;总架构师。

            Action:成立研发、测试、运维、项目的攻坚团队;架构演进:第一个实现异地多活架构。

            Result:3分钟发现问题,5分钟恢复;可复用的运维平台;可复制的异地多活的方法论。

            

             异地多活设计方法论

              业务分级:TOP1:登录;TOP2:支付。

              数据分类:登录关键数据:session、角色 ID、账号密码;支付关键数据:支付本身依赖支付宝、微信,支付后的点券元宝等是游戏管理的。 

              数据同步:session:不同步,重复生成;角色 ID:全局唯一,消息队列同步 + 算法重复生成;账号密码 & 支付:第三方管理,无需处理。 

              异常处理:人工修复;礼包、代金券补偿。

        (3)如何回答面评/面试问题

          What:关注“结果”,回答“事情 + 结果”。 微服务拆分后研发效率有多大提升?带来了什么挑战么?你们的 Docker 容器一共有多少,大概的负载如何?

          How:关注“过程”,回答“方法 + 步骤”。你们是如何拆分某某服务的?微服务拆分的时候数据库怎么处理?

          Why:关注“原因”,回答“原理 + 思考”。为什么选择 Redis,而没有选择Memcached?Redis 相比 Memcached 有什么优势,有什么缺点?

          典型疑问:

            疑问1:有人建议在答辩环节,为了防止问到自己不会的问题,在自己准备的问题上尽量多说,从而让面试官少问问题,这种方法可取吗?

              答:不可取,面试官和评委不会因为你一个问题答得多就给你通过,评委会综合考察相关能力。事实上,我们评委经常会阻止晋升的人长篇大论,啰里啰嗦地讲,评委需要听到关键的技术点和分析。

            疑问2:评委的问题我不太会,但是我掌握的一些技术可能与这个问题有关,应该尝试回答一下么?

              答:不可,不要蒙,直接说不会,然后引导评委转向自己会的内容。例如:评委问了 Redis 的多路复用自己不会,可以说 Redis 的数据结构自己比较熟。

        (4)面评技巧 - 如何言简意赅介绍 Situation

          产业链图:用于向非本业务领域的评委介绍自己的业务,一般用于晋升 P8/P9。

          业务/系统大图:用于向本业务领域的评委介绍自己的业务,一般用于晋升 P7/P8。

            

        (5)面评技巧 – Result 好或者不好怎么办?

          问题:某个项目的技术难度很高,但是最终的结果不好,可不可以讲呢?

          策略:1. 不可控的因素,比如业务调整、市场变化、国家法律政策变化等,那么是可以讲的。讲的时候注意实事求是,不要掩饰也不要回避,分析结果不好的原因,说出自己的思考和总结。2. 你自己导致的,比如过度设计、错误选型以及采取了虽然先进但是你还掌握不了的技术等,这类项目就不能讲。事实上,如果真的出现这种情况,你是没有资格申请晋升的。

          问题:某个项目的技术难度不高,但最终结果特别好,可不可以讲呢?

          策略:不讲,面试和晋升是为了证明能力,不是为了证明绩效。

        (6)面试技巧 - 工作中没有架构经验怎么办

          面试 P7:按照第4节课的方法,深入研究1~3个流行的开源系统,例如:Redis、Kafka、MongoDB。

          面试 P8:基本不可能通过!

     六、如何提升业务理解能力

      1、理解业务有什么用

        为什么技术人员要了解业务:

          术业有专攻,分工合作才是团队的本质,让产品人员和运营人员讲清楚就可以了呀,那为何技术人员要理解业务?理想与现实总是有差距的。

          如果说多懂一些更好,为何不要求产品和运营来学技术?技术的门槛要远高于业务的门槛。

          我现在还不是架构师,等我成为架构师了再去提升就可以了吧?不单是架构师要理解业务,所有技术人员都要理解业务,区别只是业务的理解层级和程度不同。

        理解业务的好处:

          防止被坑:P5/P6/P7:防止错误的需求和逻辑输入,导致后面无论做的多好都拿不到好的结果。

          识别复杂度:P7/P8/P9:识别业务的复杂度具体体现在哪些地方,需要根据业务来建模(高性能)、取舍(高可用)、预判(可扩展)等。

          技术规划:P7/P8/P9:结合业务的发展趋势来做技术规划、架构重构、架构演进等。

      2、5W1H8C1D 方法

        一个需求的诞生之路:

          客户遇到了一个问题,或者老板等认为客户/用户会遇到某个问题;客户或者老板自己想了一个解决方案,然后把解决方案作为需求提给产品人员;产品人员将客户的需求描述出来,作为项目需求。

        一个坑需求的诞生之路

            

         需求踩坑案例 - 我要一只羊

            

        如何准确理解需求 - 5W1H8C1D:

          5W:对应场景,Who/Where/When/Why/What。Who:需求涉及的利益干系人;Where:需求发生的地点;When:需求发生的时间;Why:需求要解决的问题;What:需求的输出是什么。

          1H:对应逻辑,How。需求的处理逻辑,注意这里的 How 不是设计方案。

          8C:对应约束和限制,性能/成本/合规/兼容……。Constraints:1. 性能; 2. 成本;3. 时间;4. 技术;5. 可靠性; 6. 安全性; 7. 合规性; 8. 兼容性。

          1D:对应结果,Data

        作用:1. 按照 5W 去分析,能够有效避免需求本身是错误的情况;2. 5W1H8C 是重要的设计输入信息,会影响设计。

        适用范围:1. P5/P6/P7 技术人员开发的时候理解业务需求;2. 架构设计的时候理解核心需求。

        案例:地铁扫码过闸

          Who:谁用扫码过闸? -> 用户行为建模

          Where:地铁站内有什么特点? -> 系统设计约束

          When:什么时间用到扫码过闸? -> 系统峰值需求估算

          Why:为什么要扫码过闸? -> 扫码过闸的优缺点

          What:需要输出什么? -> 用户期望的效果

          8C:环境要求?性能要求?大陆地铁相关要求和香港的一样么? -> 系统设计约束

      3、AAARR模型

        AARRR 模型 - 端到端 ToC 业务

          AARRR 漏斗模型是 PayPal“黑帮”成员之一、美国企业家、天使投资人戴夫·麦克卢尔(Dave McClure)提出的,适合用来做互联网 ToC 业务的分析。增长黑客之父肖恩·埃利斯(Sean Ellis)在2010年提出“增长黑客”这个概念的时候,就把 AARRR漏斗模型作为核心模型,他在《增长黑客》这本书中基于这个模型总结了很多成熟的落地技巧。

            

         AA:获取 + 激活

          获取 Acquisition:

            核心:1. 触达用户:让用户知道产品,触达路径就是“渠道”,比如广告、社交推广、老用户推荐、主播推荐等手段。2. 吸引用户:让用户进入产品,比如设计有创意的海报、红包现金奖励和送礼品等。

          激活 Activation:

            核心:把获取的用户转化为产品的真实用户。例如,用户下载购物 App 后,可以通过送红包、满10减9、送10张现金券这种方式,引导用户完成一次购物。

        RRR:留存 + 收入 + 推荐

          留存 Retention:

            核心:把激活的用户转换为产品的长期用户,不同用户的核心诉求不同。电商业务为例:拼多多,淘宝,京东,各自用户留存的关键是什么?

          收益 Revenue:

            核心:将留存的用户转换为收益。例如:用户直接购买产品、购买VIP服务、广告商按照用户点击付费、平台收取交易佣金等。

          推荐 Referral

            核心:通过“以老带新”的方式来实现用户增长。例如:拼多多的拼单,提现。

        如何应用 AARRR 理解 ToC 业务:

          业务手段:常见的业务手段以及优缺点获取渠道:统计分析平台;跟产品运营等交流。

          漏斗数据:核心业务(TOP5)的漏斗数据获取渠道:统计分析平台;内部业务总结规划会议。对比竞争对手的漏斗

          竞品漏斗:获取渠道:公司内的行业分析;第三方的行业分析;上市公司的财报。

     
     
  • 相关阅读:
    python自动更新chromedriver与chrome兼容
    Python生成exe可执行文件
    windows下安装python 且 安装pip
    python运行的时候报错line 192, in _run_module_as_main return _run_code(code, main_globals, None 解决方案
    log4j2配置文件log4j2.xml
    log4j配置文件中的additivity属性
    Druid作连接池的数据库的主从动态切换
    Win10进入安全模式的方法
    Win10复制文件或是从网站另存图片提示“客户端没有所需的特权”怎么解决?
    druid添加log4j2
  • 原文地址:https://www.cnblogs.com/liconglong/p/16413568.html
Copyright © 2020-2023  润新知