<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Software Architecture | Mobabel</title>
	<atom:link href="http://www.mobabel.net/category/software-architecture/feed/?lang=en_uspage-12page-4page-12page-15page-3" rel="self" type="application/rss+xml" />
	<link>http://www.mobabel.net</link>
	<description>Just One Pure ITer</description>
	<lastBuildDate>Sun, 18 Aug 2024 19:03:52 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>
	<item>
		<title>[汇总]汽车软件构架</title>
		<link>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%b1%bd%e8%bd%a6%e8%bd%af%e4%bb%b6%e6%9e%84%e6%9e%b6/</link>
					<comments>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%b1%bd%e8%bd%a6%e8%bd%af%e4%bb%b6%e6%9e%84%e6%9e%b6/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Sun, 14 May 2023 22:39:43 +0000</pubDate>
				<category><![CDATA[Collection]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=8075</guid>

					<description><![CDATA[<p>从技术的角度谈谈OTA召回 蔚来汽车深度学习算法实践 Android 车载应用与传统开发之间的尔虞我诈~ 大众的焦虑,CARIAD买单? 自动驾驶“全栈自研”大溃退——车企被迫“认清现实、放弃幻想” 走向崩溃的汽车人 【难得完整的方案】IBM给某整车制造企业的IT咨询规划 &#160; 汽车软件转型的困惑与痛点 杨修文的新书《智能汽车电子与软件:开发方法、系统集成、流程体系与项目管理》 本文节选自此书的第九章《转型软件的痛点与困惑》,这不就是我们当下正在面临的痛点么?且看段落标题: 互相低不下的头颅 硬件交样与软件迭代的冲突 对敏捷自身价值的质疑 依旧太高的信息壁垒 ASPICE的爱与恨 bug怎么这么多 欲拒还迎的转型 &#160; &#160; &#160;</p>
The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%b1%bd%e8%bd%a6%e8%bd%af%e4%bb%b6%e6%9e%84%e6%9e%b6/">[汇总]汽车软件构架</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/B98RRNMoq5IVSXyoNuneiA">从技术的角度谈谈OTA召回</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/gC5zPO2kspmqrtu-TkDeSg">蔚来汽车深度学习算法实践</a></p>
<p><a href="https://mp.weixin.qq.com/s/JR4W0-B0GxQJWTFM6WrKRg">Android 车载应用与传统开发之间的尔虞我诈~</a></p>
<p><span id="more-8075"></span></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/EivwPXw32jWwgljL0JMyUw">大众的焦虑,CARIAD买单?</a></p>
<p><a href="https://www.toutiao.com/article/7255493265066148388/?app=news_article&amp;timestamp=1689485355&amp;use_new_style=1&amp;req_id=2023071613291413AA77E13EFB2D50E5C9&amp;group_id=7255493265066148388&amp;share_token=E7067D7B-DA1A-480B-872E-CFC58858368D&amp;tt_from=weixin&amp;utm_source=weixin&amp;utm_medium=toutiao_ios&amp;utm_campaign=client_share&amp;wxshare_count=2&amp;source=m_redirect&amp;wid=1689687137086">自动驾驶“全栈自研”大溃退——车企被迫“认清现实、放弃幻想”</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/C43D5f4h4DjThpTNQ3rGqg">走向崩溃的汽车人</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/Fuy9NnckPNAaRmBo53epLA">【难得完整的方案】IBM给某整车制造企业的IT咨询规划</a></p>
<p>&nbsp;</p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/w8xKULBRR5JBq-Wq78DOqg">汽车软件转型的困惑与痛点</a></p>
<p><em>杨修文的新书<strong>《智能汽车电子与软件:开发方法、系统集成、流程体系与项目管理》</strong></em></p>
<p><em>本文节选自此书的第九章《转型软件的痛点与困惑》,这不就是我们当下正在面临的痛点么?</em><em>且看段落标题:</em></p>
<ul>
<li>互相低不下的头颅</li>
<li>硬件交样与软件迭代的冲突</li>
<li><strong>对敏捷自身价值的质疑</strong></li>
<li>依旧太高的信息壁垒</li>
<li>ASPICE的爱与恨</li>
<li>bug怎么这么多</li>
<li>欲拒还迎的转型</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%b1%bd%e8%bd%a6%e8%bd%af%e4%bb%b6%e6%9e%84%e6%9e%b6/">[汇总]汽车软件构架</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%b1%bd%e8%bd%a6%e8%bd%af%e4%bb%b6%e6%9e%84%e6%9e%b6/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[转]作为技术负责人,如何从0搭建公司后端技术栈</title>
		<link>http://www.mobabel.net/%e8%bd%ac%e4%bd%9c%e4%b8%ba%e6%8a%80%e6%9c%af%e8%b4%9f%e8%b4%a3%e4%ba%ba%ef%bc%8c%e5%a6%82%e4%bd%95%e4%bb%8e0%e6%90%ad%e5%bb%ba%e5%85%ac%e5%8f%b8%e5%90%8e%e7%ab%af%e6%8a%80%e6%9c%af%e6%a0%88/</link>
					<comments>http://www.mobabel.net/%e8%bd%ac%e4%bd%9c%e4%b8%ba%e6%8a%80%e6%9c%af%e8%b4%9f%e8%b4%a3%e4%ba%ba%ef%bc%8c%e5%a6%82%e4%bd%95%e4%bb%8e0%e6%90%ad%e5%bb%ba%e5%85%ac%e5%8f%b8%e5%90%8e%e7%ab%af%e6%8a%80%e6%9c%af%e6%a0%88/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Sun, 05 Jun 2022 22:42:38 +0000</pubDate>
				<category><![CDATA[Collection]]></category>
		<category><![CDATA[Software Architecture]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=7423</guid>

					<description><![CDATA[<p>如何您是一名创业公司的负责人,如何从0搭建公司的后端技术栈。今天要说的后台是大后台的概念,放在服务器上的东西都属于后台的东西,比如使用的框架,语言,数据库,服务,操作系统等等。 整个后台技术栈我的理解包括 4 个层面的内容: 语言:用了哪些开发语言,如:C++/Java/Go/PHP/Python/Ruby 等等; 组件:用了哪些组件,如:MQ 组件,数据库组件等等; 流程:怎样的流程和规范,如:开发流程,项目流程,发布流程,监控告警流程,代码规范等等; 系统:系统化建设,上面的流程需要有系统来保证,如:规范发布流程的发布系统,代码管理系统等等; 结合以上的的 4 个层面的内容,整个后台技术栈的结构如图 2 所示: 图2 后台技术栈结构 以上的这些内容都需要我们从零开始搭建,在创业公司,没有大公司那些完善的基础设施,需要我们从开源界,从云服务商甚至有些需要自己去组合,去拼装,去开发一个适合自己的组件或系统以达成我们的目标。咱们一个个系统和组件的做选型,最终形成我们的后台技术栈。 1. 各系统组件选型 1-1. 1、项目管理/Bug管理/问题管理 项目管理软件是整个业务的需求,问题,流程等等的集中地,大家的跨部门沟通协同大多依赖于项目管理工具。有一些 SaaS 的项目管理服务可以使用,但是很多时间不满足需求,此时我们可以选择一些开源的项目,这些项目本身有一定的定制能力,有丰富的插件可以使用,一般的创业公司需求基本上都能得到满足,常用的项目如下: Redmine:用 Ruby 开发的,有较多的插件可以使用,能自定义字段,集成了项目管理,Bug 问题跟踪,WIKI 等功能,不过好多插件 N 年没有更新了; Phabricator:用 PHP&#46;&#46;&#46;</p>
The post <a href="http://www.mobabel.net/%e8%bd%ac%e4%bd%9c%e4%b8%ba%e6%8a%80%e6%9c%af%e8%b4%9f%e8%b4%a3%e4%ba%ba%ef%bc%8c%e5%a6%82%e4%bd%95%e4%bb%8e0%e6%90%ad%e5%bb%ba%e5%85%ac%e5%8f%b8%e5%90%8e%e7%ab%af%e6%8a%80%e6%9c%af%e6%a0%88/">[转]作为技术负责人,如何从0搭建公司后端技术栈</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<section data-mpa-powered-by="yiban.io">如何您是一名创业公司的负责人,如何从0搭建公司的后端技术栈。今天要说的后台是大后台的概念,放在服务器上的东西都属于后台的东西,比如使用的框架,语言,数据库,服务,操作系统等等。</section>
<p data-tool="mdnice编辑器">整个后台技术栈我的理解包括 4 个层面的内容:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>语言:用了哪些开发语言,如:C++/Java/Go/PHP/Python/Ruby 等等;</section>
</li>
<li>
<section>组件:用了哪些组件,如:MQ 组件,数据库组件等等;</section>
</li>
<li>
<section>流程:怎样的流程和规范,如:开发流程,项目流程,发布流程,监控告警流程,代码规范等等;</section>
</li>
<li>
<section>系统:系统化建设,上面的流程需要有系统来保证,如:规范发布流程的发布系统,代码管理系统等等;</section>
</li>
</ul>
<p><span id="more-7423"></span></p>
<p data-tool="mdnice编辑器">结合以上的的 4 个层面的内容,整个后台技术栈的结构如图 2 所示:</p>
<figure data-tool="mdnice编辑器"><a href="http://www.mobabel.net/wp-content/uploads/2022/06/05/2.jpg"><img fetchpriority="high" decoding="async" class="alignnone size-full wp-image-7424" src="http://www.mobabel.net/wp-content/uploads/2022/06/05/2.jpg" alt="" width="918" height="504" srcset="http://www.mobabel.net/wp-content/uploads/2022/06/05/2.jpg 918w, http://www.mobabel.net/wp-content/uploads/2022/06/05/2-300x165.jpg 300w, http://www.mobabel.net/wp-content/uploads/2022/06/05/2-768x422.jpg 768w" sizes="(max-width: 918px) 100vw, 918px" /></a><figcaption>图2 后台技术栈结构</figcaption></figure>
<p data-tool="mdnice编辑器">以上的这些内容都需要我们从零开始搭建,在创业公司,没有大公司那些完善的基础设施,需要我们从开源界,从云服务商甚至有些需要自己去组合,去拼装,去开发一个适合自己的组件或系统以达成我们的目标。咱们一个个系统和组件的做选型,最终形成我们的后台技术栈。</p>
<h2 id='1-各系统组件选型'  id="boomdevs_1" data-tool="mdnice编辑器" >1. 各系统组件选型</h2>
<h3 id='1-1-1-项目管理-bug管理-问题管理'  id="boomdevs_2" data-tool="mdnice编辑器" >1-1. 1、项目管理/Bug管理/问题管理</h3>
<p data-tool="mdnice编辑器">项目管理软件是整个业务的需求,问题,流程等等的集中地,大家的跨部门沟通协同大多依赖于项目管理工具。有一些 SaaS 的项目管理服务可以使用,但是很多时间不满足需求,此时我们可以选择一些开源的项目,这些项目本身有一定的定制能力,有丰富的插件可以使用,一般的创业公司需求基本上都能得到满足,常用的项目如下:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>Redmine:用 Ruby 开发的,有较多的插件可以使用,能自定义字段,集成了项目管理,Bug 问题跟踪,WIKI 等功能,不过好多插件 N 年没有更新了;</section>
</li>
<li>
<section>Phabricator:用 PHP 开发的,Facebook 之前的内部工具,开发这工具的哥们离职后自己搞了一个公司专门做这个软件,集成了代码托管, Code Review,任务管理,文档管理,问题跟踪等功能,强烈推荐较敏捷的团队使用;</section>
</li>
<li>
<section>Jira:用 Java 开发的,有用户故事,task 拆分,燃尽图等等,可以做项目管理,也可以应用于跨部门沟通场景,较强大;</section>
</li>
<li>
<section>悟空 CRM :这个不是项目管理,这个是客户管理,之所以在这里提出来,是因为在 To B 的创业公司里面,往往是以客户为核心来做事情的,可以将项目管理和问题跟进的在悟空 CRM 上面来做,他的开源版本已经基本实现了 CR&lt; 的核心 功能,还带有一个任务管理功能,用于问题跟进,不过用这个的话,还是需要另一个项目管理的软件协助,顺便说一嘴,这个系统的代码写得很难维护,只能适用于客户规模小(1万以内)时。</section>
</li>
</ul>
<h3 id='1-2-2-dns'  id="boomdevs_3" data-tool="mdnice编辑器" >1-2. 2、DNS</h3>
<p data-tool="mdnice编辑器">DNS 是一个很通用的服务,创业公司基本上选择一个合适的云厂商就行了,国内主要是两家:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>阿里万网:阿里 2014 年收购了万网,整合了其域名服务,最终形成了现在的阿里万网,其中就包含 DNS 这块的服务;</section>
</li>
<li>
<section>腾讯 DNSPod:腾讯 2012 年以 4000 万收购 DNSPod 100% 股份,主要提供域名解析和一些防护功能;</section>
</li>
</ul>
<p data-tool="mdnice编辑器">如果你的业务是在国内,主要就是这两家,选 一个就好,像今日头条这样的企业用的也是 DNSPod 的服务,除非一些特殊的原因才需要自建,比如一些 CDN 厂商,或者对区域有特殊限制的。要实惠一点用阿里最便宜的基础版就好了,要成功率高一些,还是用 DNSPod 的贵的那种。</p>
<p data-tool="mdnice编辑器">在国外还是选择亚马逊吧,阿里的 DNS 服务只有在日本和美国有节点,东南亚最近才开始部点, DNSPod 也只有美国和日本,像一些出海的企业,其选择的云服务基本都是亚马逊。</p>
<p data-tool="mdnice编辑器">如果是线上产品,DNS 强烈建议用付费版,阿里的那几十块钱的付费版基本可以满足需求。如果还需要一些按省份或按区域调试的逻辑,则需要加钱,一年也就几百块,省钱省力。</p>
<p data-tool="mdnice编辑器">如果是国外,优先选择亚马逊,如果需要国内外互通并且有自己的 APP 的话,建议还是自己实现一些容灾逻辑或者智能调度,因为没有一个现成的 DNS 服务能同时较好的满足国内外场景,或者用多个域名,不同的域名走不同的 DNS 。</p>
<h3 id='1-3-3-lb-负载均衡'  id="boomdevs_4" data-tool="mdnice编辑器" >1-3. 3、LB(负载均衡)</h3>
<p data-tool="mdnice编辑器">LB(负载均衡)是一个通用服务,一般云厂商的 LB 服务基本都会如下功能:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>支持四层协议请求(包括 TCP、UDP 协议);</section>
</li>
<li>
<section>支持七层协议请求(包括 HTTP、HTTPS 协议);</section>
</li>
<li>
<section>集中化的证书管理系统支持 HTTPS 协议;</section>
</li>
<li>
<section>健康检查;</section>
</li>
</ul>
<p data-tool="mdnice编辑器">如果你线上的服务机器都是用的云服务,并且是在同一个云服务商的话,可以直接使用云服务商提供的 LB 服务,如阿里云的 SLB,腾讯云的 CLB,亚马逊的 ELB 等等。如果是自建机房基本都是 LVS + Nginx。</p>
<h3 id='1-4-4-cdn'  id="boomdevs_5" data-tool="mdnice编辑器" >1-4. 4、CDN</h3>
<p data-tool="mdnice编辑器">CDN 现在已经是一个很红很红的市场,基本上只能挣一些辛苦钱,都是贴着成本在卖。国内以网宿为龙头,他们家占据整个国内市场份额的 40% 以上,后面就是腾讯,阿里。网宿有很大一部分是因为直播的兴起而崛起。</p>
<p data-tool="mdnice编辑器">国外,Amazon 和 Akamai 合起来占比大概在 50%,曾经的国际市场老大 Akamai 拥有全球超一半的份额,在 Amazon CDN入局后,份额跌去了将近 20%,众多中小企业都转向后者,Akamai 也是无能为力。</p>
<p data-tool="mdnice编辑器">国内出海的 CDN 厂商,更多的是为国内的出海企业服务,三家大一点的 CDN 服务商里面也就网宿的节点多一些,但是也多不了多少。阿里和腾讯还处于前期阶段,仅少部分国家有节点。</p>
<p data-tool="mdnice编辑器">就创业公司来说,CDN 用腾讯云或阿里云即可,其相关系统较完善,能轻松接入,网宿在系统支持层面相对较弱一些,而且还贵一些。并且,当流量上来后,CDN 不能只用一家,需要用多家,不同的 CDN 在全国的节点覆盖不一样,而且针对不同的客户云厂商内部有些区分客户集群,并不是全节点覆盖(但有些云厂商说自己是全网节点),除了节点覆盖的问题,多 CDN 也在一定程度上起到容灾的作用。</p>
<h3 id='1-5-5-rpc-框架'  id="boomdevs_6" data-tool="mdnice编辑器" >1-5. 5、RPC 框架</h3>
<p data-tool="mdnice编辑器">维基百科对 RPC 的定义是:远程过程调用(Remote Procedure Call,RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。</p>
<p data-tool="mdnice编辑器">通俗来讲,一个完整的 RPC 调用过程,就是 Server 端实现了一个函数,客户端使用 RPC 框架提供的接口,调用这个函数的实现,并获取返回值的过程。</p>
<p data-tool="mdnice编辑器">业界 RPC 框架大致分为两大流派,一种侧重跨语言调用,另一种是偏重服务治理。</p>
<p data-tool="mdnice编辑器">跨语言调用型的 RPC 框架有 Thrift、gRPC、Hessian、Hprose 等。这类 RPC 框架侧重于服务的跨语言调用,能够支持大部分的语言进行语言无关的调用,非常适合多语言调用场景。但这类框架没有服务发现相关机制,实际使用时需要代理层进行请求转发和负载均衡策略控制。</p>
<p data-tool="mdnice编辑器">其中,gRPC 是 Google 开发的高性能、通用的开源 RPC 框架,其由 Google 主要面向移动应用开发并基于 HTTP/2 协议标准而设计,基于 ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。本身它不是分布式的,所以要实现框架的功能需要进一步的开发。</p>
<p data-tool="mdnice编辑器">Hprose(High Performance Remote Object Service Engine)是一个 MIT 开源许可的新型轻量级跨语言跨平台的面向对象的高性能远程动态通讯中间件。</p>
<p data-tool="mdnice编辑器">服务治理型的 RPC 框架的特点是功能丰富,提供高性能的远程调用、服务发现及服务治理能力,适用于大型服务的服务解耦及服务治理,对于特定语言(Java)的项目可以实现透明化接入。缺点是语言耦合度较高,跨语言支持难度较大。国内常见的冶理型 RPC 框架如下:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>Dubbo:Dubbo 是阿里巴巴公司开源的一个 Java 高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring 框架无缝集成。当年在淘宝内部,Dubbo 由于跟淘宝另一个类似的框架 HSF 有竞争关系,导致 Dubbo 团队解散,最近又活过来了,有专职同学投入。</section>
</li>
<li>
<section>DubboX:DubboX 是由当当在基于 Dubbo 框架扩展的一个 RPC 框架,支持 REST 风格的远程调用、Kryo/FST 序列化,增加了一些新的feature。Motan:Motan 是新浪微博开源的一个 Java 框架。它诞生的比较晚,起于 2013 年,2016 年 5 月开源。Motan 在微博平台中已经广泛应用,每天为数百个服务完成近千亿次的调用。</section>
</li>
<li>
<section>rpcx:rpcx 是一个类似阿里巴巴 Dubbo 和微博 Motan 的分布式的 RPC 服务框架,基于 Golang net/rpc 实现。但是 rpcx 基本只有一个人在维护,没有完善的社区,使用前要慎重,之前做 Golang 的 RPC 选型时也有考虑这个,最终还是放弃了,选择了 gRPC,如果想自己自研一个 RPC 框架,可以参考学习一下。</section>
</li>
</ul>
<h3 id='1-6-6-名字发现-服务发现'  id="boomdevs_7" data-tool="mdnice编辑器" >1-6. 6、名字发现/服务发现</h3>
<p data-tool="mdnice编辑器">名字发现和服务发现分为两种模式,一个是客户端发现模式,一种是服务端发现模式。</p>
<p data-tool="mdnice编辑器">框架中常用的服务发现是客户端发现模式。</p>
<p data-tool="mdnice编辑器">所谓服务端发现模式是指客户端通过一个负载均衡器向服务发送请求,负载均衡器查询服务注册表并把请求路由到一台可用的服务实例上。现在常用的负载均衡器都是此类模式,常用于微服务中。</p>
<p data-tool="mdnice编辑器">所有的名字发现和服务发现都要依赖于一个可用性非常高的服务注册表,业界常用的服务注册表有如下三个:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>etcd,一个高可用、分布式、一致性、key-value 方式的存储,被用在分享配置和服务发现中。两个著名的项目使用了它:Kubernetes 和 Cloud Foundry。</section>
</li>
<li>
<section>Consul,一个发现和配置服务的工具,为客户端注册和发现服务提供了API,Consul还可以通过执行健康检查决定服务的可用性。</section>
</li>
<li>
<section>Apache ZooKeeper,是一个广泛使用、高性能的针对分布式应用的协调服务。Apache ZooKeeper 本来是 Hadoop 的子工程,现在已经是顶级工程了。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">除此之外也可以自己实现服务实现,或者用 Redis 也行,只是需要自己实现高可用性。</p>
<h3 id='1-7-7-关系数据库'  id="boomdevs_8" data-tool="mdnice编辑器" >1-7. 7、关系数据库</h3>
<p data-tool="mdnice编辑器">关系数据库分为两种,一种是传统关系数据,如 Oracle,MySQL,Maria,DB2,PostgreSQL 等等,另一种是 NewSQL,即至少要满足以下五点的新型关系数据库:</p>
<ol class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>完整地支持 SQL,支持 JOIN / GROUP BY /子查询等复杂 SQL 查询。</section>
</li>
<li>
<section>支持传统数据标配的 ACID 事务,支持强隔离级别。</section>
</li>
<li>
<section>具有弹性伸缩的能力,扩容缩容对于业务层完全透明。</section>
</li>
<li>
<section>真正的高可用,异地多活、故障恢复的过程不需要人为的接入,系统能够自动地容灾和进行强一致的数据恢复。</section>
</li>
<li>
<section>具备一定的大数据分析能力。</section>
</li>
</ol>
<p data-tool="mdnice编辑器">传统关系数据库用得最多的是 MySQL,成熟,稳定,一些基本的需求都能满足,在一定数据量级之前基本单机传统数据库都可以搞定,而且现在较多的开源系统都是基于 MySQL,开箱即用,再加上主从同步和前端缓存,百万 pv 的应用都可以搞定了。不过 CentOS 7 已经放弃了 MySQL,而改使用 MariaDB。MariaDB 数据库管理系统是 MySQ L的一个分支,主要由开源社区在维护,采用 GPL 授权许可。开发这个分支的原因之一是:甲骨文公司收购了 MySQL 后,有将 MySQL 闭源的潜在风险,因此社区采用分支的方式来避开这个风险。</p>
<p data-tool="mdnice编辑器">在 Google 发布了 F1: A Distributed SQL Database That Scales 和 Spanner: Google’s Globally-Distributed Databasa 之后,业界开始流行起 NewSQL。于是有了 CockroachDB,于是有了奇叔公司的 TiDB。国内已经有比较多的公司使用 TiDB,之前在创业公司时在大数据分析时已经开始应用 TiDB,当时应用的主要原因是 MySQL 要使用分库分表,逻辑开发比较复杂,扩展性不够。</p>
<h3 id='1-8-8-nosql'  id="boomdevs_9" data-tool="mdnice编辑器" >1-8. 8、NoSQL</h3>
<p data-tool="mdnice编辑器">NoSQL 顾名思义就是 Not-Only SQL,也有人说是 No – SQL,个人偏向于 Not-Only SQL,它并不是用来替代关系库,而是作为关系型数据库的补充而存在。</p>
<p data-tool="mdnice编辑器">常见 NoSQL 有4个类型:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>键值,适用于内容缓存,适合混合工作负载并发高扩展要求大的数据集,其优点是简单,查询速度快,缺点是缺少结构化数据,常见的有 Redis,Memcache,BerkeleyDB 和 Voldemort 等等;</section>
</li>
<li>
<section>列式,以列簇式存储,将同一列数据存在一起,常见于分布式的文件系统,其中以 Hbase,Cassandra 为代表。Cassandra 多用于写多读少的场景,国内用得比较多的有 360,大概 1500 台机器的集群,国外大规模使用的公司比较多,如 eBay,Instagram,Apple 和沃尔玛等等;</section>
</li>
<li>
<section>文档,数据存储方案非常适用承载大量不相关且结构差别很大的复杂信息。性能介于 kv 和关系数据库之间,它的灵感来于 lotus notes,常见的有 MongoDB,CouchDB 等等;</section>
</li>
<li>
<section>图形,图形数据库擅长处理任何涉及关系的状况。社交网络,推荐系统等。专注于构建关系图谱,需要对整个图做计算才能得出结果,不容易做分布式的集群方案,常见的有 Neo4J,InfoGrid 等。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">除了以上4种类型,还有一些特种的数据库,如对象数据库,XML 数据库,这些都有针对性对某些存储类型做了优化的数据库。</p>
<p data-tool="mdnice编辑器">在实际应用场景中,何时使用关系数据库,何时使用 NoSQL,使用哪种类型的数据库,这是我们在做架构选型时一个非常重要的考量,甚至会影响整个架构的方案。</p>
<h3 id='1-9-9-消息中间件'  id="boomdevs_10" data-tool="mdnice编辑器" >1-9. 9、消息中间件</h3>
<p data-tool="mdnice编辑器">消息中间件在后台系统中是必不可少的一个组件,一般我们会在以下场景中使用消息中间件:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>异步处理:异步处理是使用消息中间件的一个主要原因,在工作中最常见的异步场景有用户注册成功后需要发送注册成功邮件、缓存过期时先返回老的数据,然后异步更新缓存、异步写日志等等;通过异步处理,可以减少主流程的等待响应时间,让非主流程或者非重要业务通过消息中间件做集中的异步处理。</section>
</li>
<li>
<section>系统解耦:比如在电商系统中,当用户成功支付完成订单后,需要将支付结果给通知ERP系统、发票系统、WMS、推荐系统、搜索系统、风控系统等进行业务处理;这些业务处理不需要实时处理、不需要强一致,只需要最终一致性即可,因此可以通过消息中间件进行系统解耦。通过这种系统解耦还可以应对未来不明确的系统需求。</section>
</li>
<li>
<section>削峰填谷:当系统遇到大流量时,监控图上会看到一个一个的山峰样的流量图,通过使用消息中间件将大流量的请求放入队列,通过消费者程序将队列中的处理请求慢慢消化,达到消峰填谷的效果。最典型的场景是秒杀系统,在电商的秒杀系统中下单服务往往会是系统的瓶颈,因为下单需要对库存等做数据库操作,需要保证强一致性,此时使用消息中间件进行下单排队和流控,让下单服务慢慢把队列中的单处理完,保护下单服务,以达到削峰填谷的作用。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">业界消息中间件是一个非常通用的东西,大家在做选型时有使用开源的,也有自己造轮子的,甚至有直接用 MySQL 或 Redis 做队列的,关键看是否满足你的需求,如果是使用开源的项目,以下的表格在选型时可以参考:</p>
<figure data-tool="mdnice编辑器"><a href="http://www.mobabel.net/wp-content/uploads/2022/06/05/3.jpg"><img decoding="async" class="alignnone size-full wp-image-7425" src="http://www.mobabel.net/wp-content/uploads/2022/06/05/3.jpg" alt="" width="1080" height="668" srcset="http://www.mobabel.net/wp-content/uploads/2022/06/05/3.jpg 1080w, http://www.mobabel.net/wp-content/uploads/2022/06/05/3-300x186.jpg 300w, http://www.mobabel.net/wp-content/uploads/2022/06/05/3-1024x633.jpg 1024w, http://www.mobabel.net/wp-content/uploads/2022/06/05/3-768x475.jpg 768w" sizes="(max-width: 1080px) 100vw, 1080px" /></a><figcaption>图 3</figcaption></figure>
<p data-tool="mdnice编辑器">以上图的纬度为:名字、成熟度、所属社区/公司、文档、授权方式、开发语言、支持的协议、客户端支持的语言、性能、持久化、事务、集群、负载均衡、管理界面、部署方式、评价。</p>
<h3 id='1-10-10-代码管理'  id="boomdevs_11" data-tool="mdnice编辑器" >1-10. 10、代码管理</h3>
<p data-tool="mdnice编辑器">代码是互联网创业公司的命脉之一,代码管理很重要,常见的考量点包括两块:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>安全和权限管理,将代码放到内网并且对于关系公司命脉的核心代码做严格的代码控制和机器的物理隔离;</section>
</li>
<li>
<section>代码管理工具,Git 作为代码管理的不二之选,你值得拥有。GitLab 是当今最火的开源 Git 托管服务端,没有之一,虽然有企业版,但是其社区版基本能满足我们大部分需求,结合 Gerrit 做 Code review,基本就完美了。当然 GitLab 也有代码对比,但没 Gerrit 直观。Gerrit 比 GitLab 提供了更好的代码检查界面与主线管理体验,更适合在对代码质量有高要求的文化下使用。</section>
</li>
</ul>
<h3 id='1-11-11-持续集成'  id="boomdevs_12" data-tool="mdnice编辑器" >1-11. 11、持续集成</h3>
<p data-tool="mdnice编辑器">持续集成简,称 CI(continuous integration),是一种软件开发实践,即团队开发成员经常集成他们的工作,每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。持续集成为研发流程提供了代码分支管理/比对、编译、检查、发布物输出等基础工作,为测试的覆盖率版本编译、生成等提供统一支持。</p>
<p data-tool="mdnice编辑器">业界免费的持续集成工具中系统我们有如下一些选择:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>Jenkins:Java 写的有强大的插件机制,MIT 协议开源 (免费,定制化程度高,它可以在多台机器上进行分布式地构建和负载测试)。Jenkins 可以算是无所不能,基本没有 Jenkins 做不了的,无论从小型团队到大型团队 Jenkins 都可以搞定。不过如果要大规模使用,还是需要有人力来学习和维护。</section>
</li>
<li>
<section>TeamCity:TeamCity 与 Jenkins 相比使用更加友好,也是一个高度可定制化的平台。但是用的人多了,TeamCity就要收费了。</section>
</li>
<li>
<section>Strider:Strider 是一个开源的持续集成和部署平台,使用 Node.js 实现,存储使用的是 MongoDB,BSD 许可证,概念上类似 Travis 和Jenkins。</section>
</li>
<li>
<section>GitLab CI:从GitLab 8.0开始,GitLab CI 就已经集成在 GitLab,我们只要在项目中添加一个 .gitlab-ci.yml 文件,然后添加一个 Runner,即可进行持续集成。并且 GitLab 与 Docker 有着非常好的相互协作的能力。免费版与付费版本不同可以参见这里:https://about.gitlab.com/products/feature-comparison/。</section>
</li>
<li>
<section>Travis:Travis 和 GitHub 强关联;闭源代码使用 SaaS 还需考虑安全问题;不可定制;开源项目免费,其它收费。</section>
</li>
<li>
<section>Go:Go 是 ThoughtWorks 公司最新的 Cruise Control 的化身。除了 ThoughtWorks 提供的商业支持,Go 是免费的。它适用于 Windows,Mac 和各种 Linux 发行版。</section>
</li>
</ul>
<h3 id='1-12-12-日志系统'  id="boomdevs_13" data-tool="mdnice编辑器" >1-12. 12、日志系统</h3>
<p data-tool="mdnice编辑器">日志系统一般包括打日志,采集,中转,收集,存储,分析,呈现,搜索还有分发等。一些特殊的如染色,全链条跟踪或者监控都可能需要依赖于日志系统实现。日志系统的建设不仅仅是工具的建设,还有规范和组件的建设,最好一些基本的日志在框架和组件层面加就行了,比如全链接跟踪之类的。</p>
<p data-tool="mdnice编辑器">对于常规日志系统ELK能满足大部分的需求,ELK 包括如下组件:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>ElasticSearch 是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,RESTful 风格接口,多数据源,自动搜索负载等。</section>
</li>
<li>
<section>Logstash 是一个完全开源的工具,它可以对你的日志进行收集、分析,并将其存储供以后使用。</section>
</li>
<li>
<section>Kibana 是一个开源和免费的工具,它可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助汇总、分析和搜索重要数据日志。</section>
</li>
<li>
<section>Filebeat 已经完全替代了 Logstash-Forwarder 成为新一代的日志采集器,同时鉴于它轻量、安全等特点,越来越多人开始使用它。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">因为免费的 ELK 没有任何安全机制,所以这里使用了 Nginx 作反向代理,避免用户直接访问 Kibana 服务器。加上配置 Nginx 实现简单的用户认证,一定程度上提高安全性。另外,Nginx 本身具有负载均衡的作用,能够提高系统访问性能。ELK 架构如图4所示:</p>
<figure data-tool="mdnice编辑器"><a href="http://www.mobabel.net/wp-content/uploads/2022/06/05/4.jpg"><img decoding="async" class="alignnone size-full wp-image-7426" src="http://www.mobabel.net/wp-content/uploads/2022/06/05/4.jpg" alt="" width="550" height="211" srcset="http://www.mobabel.net/wp-content/uploads/2022/06/05/4.jpg 550w, http://www.mobabel.net/wp-content/uploads/2022/06/05/4-300x115.jpg 300w" sizes="(max-width: 550px) 100vw, 550px" /></a><figcaption>图 4,ELK 流程图</figcaption></figure>
<p data-tool="mdnice编辑器">对于有实时计算的需求,可以使用 Flume + Kafka + Storm + MySQL 方案,一 般架构如图 5 所示:</p>
<figure data-tool="mdnice编辑器"><a href="http://www.mobabel.net/wp-content/uploads/2022/06/05/5.jpg"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7427" src="http://www.mobabel.net/wp-content/uploads/2022/06/05/5.jpg" alt="" width="664" height="345" srcset="http://www.mobabel.net/wp-content/uploads/2022/06/05/5.jpg 664w, http://www.mobabel.net/wp-content/uploads/2022/06/05/5-300x156.jpg 300w" sizes="(max-width: 664px) 100vw, 664px" /></a><figcaption>图 5,实时分析系统架构图</figcaption></figure>
<p data-tool="mdnice编辑器">其中:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>Flume 是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的日志收集系统,支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume 提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力。</section>
</li>
<li>
<section>Kafka 是由 Apache 软件基金会开发的一个开源流处理平台,由 Scala 和 Java 编写。其本质上是一个“按照分布式事务日志架构的大规模发布/订阅消息队列”,它以可水平扩展和高吞吐率而被广泛使用。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">Kafka 追求的是高吞吐量、高负载,Flume 追求的是数据的多样性,二者结合起来简直完美。</p>
<h3 id='1-13-13-监控系统'  id="boomdevs_14" data-tool="mdnice编辑器" >1-13. 13、监控系统</h3>
<p data-tool="mdnice编辑器">监控系统只包含与后台相关的,这里主要是两块,一个是操作系统层的监控,比如机器负载,IO,网络流量,CPU,内存等操作系统指标的监控。另一个是服务质量和业务质量的监控,比如服务的可用性,成功率,失败率,容量,QPS 等等。常见业务的监控系统先有操作系统层面的监控(这部分较成熟),然后扩展出其它监控,如 Zabbix,小米的 Open-Falcon,也有一出来就是两者都支持的,如 Prometheus。如果对业务监控要求比较高一些,在创业选型中建议可以优先考虑 Prometheus。这里有一个有趣的分布,如图6所示。</p>
<figure data-tool="mdnice编辑器"><a href="http://www.mobabel.net/wp-content/uploads/2022/06/05/6.jpg"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7428" src="http://www.mobabel.net/wp-content/uploads/2022/06/05/6.jpg" alt="" width="770" height="555" srcset="http://www.mobabel.net/wp-content/uploads/2022/06/05/6.jpg 770w, http://www.mobabel.net/wp-content/uploads/2022/06/05/6-300x216.jpg 300w, http://www.mobabel.net/wp-content/uploads/2022/06/05/6-768x554.jpg 768w" sizes="(max-width: 770px) 100vw, 770px" /></a><figcaption>图 6,监控系统分布</figcaption></figure>
<p data-tool="mdnice编辑器">亚洲区域使用 Zabbix 较多,而美洲和欧洲,以及澳大利亚使用 Prometheus 居多,换句话说,英文国家地区(发达国家?)使用 Prometheus 较多。</p>
<p data-tool="mdnice编辑器">Prometheus 是由 SoundCloud 开发的开源监控报警系统和时序列数据库(TSDB)。Prometheus 使用 Go 语言开发,是 Google BorgMon 监控系统的开源版本。相对于其它监控系统使用的 push 数据的方式,Prometheus 使用的是 pull 的方式,其架构如图 7 所示:</p>
<figure data-tool="mdnice编辑器"><a href="http://www.mobabel.net/wp-content/uploads/2022/06/05/7.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7429" src="http://www.mobabel.net/wp-content/uploads/2022/06/05/7.png" alt="" width="699" height="481" srcset="http://www.mobabel.net/wp-content/uploads/2022/06/05/7.png 699w, http://www.mobabel.net/wp-content/uploads/2022/06/05/7-300x206.png 300w" sizes="(max-width: 699px) 100vw, 699px" /></a><figcaption>图 7,Prometheus 架构图</figcaption></figure>
<p data-tool="mdnice编辑器">如上图所示,Prometheus 包含的主要组件如下:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>Prometheus Server 主要负责数据采集和存储,提供 PromQL 查询语言的支持。Server 通过配置文件、文本文件、ZooKeeper、Consul、DNS SRV Lookup 等方式指定抓取目标。根据这些目标会,Server 定时去抓取 metrics 数据,每个抓取目标需要暴露一个 http 服务的接口给它定时抓取。</section>
</li>
<li>
<section>客户端 SDK:官方提供的客户端类库有 Go、Java、Scala、Python、Ruby,其他还有很多第三方开发的类库,支持 Nodejs、PHP、Erlang 等。</section>
</li>
<li>
<section>Push Gateway 支持临时性 Job 主动推送指标的中间网关。</section>
</li>
<li>
<section>Exporter Exporter 是 Prometheus 的一类数据采集组件的总称。它负责从目标处搜集数据,并将其转化为 Prometheus 支持的格式。与传统的数据采集组件不同的是,它并不向中央服务器发送数据,而是等待中央服务器主动前来抓取。Prometheus 提供多种类型的 Exporter 用于采集各种不同服务的运行状态。目前支持的有数据库、硬件、消息中间件、存储系统、HTTP 服务器、JMX 等。</section>
</li>
<li>
<section>Alertmanager:是一个单独的服务,可以支持 Prometheus 的查询语句,提供十分灵活的报警方式。</section>
</li>
<li>
<section>Prometheus HTTP API 的查询方式,自定义所需要的输出。</section>
</li>
<li>
<section>Grafana 是一套开源的分析监视平台,支持 Graphite,InfluxDB,OpenTSDB,Prometheus,Elasticsearch,CloudWatch 等数据源,其 UI 非常漂亮且高度定制化。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">创业公司选择 Prometheus + Grafana 的方案,再加上统一的服务框架(如 gRPC),可以满足大部分中小团队的监控需求。</p>
<h3 id='1-14-14-配置系统'  id="boomdevs_15" data-tool="mdnice编辑器" >1-14. 14、配置系统</h3>
<p data-tool="mdnice编辑器">随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关、降级开关,灰度开关,参数的配置、服务器的地址、数据库配置等等,除此之外,对后台程序配置的要求也越来越高:配置修改后实时生效,灰度发布,分环境、分用户,分集群管理配置,完善的权限、审核机制等等,在这样的大环境下,传统的通过配置文件、数据库等方式已经越来越无法满足开发人员对配置管理的需求,业界有如下两种方案:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>基于 zk 和 etcd,支持界面和 api ,用数据库来保存版本历史,预案,走审核流程,最后下发到 zk 或 etcd 这种有推送能力的存储里(服务注册本身也是用 zk 或 etcd,选型就一块了)。客户端都直接和 zk 或 etcd 打交道。至于灰度发布,各家不同,有一种实现是同时发布一个需要灰度的 IP 列表,客户端监听到配置节点变化时,对比一下自己是否属于该列表。PHP 这种无状态的语言和其他 zk/etcd 不支持的语言,只好自己在客户端的机器上起一个 Agent 来监听变化,再写到配置文件或共享内存,如 360 的 Qconf。</section>
</li>
<li>
<section>基于运维自动化的配置文件的推送,审核流程,配置数据管理和方案一类似,下发时生成配置文件,基于运维自动化工具如 Puppet,Ansible 推送到每个客户端,而应用则定时重新读取这个外部的配置文件,灰度发布在下发配置时指定IP列表。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">创业公司前期不需要这种复杂,直接上 zk,弄一个界面管理 zk 的内容,记录一下所有人的操作日志,程序直连 zk,或者或者用 Qconf 等基于 zk 优化后的方案。</p>
<h3 id='1-15-15-发布系统-部署系统'  id="boomdevs_16" data-tool="mdnice编辑器" >1-15. 15、发布系统/部署系统</h3>
<p data-tool="mdnice编辑器">从软件生产的层面看,代码到最终服务的典型流程如图 8 所示:</p>
<figure data-tool="mdnice编辑器"><a href="http://www.mobabel.net/wp-content/uploads/2022/06/05/8.jpg"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7430" src="http://www.mobabel.net/wp-content/uploads/2022/06/05/8.jpg" alt="" width="591" height="357" srcset="http://www.mobabel.net/wp-content/uploads/2022/06/05/8.jpg 591w, http://www.mobabel.net/wp-content/uploads/2022/06/05/8-300x181.jpg 300w" sizes="(max-width: 591px) 100vw, 591px" /></a><figcaption>图 8,流程图</figcaption></figure>
<p data-tool="mdnice编辑器">从上图中可以看出,从开发人员写下代码到服务最终用户是一个漫长过程,整体可以分成三个阶段:</p>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>从代码(Code)到成品库(Artifact)这个阶段主要对开发人员的代码做持续构建并把构建产生的制品集中管理,是为部署系统准备输入内容的阶段。</section>
</li>
<li>
<section>从制品到可运行服务 这个阶段主要完成制品部署到指定环境,是部署系统的最基本工作内容。</section>
</li>
<li>
<section>从开发环境到最终生产环境 这个阶段主要完成一次变更在不同环境的迁移,是部署系统上线最终服务的核心能力。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">发布系统集成了制品管理,发布流程,权限控制,线上环境版本变更,灰度发布,线上服务回滚等几方面的内容,是开发人员工作结晶最终呈现的重要通道。开源的项目中没有完全满足的项目,如果只是 Web 类项目,Walle、Piplin 都是可用的,但是功能不太满足,创业初期可以集成 Jenkins + Gitlab + Walle(可以考虑两天时间完善一下),以上方案基本包括制品管理,发布流程,权限控制,线上环境版本变更,灰度发布(需要自己实现),线上服务回滚等功能。</p>
<h3 id='1-16-16-跳板机'  id="boomdevs_17" data-tool="mdnice编辑器" >1-16. 16、跳板机</h3>
<p data-tool="mdnice编辑器">跳板机面对的是需求是要有一种能满足角色管理与授权审批、信息资源访问控制、操作记录和审计、系统变更和维护控制要求,并生成一些统计报表配合管理规范来不断提升IT内控的合规性,能对运维人员操作行为的进行控制和审计,对误操作、违规操作导致的操作事故,快速定位原因和责任人。其功能模块一般包括:帐户管理、认证管理、授权管理、审计管理等等。</p>
<p data-tool="mdnice编辑器">开源项目中,Jumpserver 能够实现跳板机常见需求,如授权、用户管理、服务器基本信息记录等,同时又可批量执行脚本等功能;其中录像回放、命令搜索、实时监控等特点,又能帮助运维人员回溯操作历史,方便查找操作痕迹,便于管理其他人员对服务器的操作控制。</p>
<h3 id='1-17-17-机器管理'  id="boomdevs_18" data-tool="mdnice编辑器" >1-17. 17、机器管理</h3>
<p data-tool="mdnice编辑器">机器管理的工具选择的考量可以包含以下三个方面:</p>
<ol class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>是否简单,是否需要每台机器部署 Agent(客户端)</section>
</li>
<li>
<section>语言的选择(Puppet/Chef vs Ansible/SaltStack )开源技术,不看官网不足以熟练,不懂源码不足以精通;Puppet、Chef 基于 Ruby 开发,Ansible、SaltStack 基于 Python 开发的</section>
</li>
<li>
<section>速度的选择(Ansible vs SaltStack)Ansible 基于 SSH 协议传输数据,SaltStack 使用消息队列 zeroMQ 传输数据;大规模并发的能力对于几十台-200 台规模的兄弟来讲,Ansible的性能也可接受,如果一次操作上千台,用 salt 好一些。</section>
</li>
</ol>
<p data-tool="mdnice编辑器">如图9所示:</p>
<figure data-tool="mdnice编辑器"><a href="http://www.mobabel.net/wp-content/uploads/2022/06/05/9.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7431" src="http://www.mobabel.net/wp-content/uploads/2022/06/05/9.png" alt="" width="565" height="191" srcset="http://www.mobabel.net/wp-content/uploads/2022/06/05/9.png 565w, http://www.mobabel.net/wp-content/uploads/2022/06/05/9-300x101.png 300w" sizes="(max-width: 565px) 100vw, 565px" /></a><figcaption>图 9,机器管理软件对比</figcaption></figure>
<p data-tool="mdnice编辑器">一般创业公司选择 Ansible 能解决大部问题,其简单,不需要安装额外的客户端,可以从命令行来运行,不需要使用配置文件。至于比较复杂的任务,Ansible 配置通过名为 Playbook 的配置文件中的 YAML 语法来加以处理。Playbook 还可以使用模板来扩展其功能。</p>
<h2 id='2-创业公司的选择'  id="boomdevs_19" data-tool="mdnice编辑器" >2. 创业公司的选择</h2>
<h3 id='2-1-1-选择合适的语言'  id="boomdevs_20" data-tool="mdnice编辑器" >2-1. 1、选择合适的语言</h3>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>选择团队熟悉的/能掌控的,创业公司人少事多,无太多冗余让研发团队熟悉新的语言,能快速上手,能快速出活,出了问题能快速解决的问题的语言才是好的选择。</section>
</li>
<li>
<section>选择更现代一些的,这里的现代是指语言本身已经完成一些之前需要特殊处理的特性,比如内存管理,线程等等。</section>
</li>
<li>
<section>选择开源轮子多的或者社区活跃度高的,这个原则是为了保证在开发过程中减少投入,有稳定可靠的轮子可以使用,遇到问题可以在网上快速搜索到答案。</section>
</li>
<li>
<section>选择好招人的 一门合适的语言会让创业团队减少招聘的成本,快速招到合适的人。</section>
</li>
<li>
<section>选择能让人有兴趣的 与上面一点相关,让人感兴趣,在后面留人时有用。</section>
</li>
</ul>
<h3 id='2-2-2-选择合适的组件和云服务商'  id="boomdevs_21" data-tool="mdnice编辑器" >2-2. 2、选择合适的组件和云服务商</h3>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>选择靠谱的云服务商;</section>
</li>
<li>
<section>选择云服务商的组件;</section>
</li>
<li>
<section>选择成熟的开源组件,而不是最新出的组件;</section>
</li>
<li>
<section>选择采用在一线互联网公司落地并且开源的,且在社区内形成良好口碑的产品;</section>
</li>
<li>
<section>开源社区活跃度;</section>
</li>
</ul>
<p data-tool="mdnice编辑器">选择靠谱的云服务商,其实这是一个伪命题,因为哪个服务商都不靠谱,他们所承诺的那些可用性问题基本上都会在你的身上发生,这里我们还是需要自己做一些工作,比如多服务商备份,如用 CDN,你一定不要只选一家,至少选两家,一个是灾备,保持后台切换的能力,另一个是多点覆盖,不同的服务商在 CDN 节点上的资源是不一样的。</p>
<p data-tool="mdnice编辑器">选择了云服务商以后,就会有很多的产品你可以选择了,比较存储,队列这些都会有现成的产品,这个时候就纠结了,是用呢?还是自己在云主机上搭呢?在这里我的建议是前期先用云服务商的,大了后再自己搞,这样会少掉很多运维的事情,但是这里要多了解一下云服务商的组件特性以及一些坑,比如他们内网会经常断开,他们升级也会闪断,所以在业务侧要做好容错和规避。</p>
<p data-tool="mdnice编辑器">关于开源组件,尽可能选择成熟的,成熟的组件经历了时间的考验,基本不会出大的问题,并且有成套的配套工具,出了问题在网上也可以很快的找到答案,你所遇到的坑基本上都有人踩过了。</p>
<h3 id='2-3-3-制定流程和规范'  id="boomdevs_22" data-tool="mdnice编辑器" >2-3. 3、制定流程和规范</h3>
<ul class="list-paddingleft-2" data-tool="mdnice编辑器">
<li>
<section>制定开发的规范,代码及代码分支管理规范,关键性代码仅少数人有权限;</section>
</li>
<li>
<section>制定发布流程规范,从发布系统落地;</section>
</li>
<li>
<section>制定运维规范;</section>
</li>
<li>
<section>制定数据库操作规范,收拢数据库操作权限;</section>
</li>
<li>
<section>制定告警处理流程,做到告警有人看有人处理;</section>
</li>
<li>
<section>制定汇报机制,晨会/周报;</section>
</li>
</ul>
<h3 id='2-4-4-自研和选型合适的辅助系统'  id="boomdevs_23" data-tool="mdnice编辑器" >2-4. 4、自研和选型合适的辅助系统</h3>
<p data-tool="mdnice编辑器">所有的流程和规范都需要用系统来固化,否则就是空中楼阁,如何选择这些系统呢?参照上个章节咱们那些开源的,对比一下选择的语言,组件之类的,选择一个最合适的即可。</p>
<p data-tool="mdnice编辑器">比如项目管理的,看下自己是什么类型的公司,开发的节奏是怎样的,瀑布,敏捷的 按项目划分,还是按客户划分等等,平时是按项目组织还是按任务组织等等。</p>
<p data-tool="mdnice编辑器">比如日志系统,之前是打的文本,那么上一个 ELK,规范化一些日志组件,基本上很长一段时间内不用考虑日志系统的问题,最多拆分一下或者扩容一下。等到组织大了,自己搞一个日志系统。</p>
<p data-tool="mdnice编辑器">比如代码管理,项目管理系统这些都放内网,安全,在互联网公司来说,属于命脉了,命脉的东西还是放在别人拿不到或很难拿到的地方会比较靠谱一些。</p>
<h3 id='2-5-5-选择过程中需要思考的问题'  id="boomdevs_24" data-tool="mdnice编辑器" >2-5. 5、选择过程中需要思考的问题</h3>
<p data-tool="mdnice编辑器">技术栈的选择有点像做出了某种承诺,在一定的时间内这种承诺没法改变,于是我们需要在选择的时候有一些思考。</p>
<p data-tool="mdnice编辑器">看前面内容,有一个词出现了三次,合适,选择是合适的,不是最好,也不是最新,是最合适,适合是针对当下,这种选择是最合适的吗?比如用 Go 这条线的东西,技术比较新,业界组件储备够吗?组织内的人员储备够吗?学习成本多少?写出来的东西能满足业务性能要求吗?能满足时间要求吗?</p>
<p data-tool="mdnice编辑器">向未来看一眼,在一年到三年内,我们需要做出改变吗?技术栈要做根本性的改变吗?如果组织发展很快,在 200 人,500 人时,现有的技术栈是否需要大动?</p>
<p data-tool="mdnice编辑器">创业过程中需要考虑成本,这里的成本不仅仅是花费多少钱,付出多少工资,有时更重要的是时间成本,很多业务在创业时大家拼的就是时间,就是一个时间窗,过了就没你什么事儿了。</p>
<p>&nbsp;</p>
<p>Refer</p>
<p><a href="https://mp.weixin.qq.com/s/WiunuUq910tDdtP5HfaDHA">作为技术负责人,如何从0搭建公司后端技术栈</a></p>The post <a href="http://www.mobabel.net/%e8%bd%ac%e4%bd%9c%e4%b8%ba%e6%8a%80%e6%9c%af%e8%b4%9f%e8%b4%a3%e4%ba%ba%ef%bc%8c%e5%a6%82%e4%bd%95%e4%bb%8e0%e6%90%ad%e5%bb%ba%e5%85%ac%e5%8f%b8%e5%90%8e%e7%ab%af%e6%8a%80%e6%9c%af%e6%a0%88/">[转]作为技术负责人,如何从0搭建公司后端技术栈</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e8%bd%ac%e4%bd%9c%e4%b8%ba%e6%8a%80%e6%9c%af%e8%b4%9f%e8%b4%a3%e4%ba%ba%ef%bc%8c%e5%a6%82%e4%bd%95%e4%bb%8e0%e6%90%ad%e5%bb%ba%e5%85%ac%e5%8f%b8%e5%90%8e%e7%ab%af%e6%8a%80%e6%9c%af%e6%a0%88/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[转]10 个角度分析软件工程师应该知道的 100 件事</title>
		<link>http://www.mobabel.net/%e8%bd%ac10-%e4%b8%aa%e8%a7%92%e5%ba%a6%e5%88%86%e6%9e%90%e8%bd%af%e4%bb%b6%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%ba%94%e8%af%a5%e7%9f%a5%e9%81%93%e7%9a%84-100-%e4%bb%b6%e4%ba%8b/</link>
					<comments>http://www.mobabel.net/%e8%bd%ac10-%e4%b8%aa%e8%a7%92%e5%ba%a6%e5%88%86%e6%9e%90%e8%bd%af%e4%bb%b6%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%ba%94%e8%af%a5%e7%9f%a5%e9%81%93%e7%9a%84-100-%e4%bb%b6%e4%ba%8b/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Tue, 04 Jan 2022 00:50:36 +0000</pubDate>
				<category><![CDATA[Collection]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=7315</guid>

					<description><![CDATA[<p>认真读完这 100 条建议,你一定会有所收获。 1. 1构建软件 过早优化是万恶之源。不要低估了这个说法的有效性。 你很少需要自己从头开始去开发一些东西,几乎每一种应用场景都已经有了相应的库和依赖项。所以,不要重复发明轮子。 搞清楚问题域是找到解决方案之前的第一步,但我们却经常会跳过第一步,直接去寻找解决方案。 不要太过于追求完美。首先,让它能够正常运行,然后再去优化。优先级最高的事情应该是先保证交付。 糟糕的程序员操心代码,优秀的程序员操心数据结构以及它们之间的关系。&#8211;Linus Torvalds 在代码注释中解释你为什么要写这些代码,而不是解释你在做什么。但不要过度描述,不要把注释当成小说写。 有意义的错误日志可以节省大量的调试时间。在错误日志中提供所有相关信息,而不仅仅是“error occurred in Function X!”另外不要记录任何敏感信息或个人信息。 100% 的代码行或分支覆盖率并不意味着你的代码就没有 bug。测试用例要覆盖所有的功能需求,而不是覆盖代码行或分支。 如果你在修复 bug,请编写相应的测试用例,那么这个 bug 就不会在未来某个时刻出现。bug 的出现通常是因为错误的假设,为所有这些错误的假设编写测试用例将会让应用程序变得更加健壮。 在人们阅读你的代码时,让他们能够在不记住超过 7 样东西的情况下理解你的代码。因为人类大脑的短期记忆无法同时记住 7 样以上的东西。这也是为什么很多代码检查器在遇到包含超过 7 个参数的函数时就会发出警告。 不要因为别人告诉你要怎样去做一件事情,你就照做。你要明白为什么要这么做,如果你不信服,可以挑战一下。 解决问题应该是每个工程师都最擅长的技能。你所在的组织有很多问题需要解决,所以请开始解决问题吧。虽然不是所有问题都能够得到解决,但在尝试解决问题的过程中你会学到很多。&#46;&#46;&#46;</p>
The post <a href="http://www.mobabel.net/%e8%bd%ac10-%e4%b8%aa%e8%a7%92%e5%ba%a6%e5%88%86%e6%9e%90%e8%bd%af%e4%bb%b6%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%ba%94%e8%af%a5%e7%9f%a5%e9%81%93%e7%9a%84-100-%e4%bb%b6%e4%ba%8b/">[转]10 个角度分析软件工程师应该知道的 100 件事</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<section>认真读完这 100 条建议,你一定会有所收获。</section>
<section></section>
<p><span id="more-7315"></span></p>
<h1 id='1-1构建软件'  id="boomdevs_1" >1. 1构建软件</h1>
<ol class="list-paddingleft-2">
<li>过早优化是万恶之源。不要低估了这个说法的有效性。</li>
<li>你很少需要自己从头开始去开发一些东西,几乎每一种应用场景都已经有了相应的库和依赖项。所以,不要重复发明轮子。</li>
<li>搞清楚问题域是找到解决方案之前的第一步,但我们却经常会跳过第一步,直接去寻找解决方案。</li>
<li>不要太过于追求完美。首先,让它能够正常运行,然后再去优化。优先级最高的事情应该是先保证交付。</li>
<li>糟糕的程序员操心代码,优秀的程序员操心数据结构以及它们之间的关系。&#8211;Linus Torvalds</li>
<li>在代码注释中解释你为什么要写这些代码,而不是解释你在做什么。但不要过度描述,不要把注释当成小说写。</li>
<li>有意义的错误日志可以节省大量的调试时间。在错误日志中提供所有相关信息,而不仅仅是“error occurred in Function X!”另外不要记录任何敏感信息或个人信息。</li>
<li>100% 的代码行或分支覆盖率并不意味着你的代码就没有 bug。测试用例要覆盖所有的功能需求,而不是覆盖代码行或分支。</li>
<li>如果你在修复 bug,请编写相应的测试用例,那么这个 bug 就不会在未来某个时刻出现。bug 的出现通常是因为错误的假设,为所有这些错误的假设编写测试用例将会让应用程序变得更加健壮。</li>
<li>在人们阅读你的代码时,让他们能够在不记住超过 7 样东西的情况下理解你的代码。因为人类大脑的短期记忆无法同时记住 7 样以上的东西。这也是为什么很多代码检查器在遇到包含超过 7 个参数的函数时就会发出警告。</li>
<li>不要因为别人告诉你要怎样去做一件事情,你就照做。你要明白为什么要这么做,如果你不信服,可以挑战一下。</li>
<li>解决问题应该是每个工程师都最擅长的技能。你所在的组织有很多问题需要解决,所以请开始解决问题吧。虽然不是所有问题都能够得到解决,但在尝试解决问题的过程中你会学到很多。</li>
</ol>
<h1 id='2-2系统设计'  id="boomdevs_2" >2. 2系统设计</h1>
<ol class="list-paddingleft-2" start="13">
<li>最好的系统设计通常是最简单的。Keep it simple, stupid!(KISS 原则)。</li>
<li>设计模式和最佳实践并非银弹。一个好的工程师遵循最佳实践,但一个优秀的工程师知道什么时候打破最佳实践。</li>
<li>理解抽象。代码中引入的不必要的复杂性通常是由于糟糕的抽象导致的。</li>
<li>一个系统的健壮程度取决于它最薄弱的地方。所以,请关注系统的瓶颈部分。</li>
<li>偏离主要源头越远,事情就越糟糕。所以,尽量减少跳跃,这个原则适用于技术和非技术方面。</li>
<li>不存在完美的解决方案,一切都是权衡的结果。列出解决方案的优点和缺点,以及你的真正要求。</li>
<li>你在项目中引入的每一项技术都有相应的风险。衡量风险并制定降低风险的计划,不穿救生衣就不要往海里跳。</li>
<li>避免过早抽象。解决你现在的问题,这样就够了。当你看到类似的问题或者模式出现时,这个时候应该考虑对其进行抽象。</li>
<li>“软件设计有两种方法:一种是保持简单,简单到没有明显的缺陷,另一种是让它变得复杂,复杂到没有明显的缺陷。第一种方法要困难得多,因为要保持简单是很难的”。——Tony Hoare。</li>
<li>不要对编程语言或框架有太多偏见。如果你喜欢某种编程语言,不要过于崇拜它,也不要到处用它。如果你讨厌它,也不要一直抱怨它。每种编程语言或框架都是为特定的场景而设计的。作为工程师,你的工作是为特定场景选择正确的工具。</li>
<li>当你弄清楚代码是怎样运行,却忘记了为什么要这么做,那么代码中就有很多不必要的抽象和复杂性需要清理。</li>
<li>一旦复杂性累积起来,就很难消除。不要认为你当下做出的变更所带来的一点点复杂性没什么大不了的,如果每个开发人员都这么做,复杂性就会成倍地增加。</li>
<li>如果你决定要重写某个组件或服务,请三思而后行。读代码比写代码难,这就是为什么“重写软件”的想法在软件开发中非常常见。</li>
<li>不要犹豫,去挑战高级工程师或架构师提出的设计,有时候你的设计比他们的更好。提出有说服力的观点并进行客观比较,但不要做一个盲目自信的混蛋。</li>
<li>大多数时候,静态类型语言比动态类型语言要好,尽管静态类型系统带来了一些额外的开销。这也是为什么 TypeScript 会是最受欢迎的编程语言之一。</li>
</ol>
<h1 id='3-3一些其他贴士'  id="boomdevs_3" >3. 3一些其他贴士</h1>
<ol class="list-paddingleft-2" start="28">
<li>优化代码,让它们更容易被读懂。冗长乏味的 20 行代码总比晦涩难懂的 1 行代码要好。</li>
<li>新手容易与自己编写的代码建立情感联系,但在敏捷开发环境中,需求和代码会不断发生变化,所以你要习惯于不断修改和删除旧代码。</li>
<li>对于任何一个问题都要想出不止一种解决方法。试图找到多个解决方案会迫使你以不同的方式思考问题,在有了不同的解决方案之后,你就可以做出权衡。</li>
<li>你负责的模块越多,获得的领域知识就越多。你拥有的领域知识越多,需要参加的会议就越多。你参加的会议越多,写的代码就越少。通过记录和分享领域知识来打破这个链条,这样你就不会成为唯一的瓶颈点。当然,我也知道这说起来容易做起来难。</li>
<li>当你在某个问题上困了很长一段时间而没有任何进展时,重新描述这个问题或向别人解释这个问题,大多数情况下这样做都会有神奇的效果。为什么小黄鸭调试法会如此受欢迎,现在你应该知道答案了。</li>
<li>你不需要在理解了整个代码库之后才开始工作。在了解了系统架构和生命周期之后,就可以开始开发你的模块,不要浪费时间去了解每一类是干什么的。</li>
<li>代码是负债而不是资产。代码越多,需要阅读、理解、测试和维护的代码就越多。最好的代码是没有代码。</li>
<li>学习如何在 StackOverflow 上提问题。你可能很少需要在这类平台上提问题,但是当你使用的库或框架只有很有限的文档或用户时,这就成了一项有用的技能。</li>
<li>如果你发现了其他模块出现了 bug,请通知相应的开发人员,或者在 Scrum 中提及,不要因为这些模块不是你负责的就置之不理。</li>
<li>你编写的函数应该没有副作用,这样易于进行独立的测试。</li>
<li>看在上帝的份上,请不要自己编写日期格式化或日期解析函数。每种编程语言都有很多流行的库,使用它们就可以了,日期和时区问题比你想象的要复杂得多。</li>
</ol>
<h1 id='4-4关于安全'  id="boomdevs_4" >4. 4关于安全</h1>
<ol class="list-paddingleft-2" start="39">
<li>每个开发人员都应该知道如何编写安全的代码。基于糟糕的设计或抽象写代码是可以的,但有安全漏洞的代码绝对不行。写代码前先了解一下 OWASP 项目(https://owasp.org/www-project-top-ten/)。</li>
<li>当你想要快速格式化或验证 JSON / XML / YAML 数据时,不要使用在线格式化器或验证器,特别是如果你处理的是一些机密的生产数据。这个时候请使用本地编辑器或命令行工具,不要冒着把公司数据泄露出去的风险。(推荐工具 CyberChef,https://gchq.github.io/CyberChef/,请下载离线使用)</li>
<li>永远不要向代码库中推送敏感信息。在提交和推送代码之前,一定要仔细检查代码中是否包含了电子邮件地址、电话号码、密码、认证令牌、私钥等信息。</li>
<li>总是对用户输入进行验证和清理。永远不要假设或期望用户按照指定的格式输入数据。在验证用户输入时,首选白名单而不是黑名单。</li>
</ol>
<h1 id='5-5关于拉取请求'  id="boomdevs_5" >5. 5关于拉取请求</h1>
<ol class="list-paddingleft-2" start="43">
<li>你可以在拉取请求的评论中加入赞美之词。当我们在代码评审时,总是专注于不好的部分,而一个小小的赞美可以给你的同事带来微笑。下次可以试一试这样做。</li>
<li>每天查看拉取请求,阅读其他开发人员的评论,以获得关于特性和编码标准的不同观点。</li>
<li>代码格式和其他标准应该被自动化。使用代码格式化器和检查器来构建项目开发管道,让整个代码库保持一致和整洁。请停止在评论中进行有关 tab 好还是空格好的争论!</li>
<li>创建小而美的拉取请求。如果你正在处理多个功能,请将它们分成多个拉取请求。给评审人员留有足够的评审时间,不要在部署前 1 小时创建拉取请求。</li>
</ol>
<section>6关于学习</section>
<ol class="list-paddingleft-2" start="47">
<li>作为一个程序员,你应该喜欢学习和探索。如果你不喜欢这些,需要考虑其他职业选择。</li>
<li>你不需要去学习每一项技术,你只需要紧跟潮流,在需要的时候学习和使用它们。</li>
<li>从一个刚毕业的实习生身上也可以学到很多东西。永远不要把你的学习对象局限于更高职位的人。</li>
<li>阅读你所使用的开源项目的源代码,理解和学习干净的代码实践和代码组织方式。</li>
<li>一种学习技术的方法是自己尝试为某个开源项目构建一个高度简化的版本 (https://github.com/danistefanovic/build-your-own-x)。</li>
<li>你可以在几天内学会一门编程语言,但要了解它的生态系统需要几个月甚至几年的时间。</li>
<li>探索不同的编程语言,了解不同的编程范式。了解了不同的编程范式,当你在为不同的应用场景选择正确的编程语言时,就会有所裨益。</li>
<li>学习 git,不仅仅是 git pull 和 git commit,要理解 git 所有的高级概念。不管你使用的是什么技术,都不能没有 git。</li>
<li>大多数开发人员的工作都集中在 Web/ 网络编程方面,所以了解网络系统的底层协议是很有必要的:HTTP、HTTPS、SSL/TLS、DNS、SMTP、IPv4、IPv6 等。</li>
<li>拥有良好的 CSS 专业知识会让你看起来像一个大神!如果你是一个 Web 全栈开发者,请花几天时间学习 CSS,这将为你避免“不知道自己做什么”的尴尬。</li>
<li>一个有吸引力的 UI 设计比一个健壮的系统架构更容易给人们 (显然不是指领域专家) 留下深刻的印象。所以,当你在进行概念验证时,拥有良好的设计技能是非常有用的 (但不要把所有东西都硬编码成 HTML)。</li>
</ol>
<h1 id='6-7关于效率'  id="boomdevs_6" >6. 7关于效率</h1>
<ol class="list-paddingleft-2" start="58">
<li>创建细粒度的子任务来跟踪任务进度,尤其是当你在处理一项巨大的任务时。检查某件事是否已经完成,这会给人一种难以言表的愉悦感,这反过来会激励你坚持下去。</li>
<li>不要试图同时做多个任务,专注于一个任务,尽量减少上下文切换,上下文切换的成本比你预想的要高。</li>
<li>改进和定制你的工作流 (IDE、调试工具、生产力工具、CI/CD),帮你进行更快的迭代。</li>
</ol>
<p>迭代得越快,失败得越快。</p>
<p>失败得越快,学习得就越快。</p>
<ol class="list-paddingleft-2" start="61">
<li>把你的时间花在自动化常规任务上。如果你做某件事超过两次,那就开发一个工具,让它在第三次时可以自动完成。但不要浪费太多时间去自动化一个只需要几分钟时间就可以完成的简单任务。你应该找到一个正确的平衡点!</li>
<li>用文件夹和标签来整理工作邮件 (包括私人邮件)。每天稍微整理一下邮件,可以帮助你在需要的时候快速找到重要的文件或聊天记录。</li>
<li>学习基本的 vi 绑定,即使 vi 不是你的默认编辑器。你可以在几乎所有的文本编辑器中使用 vi 绑定,相信我,在这之后你的效率将得到大幅提升。</li>
<li>在这个行业中,文档技能被严重低估了。学习如何撰写设计文档、变更建议等。开始使用笔记工具来组织和记录几乎所有的事情——备忘录、个人目标、职业目标、随机出现的想法、书籍摘要,等等。</li>
<li>在评估任务时,一定要预留一些缓冲时间,你永远不知道在一个未知的洞穴里会遇到什么怪物。</li>
<li>如果你要边听音乐边干活,最好听器乐或低保真节拍或平静的音乐,而不要听带有歌词的音乐。我个人觉得在听演奏器乐时更有效率,这并不奇怪,科学方面已经为此提供了证据支持。</li>
</ol>
<h1 id='7-8关于自己'  id="boomdevs_7" >7. 8关于自己</h1>
<ol class="list-paddingleft-2" start="67">
<li>马上调整好你的身体姿势!</li>
<li>工作之外最好有其他业余爱好。虽然你是一名开发人员,但也没必要全天候在写代码。</li>
<li>善待每一个人!保持冷静!最重要的是,要谦虚!</li>
<li>记住要经常休息,不要把自己弄得筋疲力尽。</li>
<li>购买一套好的工作站,因为你大部分时间都在办公桌前度过 (尤其是在远程工作的日子里),在高质量的产品上多花点钱是值得的。</li>
<li>去了解不同的认知偏见,这样不仅能帮助你做出更好的个人决定,还能帮助你做出更好的技术决策。</li>
<li>在职业生涯早期就开始投资,了解复利的力量,相信我,它很神奇。同时,不要过度储蓄,如果你无法享受当下,就算存了很多钱又有什么意义呢?</li>
</ol>
<section>9关于人际关系</section>
<ol class="list-paddingleft-2" start="74">
<li>人际交往能力和你的技术能力一样重要。有意识地锻炼指导他人、公共演讲、领导项目等方面的能力。开发者可以打破给人留下的“社交无能”的刻板印象。</li>
<li>并不是每个人都有和你一样的动机。不要因为你对某个话题感兴趣,就指望别人也会感兴趣。不同的人对不同的动机有不同的反应。</li>
<li>不要用你的同事 (事实上是任何人) 不懂的东西来评判他们。</li>
<li>学习如何推销自己。你可能对很多东西都很熟练,但如果你没有在正确的平台上展示这些技能,没有人会欣赏你。</li>
<li>帮助你周围的人,让他们变得更好。传授或分享你所学到的东西。教授或写一些你学过的东西,这样会让你更好地理解它们。</li>
<li>勇敢地说出“我不知道”。你可能很擅长撒谎,但我们的大脑很善于识别某人是否在撒谎或假装。</li>
<li>你的团队中始终会有一个顶级的开发人员,他几乎可以解决任何问题。不要被他们的技术能力吓倒,看看他们提交的 PR,跟他们聊技术方面的东西,并定期从他们那里获得反馈来提高自己。</li>
<li>你很有可能会在工作中遇到你最好的朋友,不要因此无法向他们敞开心扉 (要不要接受这个建议取决于你自己的判断)。</li>
</ol>
<h1 id='8-10关于沟通'  id="boomdevs_8" >8. 10关于沟通</h1>
<ol class="list-paddingleft-2" start="82">
<li>倾听,不疲于倾听!</li>
<li>如果你在会议上没有什么想说的,也没关系,不要东拉西扯,浪费别人的时间。</li>
<li>在给别人发消息时不要只是发“你好”或“早上好”之类的问候,然后等着他们回话。你要告诉他们你找他们有什么事,没有人喜欢你这种毫无意义的问候或祝福。</li>
<li>在向别人介绍你的设计时,尽可能使用图表,一图胜千言。在文档里使用图表也很有意义 (推荐工具 draw.io)。</li>
<li>向别人介绍某些设计或概念时,少用行话。不是每个人都很熟悉技术术语,在使用术语时要恰到好处。</li>
<li>不要羞于去问一些你认为琐碎或愚蠢的问题。</li>
<li>如果你想在几分钟内完成工作,那就打电话。如果你想在几个小时内完成工作,那就使用即时通讯工具。如果你不想完成工作,那就发邮件 (2021 年人们还在使用邮件吗?)。</li>
<li>当你向别人寻求帮助时,不要只说“嘿,这个有问题,你能帮我吗”,你要说“嘿,我在运行程序 X 时出现了错误 Y,我研究并尝试了解决方案 Z,但它似乎也不行,你能帮我解决这个问题吗”。在向别人寻求帮助之前先自己做一些调查,不要因为代码中小小的拼写错误而浪费别人的时间,说真的!</li>
<li>不要成为自行车棚效应(避重就轻)的牺牲品。在会议或讨论中,重视复杂或关键的事项,而不是琐碎的事项。</li>
</ol>
<section>11关于职业生涯</section>
<ol class="list-paddingleft-2" start="91">
<li>如果你不喜欢自己做的事情,没关系,但如果你讨厌自己做的事情,那就不能接受了。</li>
<li>当你刚进入职场时,优先考虑的是学习和发展的机会,而不是薪水、福利等。在学习效率高的活动或工作上投入更多的时间。发展综合能力,你必须及早开始。</li>
<li>你工作的动力应该是为团队和项目增加价值,而不是为了给别人留下好印象,进而获得更高的薪水或晋升。如果前者做好了,后者自然会光顾。</li>
<li>花点时间写简历,并让它保持最新。建议为自己做一个可以描述你的项目和经验的作品集网站。</li>
<li>你的职位越高,你要解决的问题就越抽象模糊。所以,你要学会适应不确定性。</li>
<li>每六个月问自己以下这些问题:</li>
</ol>
<section>
<ul class="list-paddingleft-2">
<li>
<section>我是否在学习新的技能、拓宽自己的专业领域?</section>
</li>
<li>
<section>我是否对组织产生了影响?</section>
</li>
<li>
<section>从我的技能和经验来看,我的薪水是否足够高?</section>
</li>
</ul>
</section>
<p>如果你的答案都是否定的,那么你必须考虑换公司或团队了。如果你在现在的公司已经工作了 2 至 3 年以上,并且你的答案都是肯定的,那么你应该考虑换公司,或者至少要对换公司持开放态度。</p>
<ol class="list-paddingleft-2" start="97">
<li>如果你仔细观察,你会发现编程和写作非常相似。编程语言类似于人类语言,程序员类似于作家和诗人。任何人都可以成为作家,但要成为一名优秀的作家需要付出大量时间和努力。</li>
<li>定期与经理进行一对一面谈,并寻求反馈,不要等到年终总结时才发现“惊喜”。</li>
<li>如果你的经理没有为你的失败负责,并责怪你,那么在他们手下工作就是在拿你的个人和职业发展冒险。</li>
<li>经验年限只是一个数字。有时候你会发现初级工程师比高级工程师对某些事情更熟悉。但请不要误解了我的意思,经验教会你的不仅仅是技能。工作经验固然重要,但这并不是评判一个工程师的唯一因素。</li>
</ol>
<section>
<h1 id='9-12额外的建议'  id="boomdevs_9" >9. 12额外的建议</h1>
</section>
<section>
<ol class="list-paddingleft-2">
<li>记住帕累托法则 (80/20 法则),它几乎适用于软件工程的方方面面:</li>
</ol>
<section>
<ul class="list-paddingleft-2">
<li>80% 的工作是由 20% 的工程师完成的;</li>
<li>80% 的影响是由 20% 的工作所带来的;</li>
<li>80% 的错误是由 20% 的代码造成的;</li>
<li>80% 的慢性能是由 20% 的代码造成的。</li>
</ul>
</section>
<p>  我可以举出无数个例子。</p>
<ol class="list-paddingleft-2" start="2">
<li>
<section>对于那些在 StackOverflow 出现之前就开始写代码的开发人员,我们是否应该给他们一点掌声?StackOverflow 可以解决你 95% 的问题 (但千万别在上面问你的个人问题)。</section>
</li>
<li>
<section>Git 的提交消息应该具备足够好的描述,这样你就可以从成千上万的代码提交中轻松搜索到你想要的。停止使用诸如“修复了一个 bug”、“改进了性能”、“修改了 X 模块”之类的描述。</section>
</li>
</ol>
</section>
<p>&nbsp;</p>
<p>原文链接:</p>
<p>https://mp.weixin.qq.com/s/o5HTXeLdwB1nf4_fJjjTIg</p>
<p>https://hkandala.dev/100-things-you-should-know</p>The post <a href="http://www.mobabel.net/%e8%bd%ac10-%e4%b8%aa%e8%a7%92%e5%ba%a6%e5%88%86%e6%9e%90%e8%bd%af%e4%bb%b6%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%ba%94%e8%af%a5%e7%9f%a5%e9%81%93%e7%9a%84-100-%e4%bb%b6%e4%ba%8b/">[转]10 个角度分析软件工程师应该知道的 100 件事</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e8%bd%ac10-%e4%b8%aa%e8%a7%92%e5%ba%a6%e5%88%86%e6%9e%90%e8%bd%af%e4%bb%b6%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%ba%94%e8%af%a5%e7%9f%a5%e9%81%93%e7%9a%84-100-%e4%bb%b6%e4%ba%8b/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[转]一个复杂系统的拆分改造实践</title>
		<link>http://www.mobabel.net/%e8%bd%ac%e4%b8%80%e4%b8%aa%e5%a4%8d%e6%9d%82%e7%b3%bb%e7%bb%9f%e7%9a%84%e6%8b%86%e5%88%86%e6%94%b9%e9%80%a0%e5%ae%9e%e8%b7%b5/</link>
					<comments>http://www.mobabel.net/%e8%bd%ac%e4%b8%80%e4%b8%aa%e5%a4%8d%e6%9d%82%e7%b3%bb%e7%bb%9f%e7%9a%84%e6%8b%86%e5%88%86%e6%94%b9%e9%80%a0%e5%ae%9e%e8%b7%b5/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Fri, 04 Jun 2021 18:30:48 +0000</pubDate>
				<category><![CDATA[Collection]]></category>
		<category><![CDATA[Architecture]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=7179</guid>

					<description><![CDATA[<p>1. 1 为什么要拆分? 先看一段对话。 从上面对话可以看出拆分的理由: 1)  应用间耦合严重。系统内各个应用之间不通,同样一个功能在各个应用中都有实现,后果就是改一处功能,需要同时改系统中的所有应用。这种情况多存在于历史较长的系统,因各种原因,系统内的各个应用都形成了自己的业务小闭环; 2)  业务扩展性差。数据模型从设计之初就只支持某一类的业务,来了新类型的业务后又得重新写代码实现,结果就是项目延期,大大影响业务的接入速度; 3)  代码老旧,难以维护。各种随意的if else、写死逻辑散落在应用的各个角落,处处是坑,开发维护起来战战兢兢; 4)  系统扩展性差。系统支撑现有业务已是颤颤巍巍,不论是应用还是DB都已经无法承受业务快速发展带来的压力; 5)  新坑越挖越多,恶性循环。不改变的话,最终的结果就是把系统做死了。 2. 2 拆前准备什么? 2-1. 2.1 多维度把握业务复杂度 一个老生常谈的问题,系统与业务的关系? 我们最期望的理想情况是第一种关系(车辆与人),业务觉得不合适,可以马上换一辆新的。但现实的情况是更像心脏起搏器与人之间的关系,不是说换就能换。一个系统接的业务越多,耦合越紧密。如果在没有真正把握住业务复杂度之前贸然行动,最终的结局就是把心脏带飞。 如何把握住业务复杂度?需要多维度的思考、实践。 一个是技术层面,通过与pd以及开发的讨论,熟悉现有各个应用的领域模型,以及优缺点,这种讨论只能让人有个大概,更多的细节如代码、架构等需要通过做需求、改造、优化这些实践来掌握。 各个应用熟悉之后,需要从系统层面来构思,我们想打造平台型的产品,那么最重要也是最难的一点就是功能集中管控,打破各个应用的业务小闭环,统一收拢,这个决心更多的是开发、产品、业务方、各个团队之间达成的共识,可以参考《微服务(Microservice)那点事》一文,“按照业务或者客户需求组织资源”。 此外也要与业务方保持功能沟通、计划沟通,确保应用拆分出来后符合使用需求、扩展需求,获取他们的支持。 2-2. 2.2 定义边界,原则:高内聚,低耦合,单一职责! 业务复杂度把握后,需要开始定义各个应用的服务边界。怎么才算是好的边界?像葫芦娃兄弟一样的应用就是好的! 举个例子,葫芦娃兄弟(应用)间的技能是相互独立的,遵循单一职责原则,比如水娃只能喷水,火娃只会喷火,隐形娃不会喷水喷火但能隐身。更为关键的是,葫芦娃兄弟最终可以合体为金刚葫芦娃,即这些应用虽然功能彼此独立,但又相互打通,最后合体在一起就成了我们的平台。 这里很多人会有疑惑,拆分粒度怎么控制?很难有一个明确的结论,只能说是结合业务场景、目标、进度的一个折中。但总体的原则是先从一个大的服务边界开始,不要太细,因为随着架构、业务的演进,应用自然而然会再次拆分,让正确的事情自然发生才最合理。 2-3. 2.3 确定拆分后的应用目标 一旦系统的宏观应用拆分图出来后,就要落实到某一具体的应用拆分上了。 首先要确定的就是某一应用拆分后的目标。拆分优化是没有底的,可能越做越深,越做越没结果,继而又影响自己和团队的士气。比如说可以定这期的目标就是将db、应用分拆出去,数据模型的重新设计可以在第二期。&#46;&#46;&#46;</p>
The post <a href="http://www.mobabel.net/%e8%bd%ac%e4%b8%80%e4%b8%aa%e5%a4%8d%e6%9d%82%e7%b3%bb%e7%bb%9f%e7%9a%84%e6%8b%86%e5%88%86%e6%94%b9%e9%80%a0%e5%ae%9e%e8%b7%b5/">[转]一个复杂系统的拆分改造实践</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<h2 id='1-1-为什么要拆分'  id="boomdevs_1" >1. 1 为什么要拆分?</h2>
<p>先看一段对话。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218173956636-1799366252.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7180" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218173956636-1799366252.png" alt="" width="796" height="353" /></a></p>
<p>从上面对话可以看出拆分的理由:</p>
<p>1)  <strong>应用间耦合严重</strong>。系统内各个应用之间不通,同样一个功能在各个应用中都有实现,后果就是改一处功能,需要同时改系统中的所有应用。这种情况多存在于历史较长的系统,因各种原因,系统内的各个应用都形成了自己的业务小闭环;</p>
<p>2)  <strong>业务扩展性差</strong>。数据模型从设计之初就只支持某一类的业务,来了新类型的业务后又得重新写代码实现,结果就是项目延期,大大影响业务的接入速度;</p>
<p>3)  <strong>代码老旧,难以维护</strong>。各种随意的if else、写死逻辑散落在应用的各个角落,处处是坑,开发维护起来战战兢兢;</p>
<p>4)<strong>  系统扩展性差</strong>。系统支撑现有业务已是颤颤巍巍,不论是应用还是DB都已经无法承受业务快速发展带来的压力;</p>
<p>5)  <strong>新坑越挖越多,恶性循环</strong>。不改变的话,最终的结果就是把系统做死了。</p>
<p><span id="more-7179"></span></p>
<h2 id='2-2-拆前准备什么'  id="boomdevs_2" >2. 2 拆前准备什么?</h2>
<h3 id='2-1-2-1-多维度把握业务复杂度'  id="boomdevs_3" >2-1. 2.1 多维度把握业务复杂度</h3>
<p>一个老生常谈的问题,系统与业务的关系?</p>
<p>我们最期望的理想情况是第一种关系(车辆与人),业务觉得不合适,可以马上换一辆新的。但现实的情况是更像心脏起搏器与人之间的关系,不是说换就能换。一个系统接的业务越多,耦合越紧密。如果在没有真正把握住业务复杂度之前贸然行动,最终的结局就是把心脏带飞。</p>
<p>如何把握住业务复杂度?需要多维度的思考、实践。</p>
<p>一个是技术层面,通过与pd以及开发的讨论,熟悉现有各个应用的领域模型,以及优缺点,这种讨论只能让人有个大概,更多的细节如代码、架构等需要通过做需求、改造、优化这些实践来掌握。</p>
<p>各个应用熟悉之后,需要从系统层面来构思,我们想打造平台型的产品,那么最重要也是最难的一点就是功能集中管控,打破各个应用的业务小闭环,统一收拢,这个决心更多的是开发、产品、业务方、各个团队之间达成的共识,可以参考《<a href="https://yq.aliyun.com/articles/2764?spm=5176.team25.teamshow1.10.GtKpl8cc">微服务(Microservice)那点事</a>》一文,“按照业务或者客户需求组织资源”。</p>
<p>此外也要与业务方保持功能沟通、计划沟通,确保应用拆分出来后符合使用需求、扩展需求,获取他们的支持。</p>
<h3 id='2-2-2-2-定义边界-原则-高内聚-低耦合-单一职责'  id="boomdevs_4" >2-2. 2.2 定义边界,原则:高内聚,低耦合,单一职责!</h3>
<p>业务复杂度把握后,需要开始定义各个应用的服务边界。怎么才算是好的边界?像葫芦娃兄弟一样的应用就是好的!</p>
<p>举个例子,葫芦娃兄弟(应用)间的技能是相互独立的,遵循单一职责原则,比如水娃只能喷水,火娃只会喷火,隐形娃不会喷水喷火但能隐身。更为关键的是,葫芦娃兄弟最终可以合体为金刚葫芦娃,即这些应用虽然功能彼此独立,但又相互打通,最后合体在一起就成了我们的平台。</p>
<p>这里很多人会有疑惑,拆分粒度怎么控制?很难有一个明确的结论,只能说是结合业务场景、目标、进度的一个折中。但总体的原则是先从一个大的服务边界开始,不要太细,因为随着架构、业务的演进,应用自然而然会再次拆分,让正确的事情自然发生才最合理。</p>
<h3 id='2-3-2-3-确定拆分后的应用目标'  id="boomdevs_5" >2-3. 2.3 确定拆分后的应用目标</h3>
<p>一旦系统的宏观应用拆分图出来后,就要落实到某一具体的应用拆分上了。</p>
<p>首先要确定的就是某一应用拆分后的目标。拆分优化是没有底的,可能越做越深,越做越没结果,继而又影响自己和团队的士气。比如说可以定这期的目标就是将db、应用分拆出去,数据模型的重新设计可以在第二期。</p>
<h3 id='2-4-2-4-确定当前要拆分应用的架构状态-代码情况-依赖状况-并推演可能的各种异常'  id="boomdevs_6" >2-4. 2.4 确定当前要拆分应用的架构状态、代码情况、依赖状况,并推演可能的各种异常。</h3>
<p><strong>动手前的思考成本远远低于动手后遇到问题的解决成本</strong>。应用拆分最怕的是中途说“他*的,这块不能动,原来当时这样设计是有原因的,得想别的路子!”这时的压力可想而知,整个节奏不符合预期后,很可能会接二连三遇到同样的问题,这时不仅同事们士气下降,自己也会丧失信心,继而可能导致拆分失败。</p>
<h3 id='2-5-2-5-给自己留个锦囊-有备无患'  id="boomdevs_7" >2-5. 2.5 给自己留个锦囊,“有备无患”。</h3>
<p>锦囊就四个字“有备无患”,可以贴在桌面或者手机上。在以后具体实施过程中,多思考下“方案是否有多种可以选择?复杂问题能否拆解?实际操作时是否有预案?”,应用拆分在具体实践过程中比拼得就是细致二字,多一份方案,多一份预案,不仅能提升成功概率,更给自己信心。</p>
<h3 id='2-6-2-6-放松心情-缓解压力'  id="boomdevs_8" >2-6. 2.6 放松心情,缓解压力</h3>
<p>收拾下心情,开干!</p>
<h2 id='3-3-实践'  id="boomdevs_9" >3. 3 实践</h2>
<h3 id='3-1-3-1-db拆分实践'  id="boomdevs_10" >3-1. 3.1 db拆分实践</h3>
<p>DB拆分在整个应用拆分环节里最复杂,分为垂直拆分和水平拆分两种场景,我们都遇到了。垂直拆分是将库里的各个表拆分到合适的数据库中。比如一个库中既有消息表,又有人员组织结构表,那么将这两个表拆分到独立的数据库中更合适。</p>
<p>水平拆分:以消息表为例好了,单表突破了千万行记录,查询效率较低,这时候就要将其分库分表。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218182823495-1086792532.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7181" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218182823495-1086792532.png" alt="" width="1005" height="394" /></a></p>
<h4 id='3-1-1-3-1-1-主键id接入全局id发生器'  id="boomdevs_11" >3-1-1. 3.1.1 主键id接入全局id发生器</h4>
<p>DB拆分的第一件事情就是使用全局id发生器来生成各个表的主键id。为什么?</p>
<p>举个例子,假如我们有一张表,两个字段id和token,id是自增主键生成,要以token维度来分库分表,这时继续使用自增主键会出现问题。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183038636-1877294492.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7182" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183038636-1877294492.png" alt="" width="771" height="198" srcset="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183038636-1877294492.png 771w, http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183038636-1877294492-300x77.png 300w, http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183038636-1877294492-768x197.png 768w" sizes="(max-width: 771px) 100vw, 771px" /></a></p>
<p>正向迁移扩容中,通过自增的主键,到了新的分库分表里一定是唯一的,但是,我们要考虑迁移失败的场景,如下图所示,新的表里假设已经插入了一条新的记录,主键id也是2,这个时候假设开始回滚,需要将两张表的数据合并成一张表(逆向回流),就会产生主键冲突!</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183143948-1971603346.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7183" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183143948-1971603346.png" alt="" width="829" height="259" /></a></p>
<p>因此在迁移之前,先要用全局唯一id发生器生成的id来替代主键自增id。这里有几种全局唯一id生成方法可以选择。</p>
<p>1)snowflake:<a href="https://github.com/twitter/snowflake">https://github.com/twitter/snowflake</a>;(非全局递增)</p>
<p>2) mysql新建一张表用来专门生成全局唯一id(利用auto_increment功能)(全局递增);</p>
<p>3)有人说只有一张表怎么保证高可用?那两张表好了(在两个不同db),一张表产生奇数,一张表产生偶数。或者是n张表,每张表的负责的步长区间不同(非全局递增)</p>
<p>4)……</p>
<p>我们使用的是阿里巴巴内部的tddl-sequence(mysql+内存),保证全局唯一但非递增,在使用上遇到一些坑:</p>
<p>1)对按主键id排序的sql要提前改造。因为id已经不保证递增,可能会出现乱序场景,这时候可以改造为按gmt_create排序;</p>
<p>2)报主键冲突问题。这里往往是代码改造不彻底或者改错造成的,比如忘记给某一insert sql的id添加#{},导致继续使用自增,从而造成冲突;</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183529636-2134676460.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7184" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183529636-2134676460.png" alt="" width="862" height="99" srcset="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183529636-2134676460.png 862w, http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183529636-2134676460-300x34.png 300w, http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183529636-2134676460-768x88.png 768w" sizes="(max-width: 862px) 100vw, 862px" /></a></p>
<h4 id='3-1-2-3-1-2-建新表-迁移数据-binlog同步'  id="boomdevs_12" >3-1-2. 3.1.2 建新表&amp;迁移数据&amp;binlog同步</h4>
<p>1)  新表字符集建议是utf8mb4,支持表情符。<strong>新表建好后索引不要漏掉</strong>,否则可能会导致慢sql!从经验来看索引被漏掉时有发生,建议事先列计划的时候将这些要点记下,后面逐条检查;</p>
<p>2)  使用全量同步工具或者自己写job来进行全量迁移;全量数据迁移务必要在业务低峰期时操作,并根据系统情况调整并发数;</p>
<p>3)  增量同步。全量迁移完成后可使用binlog增量同步工具来追数据,比如阿里内部使用精卫,其它企业可能有自己的增量系统,或者使用阿里开源的cannal/otter:<a href="https://github.com/alibaba/canal?spm=5176.100239.blogcont11356.10.5eNr98">https://github.com/alibaba/canal?spm=5176.100239.blogcont11356.10.5eNr98</a></p>
<p><a href="https://github.com/alibaba/otter/wiki/QuickStart?spm=5176.100239.blogcont11356.21.UYMQ17">https://github.com/alibaba/otter/wiki/QuickStart?spm=5176.100239.blogcont11356.21.UYMQ17</a></p>
<p>增量同步起始获取的binlog位点必须在全量迁移之前,否则会丢数据,比如我中午12点整开始全量同步,13点整全量迁移完毕,那么增量同步的binlog的位点一定要选在12点之前。</p>
<p>位点在前会不会导致重复记录?不会!线上的MySQL binlog是row 模式,如一个delete语句删除了100条记录,binlog记录的不是一条delete的逻辑sql,而是会有100条binlog记录。insert语句插入一条记录,如果主键冲突,插入不进去。</p>
<h4 id='3-1-3-3-1-3-联表查询sql改造'  id="boomdevs_13" >3-1-3. 3.1.3 联表查询sql改造</h4>
<p>现在主键已经接入全局唯一id,新的库表、索引已经建立,且数据也在实时追平,现在可以开始切库了吗?no!</p>
<p>考虑以下非常简单的联表查询sql,如果将B表拆分到另一个库里的话,这个sql怎么办?毕竟跨库联表查询是不支持的!</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183956167-121420757.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7185" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183956167-121420757.png" alt="" width="676" height="102" srcset="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183956167-121420757.png 676w, http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218183956167-121420757-300x45.png 300w" sizes="(max-width: 676px) 100vw, 676px" /></a></p>
<p>因此,在切库之前,需要将系统中上百个联表查询的sql改造完毕。</p>
<p>如何改造呢?</p>
<p><strong>1) </strong><strong>业务避免</strong></p>
<p>业务上松耦合后技术才能松耦合,继而避免联表sql。但短期内不现实,需要时间沉淀;</p>
<p><strong>2) </strong><strong>全局表</strong></p>
<p>每个应用的库里都冗余一份表,缺点:等于没有拆分,而且很多场景不现实,表结构变更麻烦;</p>
<p><strong>3) </strong><strong>冗余字段</strong></p>
<p>就像订单表一样,冗余商品id字段,但是我们需要冗余的字段太多,而且要考虑字段变更后数据更新问题;</p>
<p><strong>4) </strong><strong>内存拼接</strong></p>
<p>4.1)通过RPC调用来获取另一张表的数据,然后再内存拼接。1)适合job类的sql,或改造后RPC查询量较少的sql;2)不适合大数据量的实时查询sql。假设10000个ID,分页RPC查询,每次查100个,需要5ms,共需要500ms,rt太高。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184220245-618223446.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7186" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184220245-618223446.png" alt="" width="379" height="137" srcset="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184220245-618223446.png 379w, http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184220245-618223446-300x108.png 300w" sizes="(max-width: 379px) 100vw, 379px" /></a></p>
<p>4.2)本地缓存另一张表的数据</p>
<p>适合数据变化不大、数据量查询大、接口性能稳定性要求高的sql。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184309964-2129746962.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7187" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184309964-2129746962.png" alt="" width="385" height="210" /></a></p>
<h4 id='3-1-4-3-1-4切库方案设计与实现-两种方案'  id="boomdevs_14" >3-1-4. 3.1.4切库方案设计与实现(两种方案)</h4>
<p align="left">以上步骤准备完成后,就开始进入真正的切库环节,这里提供两种方案,我们在不同的场景下都有使用。</p>
<p><strong>a)DB停写方案</strong></p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184509151-484867406.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7188" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184509151-484867406.png" alt="" width="434" height="174" /></a></p>
<p><strong>优点</strong>:快,成本低;</p>
<p><strong>缺点:</strong></p>
<p>1)如果要回滚得联系DBA执行线上停写操作,风险高,因为有可能在业务高峰期回滚;</p>
<p>2)只有一处地方校验,出问题的概率高,回滚的概率高</p>
<p>举个例子,如果面对的是比较复杂的业务迁移,那么很可能发生如下情况导致回滚:</p>
<p>sql联表查询改造不完全;</p>
<p>sql联表查询改错&amp;性能问题;</p>
<p>索引漏加导致性能问题;</p>
<p>字符集问题</p>
<p>此外,binlog逆向回流很可能发生字符集问题(utf8mb4到gbk),导致回流失败。这些binlog同步工具为了保证强最终一致性,一旦某条记录回流失败,就卡住不同步,继而导致新老表的数据不同步,继而无法回滚!</p>
<p><strong>b)双写方案</strong></p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184941058-1856293397.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7189" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218184941058-1856293397.png" alt="" width="655" height="418" /></a></p>
<p>第2步“打开双写开关,先写老表A再写新表B”,这时候确保写B表时try catch住,异常要用很明确的标识打出来,方便排查问题。第2步双写持续短暂时间后(比如半分钟后),可以关闭binlog同步任务。</p>
<p><strong>优点:</strong></p>
<p>1)将复杂任务分解为一系列可测小任务,步步为赢;</p>
<p>2)线上不停服,回滚容易;</p>
<p>3)字符集问题影响小</p>
<p><strong>缺点:</strong></p>
<p>1)流程步骤多,周期长;</p>
<p>2)双写造成RT增加</p>
<h4 id='3-1-5-3-1-5-开关要写好'  id="boomdevs_15" >3-1-5. 3.1.5 开关要写好</h4>
<p>不管什么切库方案,开关少不了,这里开关的初始值一定要设置为null!</p>
<p>如果随便设置一个默认值,比如”读老表A“,假设我们已经进行到读新表B的环节了。这时重启了应用,在应用启动的一瞬间,最新的“读新表B”的开关推送等可能没有推送过来,这个时候就可能使用默认值,继而造成脏数据!</p>
<p>&nbsp;</p>
<h3 id='3-2-3-2-拆分后一致性怎么保证'  id="boomdevs_16" >3-2. 3.2 拆分后一致性怎么保证?</h3>
<p>以前很多表都在一个数据库内,使用事务非常方便,现在拆分出去了,如何保证一致性?</p>
<p><strong>1)分布式事务</strong></p>
<p><span style="color: #ff0000;"><strong>性能较差,几乎不考虑</strong></span>。</p>
<p><strong>2)消息机制补偿</strong>(<a href="http://www.cnblogs.com/LBSer/p/4715395.html" target="_blank" rel="noopener">如何用消息系统避免分布式事务?</a>)</p>
<p><strong>3)定时任务补偿</strong></p>
<p>用得较多,实现最终一致,分为加数据补偿,删数据补偿两种。</p>
<p>&nbsp;</p>
<h3 id='3-3-3-3-应用拆分后稳定性怎么保证'  id="boomdevs_17" >3-3. 3.3 应用拆分后稳定性怎么保证?</h3>
<p><strong>一句话:怀疑第三方</strong>,<strong>防备使用方</strong>,<strong>做好自己!</strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>1</strong><strong>)怀疑第三方</strong><strong><br />
</strong></p>
<p>a)防御式编程,制定好各种降级策略;</p>
<ul>
<li>比如缓存主备、推拉结合、本地缓存……</li>
</ul>
<p>b)遵循快速失败原则,一定要设置超时时间,并异常捕获;</p>
<p>c)强依赖转弱依赖,旁支逻辑异步化</p>
<ul>
<li>我们对某一个核心应用的旁支逻辑异步化后,响应时间几乎缩短了1/3,且后面中间件、其它应用等都出现过抖动情况,而核心链路一切正常;</li>
</ul>
<p>d)适当保护第三方,慎重选择重试机制</p>
<p><strong>2</strong><strong>)防备使用方</strong></p>
<p>a)设计一个好的接口,避免误用</p>
<ul>
<li>遵循接口最少暴露原则;很多同学搭建完新应用后会随手暴露很多接口,而这些接口由于没人使用而缺乏维护,很容易给以后挖坑。听到过不只一次对话,”你怎么用我这个接口啊,当时随便写的,性能很差的“;</li>
<li>不要让使用方做接口可以做的事情;比如你只暴露一个getMsgById接口,别人如果想批量调用的话,可能就直接for循环rpc调用,如果提供getMsgListByIdList接口就不会出现这种情况了。</li>
<li>避免长时间执行的接口;特别是一些老系统,一个接口背后对应的可能是for循环select DB的场景。</li>
<li><strong>…</strong></li>
</ul>
<p>b)容量限制</p>
<ul>
<li>按应用优先级进行流控;不仅有总流量限流,还要区分应用,比如核心应用的配额肯定比非核心应用配额高;</li>
<li>业务容量控制。有些时候不仅仅是系统层面的限制,业务层面也需要限制。举个例子,对saas化的一些系统来说,”你这个租户最多1w人使用“。</li>
</ul>
<p><strong>3</strong><strong>)做好自己</strong></p>
<p>a)<strong>单一职责</strong></p>
<p>b)<strong>及时清理历史坑</strong></p>
<ul>
<li>例:例如我们改造时候发现一年前留下的坑,去掉后整个集群cpu使用率下降1/3</li>
</ul>
<p>c) <strong>运维SOP</strong><strong>化</strong></p>
<ul>
<li>说实话,线上出现问题,如果没有预案,再怎么处理都会超时。曾经遇到过一次DB故障导致脏数据问题,最终只能硬着头皮写代码来清理脏数据,但是时间很长,只能眼睁睁看着故障不断升级。经历过这个事情后,我们马上设想出现脏数据的各种场景,然后上线了三个清理脏数据的job,以防其它不可预知的产生脏数据的故障场景,以后只要遇到出现脏数据的故障,直接触发这三个清理job,先恢复再排查。</li>
</ul>
<p>d)<strong>资源使用可预测</strong></p>
<ul>
<li>应用的cpu、内存、网络、磁盘心中有数
<ul>
<li>正则匹配耗cpu</li>
<li>耗性能的job优化、降级、下线(循环调用rpc或sql)</li>
<li>慢sql优化、降级、限流</li>
<li>tair/redis、db调用量要可预测</li>
<li>例:tair、db</li>
</ul>
</li>
</ul>
<p>举个例子: 某一个接口类似于秒杀功能,qps非常高(如下图所示),请求先到tair,如果找不到会回源到DB,当请求突增时候,甚至会触发tair/redis这层缓存的限流,此外由于缓存在一开始是没数据的,请求会穿透到db,从而击垮db。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218190751511-799069731.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7190" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218190751511-799069731.png" alt="" width="914" height="301" /></a></p>
<p>这里的核心问题就是tair/redis这层资源的使用不可预测,因为依赖于接口的qps,怎么让请求变得可预测呢?</p>
<p>如果我们再增加一层本地缓存(guava,比如超时时间设置为1秒),保证单机对一个key只有一个请求回源,那样对tair/redis这层资源的使用就可以预知了。假设有500台client,对一个key来说,一瞬间最多500个请求穿透到Tair/redis,以此类推到db。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218191031183-757748009.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7191" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218191031183-757748009.png" alt="" width="893" height="193" /></a></p>
<p>再举个例子:</p>
<p>比如client有500台,对某key一瞬间最多有500个请求穿透到db,如果key有10个,那么请求最多可能有5000个到db,恰好这些sql的RT有些高,怎么保护DB的资源?</p>
<p>可以通过一个定时程序不断将数据从db刷到缓存。这里就将不可控的5000个qps的db访问变为可控的个位数qps的db访问。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218191224511-890757132.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7192" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/522490-20161218191224511-890757132.png" alt="" width="832" height="335" /></a></p>
<h2 id='4-4-总结'  id="boomdevs_18" >4. 4  总结</h2>
<p><strong>1</strong><strong>)做好准备面对压力!</strong></p>
<p><strong>2</strong><strong>)复杂问题要拆解为多步骤,每一步可测试可回滚!</strong></p>
<p>这是应用拆分过程中的最有价值的实践经验!</p>
<p><strong>3</strong><strong>)墨菲定律:你所担心的事情一定会发生,而且会很快发生,所以准备好你的SOP</strong><strong>(标准化解决方案)!</strong></p>
<p>某个周五和组里同事吃饭时讨论到某一个功能存在风险,约定在下周解决,结果周一刚上班该功能就出现故障了。以前讲小概率不可能发生,但是概率再小也是有值的,比如p=0.00001%,互联网环境下,请求量足够大,小概率事件就真发生了。</p>
<p><strong>4</strong><strong>)借假修真</strong></p>
<p>这个词看上去有点玄乎,顾名思义,就是在借者一些事情,来提升另外一种能力,前者称为假,后者称为真。在任何一个单位,对核心系统进行大规模拆分改造的机会很少,因此一旦你承担起责任,就毫不犹豫地全力以赴吧!不要被过程的曲折所吓倒,心智的磨砺,才是本真。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="https://www.cnblogs.com/LBSer/p/6195309.html">一个复杂系统的拆分改造实践</a></p>The post <a href="http://www.mobabel.net/%e8%bd%ac%e4%b8%80%e4%b8%aa%e5%a4%8d%e6%9d%82%e7%b3%bb%e7%bb%9f%e7%9a%84%e6%8b%86%e5%88%86%e6%94%b9%e9%80%a0%e5%ae%9e%e8%b7%b5/">[转]一个复杂系统的拆分改造实践</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e8%bd%ac%e4%b8%80%e4%b8%aa%e5%a4%8d%e6%9d%82%e7%b3%bb%e7%bb%9f%e7%9a%84%e6%8b%86%e5%88%86%e6%94%b9%e9%80%a0%e5%ae%9e%e8%b7%b5/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[转]聊聊遗留系统改造的“道”与“术”</title>
		<link>http://www.mobabel.net/%e8%bd%ac%e8%81%8a%e8%81%8a%e9%81%97%e7%95%99%e7%b3%bb%e7%bb%9f%e6%94%b9%e9%80%a0%e7%9a%84%e9%81%93%e4%b8%8e%e6%9c%af/</link>
					<comments>http://www.mobabel.net/%e8%bd%ac%e8%81%8a%e8%81%8a%e9%81%97%e7%95%99%e7%b3%bb%e7%bb%9f%e6%94%b9%e9%80%a0%e7%9a%84%e9%81%93%e4%b8%8e%e6%9c%af/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Fri, 04 Jun 2021 17:59:31 +0000</pubDate>
				<category><![CDATA[Collection]]></category>
		<category><![CDATA[Architecture]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=7173</guid>

					<description><![CDATA[<p>让我们面对现实吧,我们今天所做的一切就是在编写明天的遗留系统。—— Martin Fowler 什么是遗留系统(Legacy System)?根据维基百科的定义,遗留系统是一种旧的方法、旧的技术、旧的计算机系统或应用程序,“属于或与以前的、过时的计算机系统有关” ,但仍在使用中。通常,将系统称为“遗留系统”意味着它可能已经过时或需要更换。 遗留系统改造是程序员的宿命,因为软件永远没有完成的时候。公司的业务始终在变化,软件架构和代码也只能随之不断变化,在数字化时代,这种变化更快了。 据 IEEE 报道,自 2010 年以来,全世界的公司和政府在 IT 产品和服务上的支出估计为 35 万亿美元。其中,约四分之三用于运营和维护现有的 IT 系统。至少有 2.5 万亿美元用于尝试替换旧的 IT 系统,其中约有 7200 亿美元被浪费在失败的替换工作上。 遗留系统改造和替换是一个高风险操作,开发人员应该如何对遗留系统改造做风险评估?需要遵循哪些改造原则?重构还是重写,应该怎么选择?在近日举行的 2021 ThoughtWorks 技术雷达峰会上,ThoughtWorks 首席咨询师梅雪松围绕上述话题做了演讲分享,并在演讲后接受了 InfoQ 记者的采访,与我们聊聊他在经历众多改造项目后总结出的遗留系统改造的“道”与“术”。 1. 1微服务不是遗留系统改造的首要选择 虽然当前微服务几乎已经成了软件架构的事实标准,很多开发团队在重新开发系统的时候会把微服务作为默认架构直接使用。但对于很多遗留系统来说,微服务可以作为一个选项,但并不是团队优先要解决的问题。&#46;&#46;&#46;</p>
The post <a href="http://www.mobabel.net/%e8%bd%ac%e8%81%8a%e8%81%8a%e9%81%97%e7%95%99%e7%b3%bb%e7%bb%9f%e6%94%b9%e9%80%a0%e7%9a%84%e9%81%93%e4%b8%8e%e6%9c%af/">[转]聊聊遗留系统改造的“道”与“术”</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<blockquote>
<section>让我们面对现实吧,我们今天所做的一切就是在编写明天的遗留系统。—— Martin Fowler</section>
</blockquote>
<p>什么是遗留系统(Legacy System)?根据维基百科的定义,遗留系统是一种旧的方法、旧的技术、旧的计算机系统或应用程序,“属于或与以前的、过时的计算机系统有关” ,但仍在使用中。通常,将系统称为“遗留系统”意味着它可能已经过时或需要更换。</p>
<p>遗留系统改造是程序员的宿命,因为软件永远没有完成的时候。公司的业务始终在变化,软件架构和代码也只能随之不断变化,在数字化时代,这种变化更快了。</p>
<p><span id="more-7173"></span></p>
<p>据 IEEE 报道,自 2010 年以来,全世界的公司和政府在 IT 产品和服务上的支出估计为 35 万亿美元。其中,约四分之三用于运营和维护现有的 IT 系统。至少有 2.5 万亿美元用于尝试替换旧的 IT 系统,其中约有 7200 亿美元被浪费在失败的替换工作上。</p>
<p>遗留系统改造和替换是一个高风险操作,开发人员应该如何对遗留系统改造做风险评估?需要遵循哪些改造原则?重构还是重写,应该怎么选择?在近日举行的 2021 ThoughtWorks 技术雷达峰会上,ThoughtWorks 首席咨询师梅雪松围绕上述话题做了演讲分享,并在演讲后接受了 InfoQ 记者的采访,与我们聊聊他在经历众多改造项目后总结出的遗留系统改造的“道”与“术”。</p>
<h1 id='1-1微服务不是遗留系统改造的首要选择'  id="boomdevs_1" >1. 1微服务不是遗留系统改造的首要选择</h1>
<p>虽然当前微服务几乎已经成了软件架构的事实标准,很多开发团队在重新开发系统的时候会把微服务作为默认架构直接使用。但对于很多遗留系统来说,微服务可以作为一个选项,但并不是团队优先要解决的问题。</p>
<p>微服务的好处在于能够让不同的模块独立上线和运行,如果享受不到这个好处又付出了微服务改造所需要的成本,就划不来了。对于那些 IT 资产比较重的行业(如金融、保险等),他们的核心系统本身就很难快起来,通常是一批需求一起上线,模块是否能独立上线、独立演进并不太重要,微服务反而还会带来极高的运维复杂度。对于这类核心系统来说,优先级更高的是业务代码解耦,很多系统往往就是因为代码耦合度太高才变得复杂。梅雪松表示,解耦一直是遗留系统改造的重点,10 年前是如此,现在是如此,再过 10 年可能还是如此。虽然“高内聚、低耦合”是大家一直在追求的目标,但实际很难达到。系统开发的第一步必然是先完成业务需求,业务也有 deadline,于是就成了死循环,业务一直在催,IT 只能赶紧干,结果就留下了很多技术债而且没有时间修复,甚至没有意识到要去修复,最终这个系统就变成了遗留系统。</p>
<h1 id='2-2如何启动遗留系统改造'  id="boomdevs_2" >2. 2如何启动遗留系统改造?</h1>
<p>遗留系统改造是一个长期过程,通常会持续很长时间。因此启动改造之前,需要考虑其他相关干系人的诉求,明确改造目标。如果不能得到其他部门的支持,改造工作可能会遇到比较大的挑战。梅雪松建议可以从四个方向寻找目标:</p>
<ol class="list-paddingleft-2">
<li>业务敏捷,能不能让响应力变得更快?</li>
<li>运营效率,如何通过系统改造,提升业务运营的效率?</li>
<li>客户洞见,如何让系统更好地发现客户洞见,进而更好地理解客户需求和演进产品?</li>
<li>系统本身的韧性和弹性,这是在云时代比较典型的诉求。</li>
</ol>
<p>有了明确的改造目标后,还需要制定度量指标,在每个维度上搜集度量数据并可视化出来。这样做的好处,一是能够让团队了解改造进展和成果,确保改造朝着正确的方向走;二是能够将数据透明给相关的干系人,如业务、运营、市场等部门,以获得他们的支持。</p>
<h1 id='3-3遗留系统现代化改造的三个原则'  id="boomdevs_3" >3. 3遗留系统现代化改造的三个原则</h1>
<p>如前文所述,遗留系统改造是一项高风险工作,失败率高达三分之一。那是什么原因让遗留系统改造获得了成功?又有哪些因素导致遗留系统改造最终失败?借鉴 Neal Ford《演进式架构》一书的内容,梅雪松总结了遗留系统现代化改造的三个原则,这些原则在遗留系统改造中可以作为指导思想使用。</p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/2021-6-4-17-57-31.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7174" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/2021-6-4-17-57-31.png" alt="" width="672" height="288" srcset="http://www.mobabel.net/wp-content/uploads/2021/06/04/2021-6-4-17-57-31.png 672w, http://www.mobabel.net/wp-content/uploads/2021/06/04/2021-6-4-17-57-31-300x129.png 300w" sizes="(max-width: 672px) 100vw, 672px" /></a></p>
<p>第一个原则是要把演进能力作为一种架构特征。架构有很多特征,比如安全性、可靠性、应用性等等。既然业务一直在变化,代码需要一直演进,那就应该把演进的能力作为一种架构特征,在设计架构时需要考虑到这一点。</p>
<p>第二个原则是以适应度函数来牵引架构的演进。软件开发是一个社会化的过程,所以架构的演进以及维护需要团队来做,但团队很难自发去做这项工作,需要有一个东西来牵引着他们,并评估每一次的演进到底变得更好还是变得更坏了,这就是适应度函数。比如如果以架构分层为设计原则之一,就可以定义一个分层的适应度函数,然后把它变成一个测试放到 CI 上持续运行。</p>
<p>第三个原则是以增量变更作为架构演进的单元,这是在实操层面最重要的一个原则。很多失败的遗留系统改造案例几乎都有一个同样的特点,就是步子迈得太大了,有的直接就重新开发,甚至连数据库都变了,这种情况的风险显然是非常大的。如果在改造一个遗留系统的时候,不能分阶段地上线、迁移、切换,而是等到最后一刻才最终上线切换的话,风险可能就爆表了。如果能以增量变更的方式来做改造,每个增量都能够回滚,这种改造基本上风险是可控的。</p>
<h1 id='4-4重构不如小范围重写'  id="boomdevs_4" >4. 4重构不如小范围重写</h1>
<p>遗留系统改造有五种常见策略,分别是封装(Encapsulate)、平台切换(Replatform)、迁移(Rehost)、重构(Refactoring/Re-architecing)、重新开发(Rebulid/Replace)。</p>
<h1 id='5'  id="boomdevs_5" >5. <a href="http://www.mobabel.net/wp-content/uploads/2021/06/04/2021-6-4-17-58-31.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7175" src="http://www.mobabel.net/wp-content/uploads/2021/06/04/2021-6-4-17-58-31.png" alt="" width="639" height="353" srcset="http://www.mobabel.net/wp-content/uploads/2021/06/04/2021-6-4-17-58-31.png 639w, http://www.mobabel.net/wp-content/uploads/2021/06/04/2021-6-4-17-58-31-300x166.png 300w" sizes="(max-width: 639px) 100vw, 639px" /></a></h1>
<p>选择策略的时候,需要考虑对应的风险、收益和成本。如上图所示,封装的风险是最小的,收益也比较小,但是成本也很低。重构和重新开发的收益都比较大,但是成本也比较高,其中重新开发的风险是最高的。梅雪松强调,这些策略作用的颗粒度并不是整个系统,而可能是在很小的模块上,并且这些策略可以组合使用而非单独只选择某一个策略。</p>
<p>那对于遗留系统改造来说,重构和重新开发哪一个是更好的选择?</p>
<p>梅雪松表示,随着经历的客户改造案例越来越多,他的想法也在发生变化。最早的时候,他认为只要具备足够强的能力,重构比重写更安全,但后来他发现,很多老旧的业务系统代码质量非常糟糕,几乎可以说是“一次性”代码,并没有什么重构的价值,不如直接重写。在他看来,理解业务后再重写,其实是比较安全的,复杂的是本身不了解业务、代码又写得很乱,这时候通过代码对照去了解业务反而难上加难。当然,保证重写安全性的前提是,不能整个系统大范围地重写,而是要一小块一小块去重写。</p>
<p>但重构并非没有价值。梅雪松认为,在应对很多老代码的时候重构价值不大,但重构这个能力对于工程师来说依然非常重要。即便是开发新需求,也是一个不断重构的过程。写代码就像写文章一样,一开始写出来的一定不会是好代码,只有一遍一遍地修改和重构之后才能写出高质量的代码。因此重构并非只是架构师或高级别技术大牛才需要关注的事情,而是所有开发人员都应该具备的最基本技能。</p>
<p>&nbsp;</p>
<section>作者 | 蔡芳芳</section>
<section>采访嘉宾 | 梅雪松</section>
<p>&nbsp;</p>
<p><a href="https://mp.weixin.qq.com/s/GTyQZy3NZQgZkvT0XRbdyA">聊聊遗留系统改造的“道”与“术”</a></p>The post <a href="http://www.mobabel.net/%e8%bd%ac%e8%81%8a%e8%81%8a%e9%81%97%e7%95%99%e7%b3%bb%e7%bb%9f%e6%94%b9%e9%80%a0%e7%9a%84%e9%81%93%e4%b8%8e%e6%9c%af/">[转]聊聊遗留系统改造的“道”与“术”</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e8%bd%ac%e8%81%8a%e8%81%8a%e9%81%97%e7%95%99%e7%b3%bb%e7%bb%9f%e6%94%b9%e9%80%a0%e7%9a%84%e9%81%93%e4%b8%8e%e6%9c%af/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[汇总]构架经验</title>
		<link>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%9e%84%e6%9e%b6%e7%bb%8f%e9%aa%8c/</link>
					<comments>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%9e%84%e6%9e%b6%e7%bb%8f%e9%aa%8c/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Sun, 02 May 2021 23:40:57 +0000</pubDate>
				<category><![CDATA[Collection]]></category>
		<category><![CDATA[Software Architecture]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=6716</guid>

					<description><![CDATA[<p>1. 架构师思维 IT 生涯 &#124; 像架构师一样去思考 架构师角色的演变:从发号施令到与团队合作[好文] 康威定律的影响是一个关键主题:系统的架构反映了组织的结构。 “为什么”这样的提问方式带有评判的味道,例如,“你为什么要采取这种方法”。如果将问题改为“是什么让你决定采用这种方法”,会促使被问者解释他们的想法,而不是为他们的决定辩护,因为当被问及“为什么”时,他们可能会认为自己的决定是不是不正确的。 给架构师: 成为帮助团队架构理解的导师,而不是障碍。公开主动地分享你的知识。 为那些只有你自己感觉到但团队可能没有意识到的挑战寻求指导,来帮助你克服内心的挑战。不要独自承受,支持性的指导有助于你的角色演化。 欢迎来自客户、团队和环境的挑战。这种反馈循环可能会让人感到筋疲力尽,但可以带来巨大的回报。 用你的经验将对话引向你的专业知识告诉你会遇到的挑战。 了解团队的动态、他们的优缺点、他们对工具的掌握,以及他们日复一日地构建应用程序的实际情况。帮助你在正确的时间组织你的输入,在哪里可以带来最大的价值。 成为人际关系的建设者。培养你的软技能,建立起人际网络,从销售团队到产品负责人,从工程经理到技术中小企业。每天都要培养和维护这些关系。 给团队: 为非领域专家总结使用工具的经验,带他们踏上理解之旅。 利用架构师丰富的经验来洞察你可能有的想法、挑战或主意。他们现在是你团队的一员了。 简单明了地表达你的想法、优点和缺点,准备好接受开放性和有挑战性的反馈,构建心理安全感。 把头衔和自负留在门外,拥抱团队环境,向团队里的每一个人学习。在当今的软件设计当中,你对设计过程的影响是真实存在的。 培养你的演讲、沟通和指导技能,并每天使用它们,在快节奏的团队中进行信息交流是至关重要的。 尽你所能留住你的架构师。他们深厚的专业知识对团队的成长和壮大是无价的,不要让他们感到孤立,让他们觉得自己是团队的一部分,是未来解决方案的一部分。 &#160; &#160; 十四年架构师揭秘:要做架构师先要在鸟群中做好鸟 我是如何在阿里做“架构师”的? 我们还需要架构师吗?还需要架构部门吗?我给出的答案是:不需要,因为每个人都应该是架构师。 阿里技术大牛:一份架构师成神路线图! 绝好的的技术整理! 恕我直言,一般像你这种能说会道的技术都不太行 手上有团队,有资源,我要做的是 “找到合适的人,放到合适的位置上”,让每个人发挥各自的所长,而不是我自己再去纠结一些细节。 架构师虽然听起来很高大上,但本质上仍然是工程师,不是忽悠人的江湖骗子。&#46;&#46;&#46;</p>
The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%9e%84%e6%9e%b6%e7%bb%8f%e9%aa%8c/">[汇总]构架经验</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<h1 id='1-架构师思维'  id="boomdevs_1" >1. 架构师思维</h1>
<p><a href="https://mp.weixin.qq.com/s/x3UgS6WFKp_Z4DGMLb2xtQ">IT 生涯 | 像架构师一样去思考</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s?__biz=MzIzNjUxMzk2NQ==&amp;mid=2247532232&amp;idx=1&amp;sn=b7d379d7ee16038929e06caac99bd272&amp;chksm=e8d4810adfa3081c3bf6251f89344ad9d54415d1932fb7432408c8a57fb28559bda8eb7f4fa8">架构师角色的演变:从发号施令到与团队合作[好文]</a></p>
<blockquote><p>康威定律的影响是一个关键主题:系统的架构反映了组织的结构。</p>
<p>“为什么”这样的提问方式带有评判的味道,例如,“你为什么要采取这种方法”。如果将问题改为“是什么让你决定采用这种方法”,会促使被问者解释他们的想法,而不是为他们的决定辩护,因为当被问及“为什么”时,他们可能会认为自己的决定是不是不正确的。</p></blockquote>
<p>给架构师:</p>
<ol>
<li>成为帮助团队架构理解的导师,而不是障碍。公开主动地分享你的知识。</li>
<li>为那些只有你自己感觉到但团队可能没有意识到的挑战寻求指导,来帮助你克服内心的挑战。不要独自承受,支持性的指导有助于你的角色演化。</li>
<li>欢迎来自客户、团队和环境的挑战。这种反馈循环可能会让人感到筋疲力尽,但可以带来巨大的回报。</li>
<li>用你的经验将对话引向你的专业知识告诉你会遇到的挑战。</li>
<li>了解团队的动态、他们的优缺点、他们对工具的掌握,以及他们日复一日地构建应用程序的实际情况。帮助你在正确的时间组织你的输入,在哪里可以带来最大的价值。</li>
<li>成为人际关系的建设者。培养你的软技能,建立起人际网络,从销售团队到产品负责人,从工程经理到技术中小企业。每天都要培养和维护这些关系。</li>
</ol>
<p>给团队:</p>
<ol>
<li>为非领域专家总结使用工具的经验,带他们踏上理解之旅。</li>
<li>利用架构师丰富的经验来洞察你可能有的想法、挑战或主意。他们现在是你团队的一员了。</li>
<li>简单明了地表达你的想法、优点和缺点,准备好接受开放性和有挑战性的反馈,构建心理安全感。</li>
<li>把头衔和自负留在门外,拥抱团队环境,向团队里的每一个人学习。在当今的软件设计当中,你对设计过程的影响是真实存在的。</li>
<li>培养你的演讲、沟通和指导技能,并每天使用它们,在快节奏的团队中进行信息交流是至关重要的。</li>
<li>尽你所能留住你的架构师。他们深厚的专业知识对团队的成长和壮大是无价的,不要让他们感到孤立,让他们觉得自己是团队的一部分,是未来解决方案的一部分。</li>
</ol>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="https://mp.weixin.qq.com/s/ZJr93_0IHocTFC3497NvyA">十四年架构师揭秘:要做架构师先要在鸟群中做好鸟</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/jA73TaLqViygPvRL-YTX7g">我是如何在阿里做“架构师”的?</a></p>
<blockquote><p>我们还需要架构师吗?还需要架构部门吗?我给出的答案是:不需要,因为每个人都应该是架构师。</p></blockquote>
<p><a href="https://mp.weixin.qq.com/s/X_F_8OfbBDHWcUTPY2THrA">阿里技术大牛:一份架构师成神路线图!</a><br />
绝好的的技术整理!</p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/zbLf24_2AuzFxPowQ2Bz2Q">恕我直言,一般像你这种能说会道的技术都不太行</a></p>
<p>手上有团队,有资源,我要做的是 “找到合适的人,放到合适的位置上”,让每个人发挥各自的所长,而不是我自己再去纠结一些细节。</p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/s0RuTN8saoTR6eMBMqJXYg">架构师虽然听起来很高大上,但本质上仍然是工程师,不是忽悠人的江湖骗子。</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/rY-00ozTOovH31e_z7SQuw">9年当上架构师,我的很多想法变了</a></p>
<blockquote><p>架构师的职责与技术负责人的目标有所不同。这两个角色虽然有很多重合之处,侧重点却大相径庭。架构师需要转换思维——积极分配时间进行咨询(沿着各个“电梯”层),着眼于一年、两年或三年之后的情况,并且清楚地把它阐述出来,以让每个人都在同一个轨道上前行。</p></blockquote>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/tNwnpdMakRrIQt_5EOZ3uA">概念澄清 | 企业架构规划能细化到开发说明书,拿着就能写代码吗?</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/vDI9WaPea7afIHjkzzfSCA">软件架构可能不是你想象的那个样子</a></p>
<ul>
<li>软件架构关乎决策,而非结构</li>
<li>架构是一项技能,但架构师不是一种角色</li>
<li>架构意味着持续探索</li>
</ul>
<p><a href="https://mp.weixin.qq.com/s/1L1ssWlvZwm6anAsg79h6w">“通才架构师”的消亡:从无到有,再到上百万个框架</a></p>
<p><a href="https://mp.weixin.qq.com/s/mPY9Yq8H_KOf8B2Bn_0hIw">架构师眼中的文化:试用期才是真正的考察时间</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/E2NaShR70trfNA0y0FT8uQ">架构的腐化是必然的!</a></p>
<blockquote><p>即使能有合理的流程,从外部招到公司的“架构师”很多也只不过只是工龄长罢了,言必谈 DDD,中台,战略,一到了落地环节提不出合理的见解和建议。也有挂着架构师的头衔,实际上却是个“管理专家”,在催进度上更在行。</p></blockquote>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/MUDbKPOFDR4OuHDHUOI9Kw">构建软件最难的不是编码,而是需求</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1 id='2-构架理论'  id="boomdevs_2" >2. 构架理论</h1>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/pknm-gLXUnmPgYFW39R38g">一文看懂:什么是业务架构、数据架构、应用架构和技术架构</a><br />
<strong>企业数字化架构设计中的最常见要素,4A架构。</strong></p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/05/02/Snipaste_2024-06-02_20-00-39.jpg"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-8521" src="http://www.mobabel.net/wp-content/uploads/2021/05/02/Snipaste_2024-06-02_20-00-39.jpg" alt="" width="904" height="681" srcset="http://www.mobabel.net/wp-content/uploads/2021/05/02/Snipaste_2024-06-02_20-00-39.jpg 904w, http://www.mobabel.net/wp-content/uploads/2021/05/02/Snipaste_2024-06-02_20-00-39-300x226.jpg 300w, http://www.mobabel.net/wp-content/uploads/2021/05/02/Snipaste_2024-06-02_20-00-39-768x579.jpg 768w" sizes="(max-width: 904px) 100vw, 904px" /></a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/UWQD_llCBsF1zWYtoaKH2w">业务架构建模8步法指南及其成功关键要素</a></p>
<p>&nbsp;</p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/nux9xJko6N1tLTK23-ZbzA">“行业毒瘤”低代码</a></p>
<p><a href="https://mp.weixin.qq.com/s/eMWS5FrG4txcoBDMEURP0w">作为现代开发的基础,为什么TDD没有被广泛采用?</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/AhklSNwD1UzHv0hCGNMcVg">拥抱毒瘤 DDD!</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/9H4U7xHt3s2hzsWv1_8LJQ">一看就懂的 DDD 领域划分与架构设计!</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/re-sbQHapqxVyaVmi453Kw">MVC转DDD构架</a></p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/05/02/WeChat-Image_20220606175533.jpg"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-7537" src="http://www.mobabel.net/wp-content/uploads/2021/05/02/WeChat-Image_20220606175533.jpg" alt="" width="1080" height="806" srcset="http://www.mobabel.net/wp-content/uploads/2021/05/02/WeChat-Image_20220606175533.jpg 1080w, http://www.mobabel.net/wp-content/uploads/2021/05/02/WeChat-Image_20220606175533-300x224.jpg 300w, http://www.mobabel.net/wp-content/uploads/2021/05/02/WeChat-Image_20220606175533-1024x764.jpg 1024w, http://www.mobabel.net/wp-content/uploads/2021/05/02/WeChat-Image_20220606175533-768x573.jpg 768w" sizes="(max-width: 1080px) 100vw, 1080px" /></a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/bXQdk-3dBd586r48DN4YGw">敏捷“杀死”统一建模语言?</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/_6B737Ubt-vVZ5ZNTU3VyA">阿里工程师教你 3 分钟实现数据源编排和接入</a></p>
<p><strong class="mr-2 flex-self-stretch"><a href="https://github.com/donnemartin/system-design-primer" data-pjax="#js-repo-pjax-container">system-design-primer</a></strong></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/cWHK76mDRXh5G4_nIBZHzA">软件架构设计分层模型和构图思考</a> 各种方案的顶层构架</p>
<ul>
<li>云平台三层架构:资源-平台-应用</li>
<li>SOA分层:组件-服务-流程</li>
<li>云和SOA架构融合</li>
<li>应用架构分层</li>
<li>软件技术架构分层</li>
<li>单个应用功能架构</li>
<li>架构图的分层构图逻辑<br />
<section data-mid=""></section>
</li>
</ul>
<p><a href="https://mp.weixin.qq.com/s/V80b_Ba1LO0qeq9mR2mi2w">《数据密集型应用系统设计》<strong>《Designing Data-Intensive Application》</strong></a></p>
<p>这本书的主要讲了分布式数据库、数据分区、事务、分布式系统等内容。从数据模型与查询语言,数据编码到数据复制和分区,再到事务,一致性共识,分布式系统面临的一些挑战(如故障与部分失效、不可靠网络和时钟),作者都结合实例提供了有深度的讲解,在工业与学术之间平衡的很好。</p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/yzo7WXYzLcnaoc70r3I6nA">如何画出一张优秀的架构图</a></p>
<p><a href="https://hilton.org.uk/blog/zero-bug-policy">https://hilton.org.uk/blog/zero-bug-policy</a></p>
<p><a href="https://12factor.net/">https://12factor.net/</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/xbAgKjOqqdZrot09fC5bzQ">如何认识 IT项目的差异化价值</a></p>
<blockquote><p>作为IT咨询顾问,我经常被客户领导询问:“你们的这个解决方案,和其他家不同在哪里?”</p>
<p>作为咨询公司的工作者,我也经常被同事们提醒:“我们要讲出来我们的方案和其他竞争对手不同在哪里,我们的价值点、卖点究竟是什么?”</p>
<p>面对这些问题,我有时候感觉挺无语——因为财务、人力资源、供应链、研发等等企业运营管理的IT解决方案的课题,在我来看基本原理都是一样的,企业间并没有那么大的差异,甚至跨行业的差异性都不大;企业级IT系统在很大程度上,是企业共性能力的数字化抽象。</p>
<p>要是一个企业的这类IT系统的实施结果,跟其他家做得不一样,倒是真有问题了。</p></blockquote>
<p><strong>满分的答案都一样,学渣的考卷才百花齐放</strong></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/13QgNN8HRlDlpD2gXvmuwQ">IT咨询项目,甲方该怎样和咨询公司合作</a></p>
<p><a href="http://www.mobabel.net/wp-content/uploads/2021/05/02/WeChat-Image_20221211144048.png"><img loading="lazy" decoding="async" class="alignnone wp-image-7880" src="http://www.mobabel.net/wp-content/uploads/2021/05/02/WeChat-Image_20221211144048.png" alt="" width="298" height="218" /></a></p>
<p id="activity-name" class="rich_media_title ">什么?代码审查存在缺陷?我带你搞定它!</p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/UJmgMYq2x9w_Dukn0lbiyQ">GDPR巨额罚款震撼全球,聊聊隐私安全建设思路与实践</a></p>
<p>&nbsp;</p>
<h1 id='3-最佳实践'  id="boomdevs_3" >3. 最佳实践</h1>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/UTBRZ1H0ZgDQokMUZ4h7rg">阿里腾讯程序员写的代码就比别人好?你不知道大厂们操碎了多少心</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/g2QdvsrZuIWJHrt5pNv6Zw">来自Airbnb、Netflix等公司的代码评审最佳实践</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/fQb45nLtc1zEAQAfl8hS9A">25种代码坏味道总结+优化示例</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/yfUQDz3wK-jdJdLa5IbsdQ">还重构?就这代码只能铲了重写!</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/rRNfQ8x0xNMMeM_mK5ZuSA">WhatsApp 50名工程师支撑着一个10亿用户量的产品:成功因素之一是几乎不开会</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/2yam7vPpkwQ4oDD1iJnd3g">来自谷歌的开发心得:所有SQL和代码,都没必要藏着掖着</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/odjAsFc5kWEbU_LdrI-J2A">一个人如何完成一家创业公司的技术架构?</a></p>
<blockquote><p>德国公司Panelbear的云构架,很多有用的建议,非常细节。</p></blockquote>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/girCm2QlDF6Y-ufohhgMcQ">让小型企业提高 20 倍效率的统一技术栈</a></p>
<blockquote><p>技术栈帮助 Atmos 在只有 1-2 名全职工程师的情况下,发展到 1 万多个客户</p></blockquote>
<p><a href="https://mp.weixin.qq.com/s/2dlIrdskHJcLMmtY2XCzFg">瑞阳的智造实践:从单个车间试点到全面智能车间建设</a></p>
<p>&nbsp;</p>
<h1 id='4-最差实践'  id="boomdevs_4" >4. 最差实践</h1>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/L2hviITn-MgKGWzyUdXSjg">阿里研究员:警惕软件复杂度困局</a></p>
<p>大 型软件设计和实现的本质是大量的工程师相互通过“写作”来交流一些包含丰富细节的抽象概念并且相互不断迭代的过程[2]。稍有差错,系统复杂度就会失控。</p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/bOjRS4YaDYG6vYHGjENxPg">造成重大宕机事故:这15招,屡试不爽</a></p>
<p>也是德企常见问题</p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/Ir45U0RiYa22-9LoCwr5XQ">如何搭建一个拖垮公司的技术架构?</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/ELi14uk_aLjexnw4Z_bZ2Q">一次线上事故,我顿悟了异步的精髓</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/3iTZNFVmdbSC5GWbo-CtEA">凉凉,老板叫我开发一个简单的工作流引擎</a></p>
<p><a href="https://mp.weixin.qq.com/s/4q6ALGVzgK_JE411dHR02A">代码为王的时代:车企如何掌握卓越软件开发能力 麦肯锡</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/pVU5E2GnJVr2XwhzsM828g">传统车企「大逃杀」:缺人,缺合适的人</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/-V-fkr8IMTA2_mmCojel6Q">为什么欧洲的软件发展不行?</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/5pBRlrl22bTlpPZ-H0cTzg">软件正在吞噬汽车,传统汽车业面临淘汰?</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/KRNdnzAelPHhqRuvcVo61g">通用电气在平台工程上浪费70亿美元的教训</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/udt-LB67BZ8EGrwWE9ouXg">LinkedIn十几年积累的 300 万行代码,领导要全部“快速”重写,我直接辞职了</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1 id='5-顾问'  id="boomdevs_5" >5. 顾问</h1>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/Wl4_RZMLWRcMpT7W05qjpQ">花200万请顾问的老板们,现在怎么样了?</a></p>The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%9e%84%e6%9e%b6%e7%bb%8f%e9%aa%8c/">[汇总]构架经验</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e6%9e%84%e6%9e%b6%e7%bb%8f%e9%aa%8c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[汇总]Git经验</title>
		<link>http://www.mobabel.net/%e6%b1%87%e6%80%bbgit%e7%bb%8f%e9%aa%8c/</link>
					<comments>http://www.mobabel.net/%e6%b1%87%e6%80%bbgit%e7%bb%8f%e9%aa%8c/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Fri, 03 Apr 2020 16:32:53 +0000</pubDate>
				<category><![CDATA[Collection]]></category>
		<category><![CDATA[Git]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=6252</guid>

					<description><![CDATA[<p>别再推荐Git Flow了 10个节省时间和改善工作流的Git技巧 小姐姐用动图展示 10 个 Git 命令</p>
The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bbgit%e7%bb%8f%e9%aa%8c/">[汇总]Git经验</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/9M3sgkFpr9sIJYY5kQ71Dg">别再推荐Git Flow了</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/nDlZDEF4crpqByB9kzMBjg">10个节省时间和改善工作流的Git技巧</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/cSaTdFfrc_u7YPmgFdYdAQ">小姐姐用动图展示 10 个 Git 命令</a></p>The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bbgit%e7%bb%8f%e9%aa%8c/">[汇总]Git经验</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e6%b1%87%e6%80%bbgit%e7%bb%8f%e9%aa%8c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[汇总]中国工业相关</title>
		<link>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e4%b8%ad%e5%9b%bd%e5%b7%a5%e4%b8%9a%e7%9b%b8%e5%85%b3/</link>
					<comments>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e4%b8%ad%e5%9b%bd%e5%b7%a5%e4%b8%9a%e7%9b%b8%e5%85%b3/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Sun, 01 Sep 2019 20:26:13 +0000</pubDate>
				<category><![CDATA[Industry 4.0]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=5967</guid>

					<description><![CDATA[<p>“不就是一卖机床的吗?” &#124; 甲子光年 截止2018底,我国已有269个工业互联网平台——超过世界所有其他国家的总和[1]。 在消费互联网时代,评判一家互联网公司的价值尺度是MAU(月活跃用户数),而工业互联网公司的价值在于能为工业企业带来多大的ROI(投资回报率),工业企业会以ROI来决定会不会付费。 MES项目失败归因 谷俊丽:一万字解答ADAS系统的今天和未来 上海市发布推动工业互联网创新升级行动计划 揭秘618:一场横跨十年的“供应链战争” 生不出孩子怪天气?驳《我国工业软件失去的30年》 互联网下半场,产业数字化为什么那么难? 全球企业信息系统实施服务商哪家强 中国制造2025和工业互联网(一) 中国制造的隐痛:传感器之殇 2021,和工业4.0说拜拜 如果中国重新开发像MATLAB这样的软件大概需要多久? 企业如何走向下一代ERP(Next Gen ERP) 观察者网专访果总 | 华为投入近百亿才换掉甲骨文ERP,为什么这么难?</p>
The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bb%e4%b8%ad%e5%9b%bd%e5%b7%a5%e4%b8%9a%e7%9b%b8%e5%85%b3/">[汇总]中国工业相关</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/9_YpVQw_zPQdwWLKi0VCkg">“不就是一卖机床的吗?” | 甲子光年</a><br />
截止2018底,<strong>我国已有269个工业互联网平台——超过世界所有其他国家的总和</strong><strong>[1]</strong>。</p>
<p>在消费互联网时代,评判一家互联网公司的价值尺度是MAU(月活跃用户数),而工业互联网公司的价值在于能为工业企业带来多大的<strong>ROI(投资回报率)</strong>,工业企业会以ROI来决定会不会付费。</p>
<p><span id="more-5967"></span></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/xgikDoXAnFQOfE99avBcAQ">MES项目失败归因</a></p>
<p><a href="https://mp.weixin.qq.com/s/WSEhkSkWn0cSxJNY9hjHyA">谷俊丽:一万字解答ADAS系统的今天和未来</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/zV_ngCAWlWcDivT5fF2zIg">上海市发布推动工业互联网创新升级行动计划</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/gxbzaBXuTR35op3vsiWpFg">揭秘618:一场横跨十年的“供应链战争”</a></p>
<p id="activity-name" class="rich_media_title"><a href="http://mp.weixin.qq.com/s?__biz=MzUxMDYzMjU1Mw==&amp;mid=2247489321&amp;idx=1&amp;sn=a35cc8b077936c809f91fd60d23c5478&amp;chksm=f97ea02fce092939129362255994193ae03415de3daec427ccca39906d32590232a1f8a5d2bb&amp;mpshare=1&amp;scene=24&amp;srcid=&amp;sharer_sharetime=1592174282911&amp;sharer_shareid=fe7c7ea5b68ab5b8e3f569204da103c4#rd">生不出孩子怪天气?驳《我国工业软件失去的30年》</a></p>
<p id="activity-name" class="rich_media_title"><a href="http://mp.weixin.qq.com/s?__biz=MzA4NTU2MTg3MQ==&amp;mid=2655173093&amp;idx=1&amp;sn=b4408db96ce8dfacc922bd3ddaef49aa&amp;chksm=84601e85b31797934ce0df8a6335c85a3e167f22999caac30ba8883d092c06f4d58c4c05ee60&amp;mpshare=1&amp;scene=24&amp;srcid=&amp;sharer_sharetime=1590039590478&amp;sharer_shareid=fe7c7ea5b68ab5b8e3f569204da103c4#rd">互联网下半场,产业数字化为什么那么难?</a></p>
<p id="activity-name" class="rich_media_title"><a href="http://mp.weixin.qq.com/s?__biz=MzI5MzMzODE5MQ==&amp;mid=2247487983&amp;idx=1&amp;sn=9b6d8338ae4ae877afa484b89c00f29d&amp;chksm=ec72fccfdb0575d995d11867e0b9df9dc354ae155dabd8673c70acefa2b10911e9d701b770b2&amp;mpshare=1&amp;scene=24&amp;srcid=&amp;sharer_sharetime=1593007880021&amp;sharer_shareid=fe7c7ea5b68ab5b8e3f569204da103c4#rd">全球企业信息系统实施服务商哪家强</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/QvszycNt6UmQO8gx_lhGmg">中国制造2025和工业互联网(一)</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/5vKW2LGDgHvlghG7AyBQog">中国制造的隐痛:传感器之殇</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/SINmU7S19IaratAL1XDDHQ">2021,和工业4.0说拜拜</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/uqbcDRb_xw2ESrxnRzWaxg">如果中国重新开发像MATLAB这样的软件大概需要多久?</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/rF0XcIXnD6y7pHiGdFeWuQ">企业如何走向下一代ERP(Next Gen ERP)</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/kN2lzmK5UnC_mPfxgfrYMg">观察者网专访果总 | 华为投入近百亿才换掉甲骨文ERP,为什么这么难?</a></p>The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bb%e4%b8%ad%e5%9b%bd%e5%b7%a5%e4%b8%9a%e7%9b%b8%e5%85%b3/">[汇总]中国工业相关</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e6%b1%87%e6%80%bb%e4%b8%ad%e5%9b%bd%e5%b7%a5%e4%b8%9a%e7%9b%b8%e5%85%b3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[汇总]IDEA技巧</title>
		<link>http://www.mobabel.net/%e6%b1%87%e6%80%bbidea%e6%8a%80%e5%b7%a7/</link>
					<comments>http://www.mobabel.net/%e6%b1%87%e6%80%bbidea%e6%8a%80%e5%b7%a7/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Thu, 15 Aug 2019 14:59:51 +0000</pubDate>
				<category><![CDATA[Toolchain]]></category>
		<category><![CDATA[IDEA]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=5953</guid>

					<description><![CDATA[<p>整理了一些 IDEA 中比较骚的技巧 一个表达式后按下点号 . ,然后输入一些提示或者在列表中选择一个候选项 IDEA的这八条配置你一定要改 为什么你的Intellij没别人的好用? 这样配置:让你的 IDEA 好用到飞起来 最新版IDEA常用配置指南,打造你的最酷IDE 12 个超燃的 IntelliJ IDEA 插件! 用了这个IntellijIDEA插件以后,我写代码快了10倍! IDEA万能快捷键,你必须知道的17个实用技巧,提升撸码效率! 碰到Maven依赖冲突,想砸电脑?这个IDEA插件必须了解一下.. 是时候扔掉 Postman 了,试试 IntelliJ IDEA 自带的高能神器! 手把手教你如何免费且光荣地使用正版IntelliJ IDEA IntelliJ IDEA 更新后,电脑卡成球,该如何优化? Sonarqube Review代码 IntelliJ&#46;&#46;&#46;</p>
The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bbidea%e6%8a%80%e5%b7%a7/">[汇总]IDEA技巧</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/AJJH8a5cLbXJhb5UAcEiCg">整理了一些 IDEA 中比较骚的技巧</a><br />
一个表达式后按下点号 . ,然后输入一些提示或者在列表中选择一个候选项</p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&amp;mid=2247487906&amp;idx=1&amp;sn=cc26e8de8104705257033407389698f9&amp;chksm=e9c5e813deb261058c73b6d1b479e4128b257c3506ed2a98543cbd0fde47c44d1917d59bc870&amp;mpshare=1&amp;scene=24&amp;srcid=#rd">IDEA的这八条配置你一定要改</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/b6Nq4nFKqsyrudUJZpNVEg">为什么你的Intellij没别人的好用?</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/XQMpgfHSy6f4_84XrFM0Mg">这样配置:让你的 IDEA 好用到飞起来</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/SJeuBn0xKOL_kWUgYMWUBA">最新版IDEA常用配置指南,打造你的最酷IDE</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/CX5Zm3BO24pcbfHD-zpL1A">12 个超燃的 IntelliJ IDEA 插件!</a></p>
<p id="activity-name" class="rich_media_title "><a href="https://mp.weixin.qq.com/s/fAsZOPItWc_AWOT6YJkG5w">用了这个IntellijIDEA插件以后,我写代码快了10倍!</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/IV08nfcURu4Y0KhcEERT2A">IDEA万能快捷键,你必须知道的17个实用技巧,提升撸码效率!</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/-wT3DWa8_x_E37mJ9FSQnw">碰到Maven依赖冲突,想砸电脑?这个IDEA插件必须了解一下..</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/o6Y1bDcnCt3szORk9vJzLQ">是时候扔掉 Postman 了,试试 IntelliJ IDEA 自带的高能神器!</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/y7cJdbrPn-oD6ko_i_FCag">手把手教你如何免费且光荣地使用正版IntelliJ IDEA</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/grvrSzZfzTqpAYs194PBVQ">IntelliJ IDEA 更新后,电脑卡成球,该如何优化?</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/5Ngw0tgfskRgnwlqvJIAww">Sonarqube Review代码</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/SauiTvwyyTgQkqUSdB2AMQ">IntelliJ IDEA 15款 神级超级牛逼插件推荐(自用,真的超级牛逼)</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/qLQOM-_0E2bQqZNTkuihbw">IDEA 解决 Maven 依赖冲突的高能神器!</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/5se2lSv7MGXEOinGIjNSXw">Intellij IDEA 这样配置注释模板,让你瞬间高出一个逼格!</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/jV6JSRAQKR-BYEQI31tWgQ">IDEA牛逼!900行&#8221;又臭又长&#8221;的类重构,几分钟搞定</a></p>
<p id="activity-name" class="rich_media_title"><a href="https://mp.weixin.qq.com/s/_RVcijCsQakdSMOuA4KJMQ">idea插件PlantUml</a></p>
<p>&nbsp;</p>
<div id="gtx-trans" style="position: absolute; left: -71px; top: 591px;">
<div class="gtx-trans-icon"></div>
</div>The post <a href="http://www.mobabel.net/%e6%b1%87%e6%80%bbidea%e6%8a%80%e5%b7%a7/">[汇总]IDEA技巧</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e6%b1%87%e6%80%bbidea%e6%8a%80%e5%b7%a7/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[转]必备的TCP知识</title>
		<link>http://www.mobabel.net/%e8%bd%ac%e5%bf%85%e5%a4%87%e7%9a%84tcp%e7%9f%a5%e8%af%86/</link>
					<comments>http://www.mobabel.net/%e8%bd%ac%e5%bf%85%e5%a4%87%e7%9a%84tcp%e7%9f%a5%e8%af%86/#respond</comments>
		
		<dc:creator><![CDATA[leelight]]></dc:creator>
		<pubDate>Sat, 15 Jun 2019 21:44:31 +0000</pubDate>
				<category><![CDATA[Protocol Theory]]></category>
		<category><![CDATA[TCP]]></category>
		<guid isPermaLink="false">http://www.mobabel.net/?p=5416</guid>

					<description><![CDATA[<p>&#160; &#160; [source]面试必备的TCP知识,都在这里了!</p>
The post <a href="http://www.mobabel.net/%e8%bd%ac%e5%bf%85%e5%a4%87%e7%9a%84tcp%e7%9f%a5%e8%af%86/">[转]必备的TCP知识</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></description>
										<content:encoded><![CDATA[<p>&nbsp;</p>
<p>&nbsp;</p>
<p>[source]<a href="https://mp.weixin.qq.com/s/HLOMQ6L-0HVFzlF6oncYcA">面试必备的TCP知识,都在这里了!</a></p>The post <a href="http://www.mobabel.net/%e8%bd%ac%e5%bf%85%e5%a4%87%e7%9a%84tcp%e7%9f%a5%e8%af%86/">[转]必备的TCP知识</a> first appeared on <a href="http://www.mobabel.net">Mobabel</a>.]]></content:encoded>
					
					<wfw:commentRss>http://www.mobabel.net/%e8%bd%ac%e5%bf%85%e5%a4%87%e7%9a%84tcp%e7%9f%a5%e8%af%86/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Page Caching using Disk: Enhanced (Requested URI contains query) 

Served from: www.mobabel.net @ 2024-12-04 20:44:12 by W3 Total Cache
-->