自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(22)
  • 收藏
  • 关注

原创 如何解决代码循环依赖问题?

合理的系统架构以及持续的重构优化工作能够减轻这种复杂关系,但如何有效识别系统中存在的循环依赖仍然是开发人员面临的一个很大的挑战。所谓循环依赖,简单来说就是一个类A会引用类B中的方法,而反过来类B同样也会引用类A中的方法,从而导致类A和类B之间存在相互引用,从而形成一种循环依赖。组件之间的循环依赖关系的产生原因在于组件1中的类与组件2中的类之间存在依赖关系,从而导致组件与组件之间产生一种循环依赖。对于循环依赖,JDepend给出了四个子页面,分别是所选中的包、存在循环依赖关系的包、所依赖的包和被依赖的包。

2024-05-15 11:13:21 573

原创 如何基于可靠事件模式实现最终一致性?

如果我们发现事件表存在长时间处于“新增”状态的事件,那么显然系统已经处于一种不一致的情况,这时候就需要事件服务主动查询业务服务中与该事件相关的业务数据是否已经处理完成。通过前面的分析,我们明白了一个道理。这个过程需要考虑事件的处理时机,服务将事件写入事件表的时机在于开启事务之后,而将事件表中的事件发送到消息中间件的时机在于事务提交。所以,我们需要使用一个额外的“事件恢复”机制来恢复事件,该事件恢复机制同样定时从事件表中获取那些未发布成功的事件并进行重新发布,只有重新发布成功才把事件的状态设置为“成功”。

2024-05-14 14:37:27 476

原创 什么是RSocket?它有哪些优势?

显然,RSocket接口通过四个方法分别实现了它所提供的四种交互模式,其中requestResponse方法返回的是一个Mono对象,这里的Payload代表的就是一种消息对象,由两部分组成,元信息metadata和数据data,类似于常见的消息通信中的消息头和消息体的概念。这样,整个调用过程就结束了。在交互模式上,与HTTP的请求-响应这种单向的交互模式不同,RSocket倡导的是对等通讯,不再使用传统的理解是客户端-服务器端改进,而是在两端之间可以自由的相互发送和处理请求。

2024-05-13 10:58:56 1028

原创 什么是资源池技术?它有什么用?

更为重要的,我们详细分析了资源池的应用场景,并基于Mybatis这一主流ORM框架,给出了数据库连接池这一具体资源池的工作流程和实现过程。这里池(Pool)是一种对资源的抽象方法,代表一组可以随时使用的资源,但这些资源的创建和释放过程则基于一定的管理策略。接下来,为了模拟昂贵的对象初始化过程,我们可以构建如下所示的User类,注意到在构造函数中,我们通过Thread.sleep(1000)来模拟这种高成本的创建过程。资源池的概念本身比较简单,我们对它的基本操作进行抽象,可以自己实现一个资源池,如下所示。

2024-05-11 09:09:07 876

原创 什么是分库分表?代表性框架有哪些?

然而,这种直接在业务代码中嵌入分片组件的方法也有明显的缺点。所谓分库分表,业界并没有一个统一的定义,我们可以简单理解为:为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分成若干数据库,将原来数据量大的表拆分成若干数据表组成,使得单一数据库、单一数据表的数据量变得足够小,从而达到提升数据库性能的效果。基于前面关于分库分表的讨论,我们可以抽象其背后的一个核心概念,这个概念就是分片(Sharding),即无论是分库还是分表,都是把数据划分成不同的数据片,并存储在不同的目标对象中。

2024-05-10 11:31:00 949

原创 什么才是正确的领域驱动实现架构?

作为一种系统建模方法,DDD同样涉及系统的体系架构设计。区别于分布式、事件驱动、消息总线等架构设计方法,DDD中的架构设计关注前面各章所介绍的聚合、实体、值对象、领域事件、应用服务以及资源库之间的交互方式和风格,并在设计思想上有其独特的考虑。本节内容将针对DDD特有的架构模式展开讨论,包括经典分层架构、整洁架构以及六边形架构。

2024-05-09 09:28:44 1729

原创 如何正确理解RestTemplate远程调用的实现原理?

本文从源码出发理解RestTemplate实现远程调用的底层原理。初始化RestTemplate实例我们可以通过RestTemplate所提供的几个构造函数来对其进行初始化。在分析这些构造函数之前,有必要先看一下RestTemplate类的定义,如下所示:public class RestTemplate extends InterceptingHttpAccessor implements RestOperations 可以看到,RestTemplate扩展了InterceptingHttpAccesso

2024-05-08 11:32:19 901

原创 如何有效识别限界上下文?

在实施DDD的过程中,识别限界上下文是一大难点,但也并非无章可循。在本文内容中,我们将分别从业务维度、工作维度以及技术维度进行展开,讨论如何有效识别限界上下文的方法和技巧。

2024-05-07 11:30:46 778

原创 如何实现自定义度量指标和Actuator端点?

在日常开发过程中,有时候扩展现有端点并不一定能够满足需求,自定义Spring Boot Actuator监控端点是更灵活的方法。现在,假设我们需要提供一个监控端点以获取当前系统的用户信息和计算机名称,我们就可以实现一个独立的MySystemEndPoint,代码如下所示:@Endpoint(id ="mysystem"truepublicclasspublicresultnewmap= System.getenv();

2024-05-06 10:47:18 820

原创 如何设计一套轻量级的批处理技术?

在分层架构的基础上,我们就引出了批处理的健壮性需求,并同样阐述了三种实现方案。而这三种策略的采用时机也是可以动态调整的,典型的例子包含:但刚开始出现异常情况时,我们可以采用重试机制,但当重试出现三次之后如果仍然抛出异常,那么我们就需要转为采用重启策略了。忽略的含义在于,对于那些并不影响批处理执行流程的异常情况,我们没有必要停止整个任务,而是可以选择性的忽略这些异常。在考虑批处理架构之前,我们站在最高的抽象度上,可以把批处理过程看作是一个流程,包括读数据、处理数据和写数据,而这些数据背后是各种数据存储媒介。

2024-04-29 09:55:14 777 2

原创 如何基于Zookeeper实现注册中心模型?

在分布式系统中,通常会存在几十个甚至上百个服务,开发人员可能甚至都无法明确系统中到底有哪些服务正在运行。另一方面,我们很难同时确保所有服务都不出现问题,也很难保证当前的服务部署方式不做调整和优化。由于自动扩容、服务重启等因素,服务实例的运行时状态也会经常变化。通常,我们把这些服务实例的运行时状态信息统称为服务的元数据(Metadata)。既然服务数量的增加以及服务实例的变化都不可避免,那么,有什么好的办法能够做到对这些服务实例进行有效的管理呢?这实际上就是一个服务治理的问题。

2024-04-28 10:21:50 1766 3

原创 请求限流算法有哪些?分别面向什么应用场景?

单位时间内调用量限流的基本思想非常简单,就是控制一定时间内的请求量大小,如果这个请求量在合理的访问阈值内,我们就认为能起到限流的效果。那么在第11秒开始的瞬间原则上又可以发送10个请求,这样在这一段很短的时间之内,服务A相当于接收到了20个请求,超过了限流的阈值,可能导致服务失败。上图中,我们看到请求1~9以不同的速率进入漏桶,而输出的则是固定速率的请求1~5,剩余的请求则会继续留在漏桶中。请注意,漏桶本身的容量肯定也不是无限大的,所以当桶中的请求数量超过了桶的容量,新来的请求也只能被丢弃掉了。

2024-04-26 10:24:05 965

原创 什么是序列化?如何对序列化实现工具进行正确选型?

在现实中,我们通常会使用Dubbo、Spring Cloud等开源框架,以及TCP、HTTP等网络传输协议来发起远程调用。对于这些框架和协议而言,客户端发起请求的方式,以及服务端返回响应结果的处理过程都是不一样的。但是这里存在一个共同点,即无论采用何种开发框架和网络传输协议,都涉及到业务数据在网络中的传输,这就需要应用到序列化技术。和网络通信不同,序列化技术是直接面向开发人员的,我们可以对具体的序列化工具和框架进行选择,而不像网络通信过程那样只能依靠框架底层所封装的能力。

2024-04-25 10:29:34 1203

原创 什么是可靠事件模式?如何实现?

当订单服务往消息中间件中投递消息时,因为消息投递的过程需要与消息中间件进行网络通信,当消息投递成功但返回时可能发生网络异常,这样对于订单服务而言消息投递是成功的,但因为网络原因接收不到返回消息,所以就会认为本次消息投递失败,从而触发数据库回滚。显然,在上图中,因为事件消息的发布可能会失败或无法获取返回结果,我们需要使用一个额外的“事件恢复”服务来恢复事件,该事件恢复服务定时从事件表中恢复未发布成功的事件并重新发布,只有重新发布成功才删除保存在本地事件表中的事件。在我们的案例中,显然订单服务是事件的生产者。

2024-04-24 11:50:56 795

原创 什么是集群容错?如何实现集群容错?

在使用负载均衡策略时,我们需要提到集群这一概念。集群的构建一方面能够为实现负载均衡提供基础,另一方面,它也能够有效应对服务访问出错的场景,这就是集群容错。在分布式系统运行过程中,远程调用发生失败的现象不可避免。为了应对服务访问失败,集群容错是一种简单高效的技术组件。那么,什么是集群容错?常见的又有哪些集群容错策略呢?集群容错是服务容错的其中一种实现方式。我们知道,所谓集群,就是同时存在一个服务的多个实例。一旦我们访问其中一个实例出现问题,原则上可以访问其他实例来获取结果。

2024-04-19 14:21:28 1159

原创 什么是动态代理?它在主流开源框架中有哪些应用?

在系统设计过程中,对象之间相互依赖会造成耦合度过高,我们需要引入一个中间类来消除或缓解在直接访问目标对象时所带来的问题。但是对于发起访问的对象而言,通常希望这个中间类的存在是无感知的,这时候我们就可以引入动态代理机制。那么,问题就来了,作为一种通用型的技术组件,动态代理在分布式系统构建过程中起到什么作用呢?本文内容将和你一起探讨这个话题。在系统设计领域,代理(Proxy)是一种常见的技术组件,主要目的就是在访问目标对象之前添加一层代理对象,用于消除或缓解在直接访问目标对象时带来的问题。

2024-04-18 15:53:03 737

原创 如何自己动手写一个基础RPC架构

任何分布式系统的开发都涉及到跨进程之间的远程过程调用,也就是所谓的RPC。前面两讲我们讨论的网络通信和序列化实际上也都属于是RPC架构的范畴,只是关注于不同的技术切入点。而RPC本身也构成一种架构体系,包含一系列相互协作的核心组件。在Dubbo、Spring Cloud等主流的分布式服务框架中,这些技术组件使用起来都非常简单,因为框架为开发人员屏蔽了底层的实现细节。那么,现在假如没有这些开源框架,而是需要你自己来设计并实现一套远程过程调用机制,你应该怎么做的?

2024-04-17 15:13:39 972

原创 如何实现分布式链路跟踪

而四种注解构成了客户端和服务器对一次请求处理的闭环,对于服务A而言,cs是11:10:44, cr是11:10:55,也就说该次服务请求经由服务A的整个调用链路时间是11s(11:10:44-11:10:55),显然这个响应时间非常长。对于服务监控而言,服务调用链数据收集、分析和管理的目的是为了发现服务调用过程的问题并采取相应的优化措施。所谓跨度,就是调用链路中的其中一段时间,具有明确的开始和结束这两个节点,这样通过计算开始时间和结束时间之间的时间差,我们就能明确调用过程在这个Span上所产生的时间延迟。

2024-04-16 17:22:45 1146

原创 如何基于微内核架构模式实现系统扩展?

请注意,在上面这个Main函数中,我们并没有引入任何与Log4jProvider相关的包结构,但在运行过程中,却实现了对Log4jProvider类的动态调用,这是微内核架构的核心特征,对组件之间的依赖关系进行了解耦,从而确保了系统的扩展性。针对这样的扩展性需求,本质上开发人员想要的是一种类似插件化的架构体系,调用者通过一个插件工厂获取想要的插件,而插件工厂则基于配置动态创建对应的插件,这样整体系统就像搭积木一样可以进行动态的组装。这里的内核系统用来定义插件的实现规范,并管理着插件的生命周期。

2024-04-15 09:20:02 918

原创 负载均衡算法有哪些?如何实现?

在分布式环境下,我们将多个服务实例集中在一起,每一次请求都可以由集群中的某一个服务实例进行响应。那么具体某一个请求到底应该是由哪个服务实例来响应最为合适呢?这个话题看上去很简单,实际上却有点复杂,涉及到服务请求的路由机制。而在分布式系统中,负载均衡就是最常见也是最具代表性的一种路由机制。为了对请求进行合理的分发,我们需要提供一组负载均衡算法,那么常见的负载均衡算法有哪些?它们又应该如何实现呢?我们先来看这些问题背后的示意图,如下图所示。

2024-04-12 10:06:15 896

原创 Spring是如何解决循环依赖问题

而earlySingletonObjects中存放的是那些提前暴露的对象,也就是已经创建但还没有完成属性注入的对象,属于第二级缓存。所谓的三级缓存,在Spring中表现为三个Map对象,定义在DefaultSingletonBeanRegistry类中,该类是DefaultListableBeanFactory的父类,如下所示。ClassB对象创建完成之后会放到第一级缓存中,这时候ClassA就能从第一级缓存中获取ClassB的实例,进而完成ClassA的所有初始化流程。

2024-04-11 16:31:13 1087 2

原创 Spring Cloud Stream

关于如何构建一个统一化的消息通信平台,Spring Cloud Stream是我们值得深入分析和研究的一个框架。对于消息通信而言,我们需要分别实现消息的发布者和消费者。在Spring Cloud Stream中分别是Source和Sink组件。而消息的传递显然应该用到通道,所以Spring Cloud Stream也包含了Channel组件。最后,作为Spring Cloud Stream框架在设计上的一大特色,Binder组件专门用于屏蔽与各种消息中间件之间的技术差异,为开发者提供统一的API。

2024-04-10 10:08:32 759 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除