架构与设计 文章

WCF已退休?.NET分布式技术的历史演进与现代替代方案分析
架构与设计
2025-11-07 0k

WCF已退休?.NET分布式技术的历史演进与现代替代方案分析

引言 提到 WCF(Windows Communication Foundation),很多.NET 开发者并不陌生 —— 它曾是.NET Framework 时代分布式系统通信的 “全能选手”。但如今,REST API、gRPC 等技术早已成为主流,有人疑惑:WCF 是不是已经没有意义了?它真的只是 “API 不普及时代的临时替代” 吗? 其实,WCF 的价值远比 “临时替代” 复杂。它的兴起源于特定时代的技术需求,衰落则是技术迭代的必然,而其设计思想至今仍在影响着现代分布式通信技术。今天我们就从时代背景、现状价值、技术替代三个维度,彻底说清 WCF 的 “前世今生”。 一、先澄清:WCF 不是 “临时 API 替代”,而是当年的 “全能服务框架” 很多人对 WCF 的认知停留在 “服务调用”,但这只是它的冰山一角。WCF 的核心定位是微软为.NET Framework 打造的「统一服务开发框架」,目标是让开发者用一套代码,兼容多种通信场景,而非简单替代早期功能单一的 WebService 或 ASHX。 它的核心能力远超 “基础 API 调用”: 多协议支持:覆盖 HTTP(REST/SOAP)、TCP、命名管道(Named Pipe)、MSMQ、WS-* 等,既能满足简单接口通信,也能支撑企业级复杂协议(如事务、安全、可靠消息); 多交互模式:支持请求 - 响应、单向通信、发布订阅、流传输(大文件 / 实时数据)等,适配不同分布式场景; 企业级特性:内置 Windows 认证、证书认证、自定义授权、数据加密、分布式事务等,无需额外开发即可满足企业级安全和一致性需求。 而早期的 “API”(如简单 WebService)功能单一、缺乏统一配置能力,WCF 的出现本质是为了解决「企业级分布式系统的复杂通信痛点」,而非 “临时过渡”。 二、现在的 WCF:新项目零价值,存量系统仍需 “续命” 1.

WCF 分布式技术 .NET
阅读更多
架构反思:引入 Redis 统计在线人数后,JWT 是否还有存在的意义?
架构与设计
2024-10-16 0k

架构反思:引入 Redis 统计在线人数后,JWT 是否还有存在的意义?

在构建 .NET Web API 后台时,为了实现在线人数统计,我们通常会引入 Redis 来存储用户的活跃状态。 这时,一个非常敏锐且直击架构本质的问题往往会浮出水面: “既然为了统计在线人数,每次请求都要去 Redis 读写一次,那 JWT ‘无状态、不查库’ 的核心优势不就没了吗?干脆用一个短小的随机字符串(普通 Token),既能节省流量,又能节省计算资源,岂不更好?” 这是一个极好的问题。它触及了软件架构的核心——权衡 (Trade-off)。 答案是:在特定场景下,普通 Token 确实更好;但在大多数现代架构中,JWT + Redis 的组合依然具有不可替代的优势。 本文将从依赖性、性能、架构扩展性三个维度,深入剖析为什么我们依然推荐保留 JWT。 1. 核心区别:强依赖 vs. 弱依赖 这是两者最根本的区别,决定了系统的可用性 (Availability) 上限。 🔵 方案 A:普通 Token (Reference Token) + Redis 在这个方案中,Token 只是一个无意义的随机字符串(一把钥匙)。 流程: 请求到达 -> 解析 Token -> 必须请求 Redis 查找对应的 UserID -> 拿到身份 -> 执行业务。 风险: 这里 Redis 是强依赖。 如果 Redis 宕机、网络抖动或连接数耗尽,整个系统的认证模块瞬间瘫痪。

JWT Redis 认证授权
阅读更多
从机器指令到面向对象:编程思想的演进与领域驱动设计
架构与设计
2024-07-24 0k

从机器指令到面向对象:编程思想的演进与领域驱动设计

面对领域驱动设计(DDD)的火热,很多熟悉面向对象(OOP)的开发者都会有一个疑问:这和我以前学的OOP是什么关系?是全新的东西,还是旧瓶装新酒?本文将带你回顾编程思想的演进历程,理清DDD与OOP的深刻联系,并展望现代编程思想的融合之道。 一、编程思想的演进脉络:一部与“复杂性”的斗争史 编程的发展史,就是一部工程师们如何不断地抽象和封装,以应对日益增长的软件复杂性的历史。让我们用一张时间线来直观感受这一历程: timeline title 编程思想演进历程 1950年代以前 : 面向机器编程 : 主要与硬件直接交互 1950-1960年代 : 面向过程编程 : 以步骤为中心<br>结构化程序设计 1960-1970年代 : 面向对象编程兴起 : 对象为核心<br>封装、继承、多态 2000年代 : 领域驱动设计提出 : 应对业务复杂性<br>强调领域建模 2000年代至今 : 多种思想并存 : 函数式编程复兴<br>响应式编程等 下面我们来详细解读每个阶段的核心思想与突破: 面向机器与面向过程:效率与结构的初探 面向机器:在计算机诞生初期,编程直接使用机器语言或汇编语言,程序员必须深入了解硬件细节。这种方式效率极低,难以维护,是“与硬件共舞”的时代。 面向过程:随着高级语言(如Fortran, C)的出现,面向过程的思想成为主流。它将程序看作一系列线性步骤(过程),通过函数来实现每个环节,其核心方法是“自顶向下、逐步求精”。然而,当系统变得复杂时,数据和操作分离的特性使得代码的复用和维护变得异常困难,全局变量的滥用等问题凸显。 面向对象编程的兴起:将现实世界映射入代码 为了解耦数据与操作,面向对象编程(OOP) 应运而生。它以类和对象作为基本程序单位,将数据和对数据的操作封装在一起。它通过三大特性来管理复杂性: 封装:收敛内部逻辑,只暴露必要的接口。 继承:实现代码的复用和层次的抽象。 多态:允许同一接口表现出不同的行为,极大地提高了系统的灵活性。 OOP通过对象的概念将现实世界映射到软件系统,更符合人类的思维方式,是程序设计方法学上的一次巨大飞跃。 领域驱动设计的深化:聚焦业务复杂性的战略工具 到了2004年,埃里克·埃文斯(Eric Evans)在其著作《领域驱动设计》中提出了DDD。这时,软件的规模和技术复杂性已经得到较好控制,但业务逻辑本身的复杂性成为了新的挑战。 DDD的核心是建立正确的领域模型,并让这个模型成为项目成员(包括领域专家、设计人员、开发人员)之间沟通的通用语言。它在OOP的基础上,进一步强调了边界的控制,引入了限界上下文和聚合等核心模式,来应对大型、复杂业务系统的设计和拆分问题。 二、DDD与OOP:是继承与发展,而非颠覆与取代 领域驱动设计并非一个全新的编程范式,它可以看作是面向对象思想在复杂业务系统分析和设计上的进一步发展和规范化应用。 1. 核心理念的继承

编程思想 面向对象 OOP
阅读更多
分布式系统并发控制:从单机锁到分布式锁的深度解析
架构与设计
2024-05-06 0k

分布式系统并发控制:从单机锁到分布式锁的深度解析

引言 在分布式系统开发中,并发控制是一个永恒的话题。最近在代码评审时,我看到了这样一段代码: // 复杂操作仍需 lock public void ComplexOperation() { lock (_lockObj) { if (_count > 0 && _count < 100) { _count *= 2; // 其他复杂业务逻辑... } } } 这引发了一系列深入的讨论:如果锁里面执行的是用户下单操作,A用户下单过程中执行了1秒,B用户的请求会怎样?是直接失败还是等待?我们需要手动处理这种等待吗? 本文将围绕这个问题展开,深入探讨单机锁、细粒度锁、数据库事务和Redis分布式锁的优缺点及适用场景。 第一部分:单机锁的行为分析 锁的基本行为 当我们在C#中使用lock语句时,CLR会为我们管理一个等待队列: public void PlaceOrder(Order order) { lock (_lockObj) // 所有用户下单都串行化! { // 复杂的下单逻辑,耗时1秒... ProcessOrder(order); UpdateInventory(); // 其他业务... } } 关键结论:B用户会等待A用户执行完,而不是直接失败。整个过程是自动的,不需要人工干预。 具体执行流程 A用户进入lock块,开始执行下单操作(耗时1秒) B用户的线程到达lock语句时,发现_lockObj已被锁定 B线程会阻塞并等待,直到A线程释放锁 A用户执行完毕,释放锁 B线程获得锁,开始执行自己的下单操作 单机锁的严重问题 虽然锁机制自动处理了同步,但这种设计存在严重问题: 性能瓶颈:所有用户请求串行处理 响应时间变长:B用户需要等待A用户的1秒 + 自己的1秒 = 至少2秒 系统吞吐量下降:无法充分利用多核CPU优势 第二部分:解决方案对比 🥉 方案一:细粒度锁 private readonly Dictionary<string, object> _userLocks = new(); private readonly object _dictLock = new object(); public void PlaceOrder(string userId, Order order) { object userLock; lock (_dictLock) { if (!

分布式系统 并发控制 锁机制
阅读更多
DDD领域驱动设计全面解析:.NET核心概念与落地实践指南
架构与设计
2024-01-24 0k

DDD领域驱动设计全面解析:.NET核心概念与落地实践指南

DDD领域驱动设计全面解析:.NET核心概念与落地实践指南 领域驱动设计(Domain-Driven Design,简称 DDD)是一种以业务领域为核心的现代化软件架构设计方法论,专注于解决复杂企业级业务系统的设计与开发难题。在当今微服务架构和分布式系统盛行的环境下,DDD已成为构建高内聚、低耦合系统的最佳实践。本文将深入剖析DDD核心概念,结合.NET技术栈全面讲解DDD落地实践,帮助开发者掌握企业级应用架构设计精髓。 .NET 作为成熟稳定的企业级开发平台,天然支持 DDD 领域驱动设计的核心诉求 —— 无论是分层架构、面向对象设计,还是依赖注入、领域模型映射等,都能通过 ASP.NET Core、EF Core、MediatR 等 .NET 生态工具无缝落地。本文将从 DDD 领域驱动设计的核心思想出发,结合 .NET 实战场景,系统讲解 DDD 关键概念、架构分层及落地技巧,提供完整的企业应用架构解决方案。 一、DDD领域驱动设计核心思想:业务驱动的架构哲学 DDD领域驱动设计的本质是业务驱动而非技术驱动,所有设计决策都围绕业务需求展开,在 .NET 企业应用开发中,核心遵循三大原则: 领域优先:业务逻辑(领域模型)是系统的核心资产,技术细节(数据库、API、缓存等)仅作为辅助实现; 边界清晰:通过「限界上下文」划分业务边界,解决复杂系统中的 “知识混乱”,避免不同业务模块的概念冲突; 迭代演进:通过「领域语言(Ubiquitous Language)」统一团队(开发、产品、测试)认知,领域模型随业务迭代持续优化。 二、DDD核心概念详解与.NET落地实践 DDD 的概念体系可分为「领域层核心概念」「架构分层」「辅助概念」三类,以下结合 .NET 代码示例和生态工具逐一说明。 (一)领域层核心概念:DDD业务逻辑的核心载体 领域层是 DDD 的 “心脏”,包含业务模型、规则和行为,不依赖任何外部技术框架,纯业务逻辑封装。 1. 领域模型(Domain Model)- DDD核心设计元素 领域模型是业务概念的代码映射,分为两种设计风格: 贫血模型:仅包含属性和 getter/setter,无业务逻辑(传统 MVC 常用,非 DDD 推荐); 充血模型:包含属性 + 业务逻辑方法(DDD 核心),模型自身封装业务规则,确保数据一致性。 .

DDD 领域驱动设计 dotnet
阅读更多
SOA架构和微服务架构的区别
架构与设计
2021-03-12 0k

SOA架构和微服务架构的区别

SOA:  SOA(Service Oriented Architecture)“面向服务的架构”,他是一种设计方法,其中包含多个服务, 服务之间通过相互依赖最终提供一系列的功能。一个服务 通常以独立的形式存在与操作系统进程中。各个服务之间 通过网络调用。 微服务架构:  其实和 SOA 架构类似,微服务是在 SOA 上做的升华,微服务架构强调的一个重点是 “业务需要彻底的组件化和服务化”,原有的单个业务系统会 拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。(去中心化)  微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想 + 80%的领域建模思想 主要区别: 功能 SOA 微服务 组件大小 大块业务逻辑 单独任务或小块业务逻辑 耦合 通常松耦合 总是松耦合 公司架构 任何类型 小型、专注于功能交叉团队 管理 着重中央管理 着重分散管理 目标 确保应用能够交互操作 执行新功能、快速拓展开发团队 摘自: https://blog.csdn.net/zpoison/article/details/80729052

微服务 SOA 架构设计
阅读更多
控制反转(IoC)与依赖注入(DI)- 很容易明白的那种
架构与设计
2021-03-12 0k

控制反转(IoC)与依赖注入(DI)- 很容易明白的那种

一、控制反转 正常控制权是由调用方掌握,控制反转将控制权交给了容器,在运行时由容器决定具体的实现。 二、依赖注入 依赖注入是控制反转的一种实现,调用某个类是对这个类(被调用类)的依赖,正常是直接实例化(被调用类),而依赖注入,是通过构造函数等方式由容器注入到调用方 三、控制反转和依赖注入的关系 控制反转是一种思想 依赖注入是一种设计模式 IoC框架使用依赖注入作为实现控制反转的方式,但是控制反转还有其他的实现方式,例如说依赖查找,所以不能将控制反转和依赖注入等同。

架构设计 IoC DI
阅读更多
程序员除了会 CRUD 之外,还应该知道什么叫 CQRS!
架构与设计
2017-03-11 0k

程序员除了会 CRUD 之外,还应该知道什么叫 CQRS!

今天主要跟大家分享一下什么是 CQRS,以及在项目中如何去使用。 1、先了解什么是CRUD系统 我们平常最熟悉的就是三层架构,通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体。然后通过业务层来处理业务逻辑,将处理结果封装成DTO对象返回给控制层,再通过前端渲染。反之亦然。 这里基本上是围绕关系数据库构建而成的“创建、读取、更新、删除”系统(即CRUD系统),此类系统在一些业务逻辑简单的项目中可能没有什么问题,但是随着系统逻辑变得复杂,用户增多,这种设计就会出现一些性能问题。 我们经常用到的解决方案就是对数据库进行读写分离。让主数据库处理事务性的增、删、改操作,让从数据库处理查询操作,然后主从数据库之间进行同步。但是这只是从DB角度处理了读写分离,从业务或者系统层面上来说,读和写的逻辑仍然是存放在一起的,他们都是操作同一个实体对象。 这时候,CQRS 就该登场了。 2、什么是CQRS系统 简单的说,CQRS(Command Query Responsibility Segration)就是一个系统,从架构上把 CRUD 系统拆分为两部分:命令(Command)处理和查询(Query)处理。其中命令处理包括增、删、改。 然后命令与查询两边可以用不同的架构实现,以实现CQ两端(即Command Side,简称C端;Query Side,简称Q端)的分别优化。两边所涉及到的实体对象也可以不同,从而继续演变成下面这样。 当然了,CQRS 作为一个读写分离思想的架构,在数据存储方面也没有做过多的约束。所以 CQRS可以有不同层次的实现。 3、CQRS 实现方式 CQRS 可以有两种实现方式。 1)CQ 两端数据库共享,只是在上层代码上分离。这样做的好处是可以让我们的代码读写分离,更容易维护,而且不存在 CQ 两端的数据一致性问题,因为是共享一个数据库的。这种架构是非常实用的(也就是我上面画的那种)。 2)CQ 两端不仅代码分离,数据库也分离,然后Q端数据由C端同步过来。同步方式有两种:同步或异步,如果需要 CQ 两端的强一致性,则需要用同步;如果能接受 CQ 两端数据的最终一致性,则可以使用异步。C端可以采用Event Sourcing(简称ES)模式,所有C端的最新数据全部用 Domain Event 表达即可;而要查询显示用的数据,则从Q端的 ReadDB(关系型数据库)查询即可。 4、CQRS 的简单实现 说了这么多,该怎么实现呢?我们以上面提到的第一种方式为例:代码层面实现分离,数据库共享。这种方式在企业里也非常实用。 首先有几个概念需要介绍一下,CQRS 模式中,首先需要有 Command,这个 Command 命令会对应一个实体和一个命令的执行类。那整个系统中肯定有很多不同的 Command,那么还需要一个 CommandBus 来做命令的分发处理。 可能大家觉得比较抽象,我来写几行示例代码,一看就明白了。假设有个订单模块,我要新增一个订单信息。那么根据上文的分析,需要有个新增命令以及对应的订单实体(并不一定和数据库的订单实体完全对应)。首先先创建一个命令接口(绑定命令对应的实体),接口内部有个该命令的处理方法。 public interface Command<T> { Object execute(T commandModel); } interface Command<T> { Object execute(T commandModel); } OK,接下来我们可以创建订单的新增命令了。

dotnet CQRS 架构设计
阅读更多