<?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>架构 &#8211; 有意与无意之间</title>
	<atom:link href="https://zhangxihai.cn/archives/category/design/feed" rel="self" type="application/rss+xml" />
	<link>https://zhangxihai.cn</link>
	<description>千淘万漉虽辛苦 吹尽狂沙始到金 - 生命不息 编程不止</description>
	<lastBuildDate>Sat, 06 Dec 2025 07:21:09 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.11</generator>
	<item>
		<title>为什么分层架构中会用命令总线和查询总线模式？</title>
		<link>https://zhangxihai.cn/archives/399</link>
					<comments>https://zhangxihai.cn/archives/399#respond</comments>
		
		<dc:creator><![CDATA[胖爷]]></dc:creator>
		<pubDate>Sat, 06 Dec 2025 07:21:09 +0000</pubDate>
				<category><![CDATA[架构]]></category>
		<guid isPermaLink="false">https://zhangxihai.cn/?p=399</guid>

					<description><![CDATA[有个以前小伙伴看我最近开源项目，问我为什么要用命令总线（CommandBus）以及查询总线（QueryBus），感觉非常诡异，它既不是PipeLine，也不提供复杂构造模式，仅仅是为了找到某个处理器，就需要这么复杂的开发范式吗？ 我估计他以前在团队里只是被动强迫使用，疑虑颇多。 其实很简单，使用CommandBus或QueryBus，你首先需要接触到CQRS...]]></description>
										<content:encoded><![CDATA[<p>有个以前小伙伴看我最近开源项目，问我为什么要用命令总线（CommandBus）以及查询总线（QueryBus），感觉非常诡异，它既不是PipeLine，也不提供复杂构造模式，仅仅是为了找到某个处理器，就需要这么复杂的开发范式吗？</p>
<p>我估计他以前在团队里只是被动强迫使用，疑虑颇多。</p>
<p>其实很简单，使用CommandBus或QueryBus，你首先需要接触到CQRS架构模式，即命令查询职责分离。</p>
<p>不管你是否选择面向对象语言，CQRS模式都能帮助你理清复杂业务，减少不同的复杂业务用例之间的相互影响。</p>
<p>但不是所有领域都需要使用CQRS的，尤其像所谓的支撑域（Supporting/Generic）、平台域（Platform）等， 都是复杂度有限的领域。</p>
<p>但是一旦碰到复杂的核心域，采用CQRS就是个很好的选择，这样你就不会被某种单一模型（约定）绑架，可以更灵活的实现复杂用例。</p>
<p>但即使我们采用CQRS，在某个单一的命令处理器中依然不能完成所有工作，复杂度超表。</p>
<p>例如执行购物车下单这个命令， 我们就可能需要进行以下处理：</p>
<ol>
<li>检测库存并锁库存</li>
<li>生成商品快照留痕</li>
<li>创建订单（创建订单和记录商品在同一个约束里）</li>
<li>生成支付订单返回</li>
</ol>
<p>你看看这是一个非常复杂的业务用例，我们不可能在表现层的Controller里完成，或者在RPC框架的Adapter里完成。</p>
<p>那样就太蠢了，中台思想在哪里，解耦在哪里？</p>
<p>所以我们必然会在Application中Services文件夹下创建一个CreateOrderAppService。</p>
<p>但这只是一个门面（Facade），如果你将所有业务逻辑都放在这里，你将违背一个很重要的原则：单一职责。因为你当前的行为，未来你还可能违背开闭原则及接口隔离原则。</p>
<p>所以这个门面我们只能协调大量命令处理器(Handler),协调基础设施共同工作。</p>
<p>这时候你就会发下一些问题：</p>
<ol>
<li>
<p>依赖性问题<br />
你的门面(Facade)依赖了大量Handler, 你能想象你需要注入或者在构造函数中定义超过3个Handler哪有那种场景吗？你会瞬间得到一个“巨大类”, 你的耦合度爆表，你无法自由替换。</p>
</li>
<li>
<p>生命周期问题<br />
如果我们规避第一个问题，从注入改为直接new, 那生命周期就会完全固定，灵活性失去。</p>
</li>
<li>
<p>无法替换Handler<br />
我知道你可能会说我修改接口注入就可以啦，但请问你能实现插件化还有A/B测试这种替换吗？</p>
</li>
<li>
<p>无法实现精准统一的应用级控制<br />
我知道有人在上层用IF/ELSE，有人用一个Abstract，但那样是真的蠢爆了好么？</p>
</li>
</ol>
<p>最后一个问题总线模式是否损耗性能？</p>
<p>在C#或JAVA中，通常通过扫描指定文件夹将命令与处理器的关系，将查询与处理的关系注册到容器，或自定义类型存于内容，又是扫描又是反射，是否会拖慢性能？</p>
<p>这得看情况，因为它有两个阶段：</p>
<p>一个是启动阶段，遍历扫描可能需要5-200ms, 因为I/O（读取元数据）有开销、反射有开销、过滤匹配有开销。</p>
<p>一个是运行时阶段，分发调用的时间几乎可以忽略不计。</p>
<p>所以影响性能只有启动阶段，但这对单体应用基本没什么意义。</p>
<p>对于微服务启动阶段增加二三十毫秒，大部分公司还是能接受的。 </p>
<p>要是超过， 那一定是服务的粒度出问题了。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zhangxihai.cn/archives/399/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>应老板要求设计的DDoS攻击省钱防御方案</title>
		<link>https://zhangxihai.cn/archives/168</link>
					<comments>https://zhangxihai.cn/archives/168#respond</comments>
		
		<dc:creator><![CDATA[胖爷]]></dc:creator>
		<pubDate>Fri, 18 Jun 2021 06:18:08 +0000</pubDate>
				<category><![CDATA[架构]]></category>
		<guid isPermaLink="false">https://zhangxihai.cn/?p=168</guid>

					<description><![CDATA[前段时间公司网站遭受DDOS攻击，瞬间每秒接近30G(其实攻击力度很低啦)的流量涌向主项目的负载均衡，由于服务器全部裸奔，除了关机没有任何解决办法，但老板不允许关机，最后是腾讯云单方面强制关闭负载均衡服务器1小时后，攻击消失。 其实在此次攻击发生前，已经发生多次DDOS攻击，腾讯商务报价5万每季度/10IP/10次峰值DDOS防护套餐被老板认为太贵了，所以就...]]></description>
										<content:encoded><![CDATA[<p>前段时间公司网站遭受DDOS攻击，瞬间每秒接近30G(其实攻击力度很低啦)的流量涌向主项目的负载均衡，由于服务器全部裸奔，除了关机没有任何解决办法，但老板不允许关机，最后是腾讯云单方面强制关闭负载均衡服务器1小时后，攻击消失。</p>
<p>其实在此次攻击发生前，已经发生多次DDOS攻击，腾讯商务报价5万每季度/10IP/10次峰值DDOS防护套餐被老板认为太贵了，所以就这么一直裸奔着。如果对比国内其他运营商的报价，在同等防护力度，流量清洗效率上，腾讯云的报价应该是最低的，奈何老板就是认为因为一个季度两三次的攻击就花费5万元是一种浪费，我们也是毫无办法。只能按要求给他想一下更省钱的方案。</p>
<p>以下精选靠谱方案中最靠谱的几个：</p>
<h3>方案1：临时负载方案</h3>
<p>当遇到DDOS攻击时，临时购买一个月限制带宽的ELB，然后DNS解析到新IP上。 再升级一下就是购买限制ELB，只对资源付费，日常不解析，就没有流量费用，再采用DNS检测的方法，切换解析；<br />
优点：便宜，没有更便宜的方案了，实例租用一个月不到200. 流量按使用量付费就好了。<br />
缺点：攻击者可以顺藤摸瓜ping出新的dns。或者直接对dns服务发起ddos攻击。<br />
就是赌攻击者比较傻，老板十分满意，目前最钟意的方案。 </p>
<h3>方案2：多路解析方案</h3>
<p>购买Dnspod最低版商业解析，1280元每年，分6路解析。解析到6路ELB上，也就是多了5路ELB，再加1000元/年、<br />
优点：便宜，攻击一路，其它路还能保障还能提供服务。<br />
缺点：只要同时攻击电信 联通  移动三路，就完全瘫痪了。<br />
还在在赌攻击者比较傻，老板不太满意，优点小贵呢。</p>
<h3>方案3：统一入口方案</h3>
<p>单独购买一台8核16G腾讯云服务器器， 作为整套系统的入口和负载均衡，成本1200元/月。然后购买一个腾讯云最低版高防IP，绑定到入口服务器。高防IP可以每季度清洗10次峰值20GIP的ddos，超过则另外付钱。<br />
优点：花小钱就能做到多IP常规防御。<br />
缺点：不够稳定，入口放在一台服务器上不稳定。如果通过DNS来负载，那么购买专业版负载解析和多个高防IP又是老板承受不了的。<br />
这方案不用赌攻击者的智商，但绝对是一个会坑死运维的方案。</p>
<h3>方案4：突发境外清洗方案</h3>
<p>境外的计算资源比较足，常常2000元/月就能买到30G-80G有效高防大母鸡了，利用这个特点，可以购买一台或多台境外服务器，配置到到境内闲置ELB的反代（即按流量付费，但平时不解析的ELB）， 在DNS中配置对常用ELB的检查，如果检查失败，则DNS会自动切换到境外服务器反代回境内，检查成功则会自动切换回来。<br />
优点：钱不多，被动多少能起到流量清洗的效果；<br />
缺点：可能会误报，误解析， 防御时境外反代境内，会让接口速度变慢。</p>
<p>总结：这些方案看起来巧妙，还是极不靠谱。但碰到一个抠逼老板，也是没办法的事。一次的攻击损失就在10万以上， 还不愿意花这些钱。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zhangxihai.cn/archives/168/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
