- 博客(74)
- 收藏
- 关注
原创 一次性理清Environment体系
在Spring中,我们可以通过配置文件等方式去进行一些属性值的配置,比如通过@Value注解去获取到对应的属性值,又或者说是想在程序运行时获取系统环境变量,类似的这些操作其实都是去获取一些配置数据,所以在Spring中对这些数据的提供了一个Environment组件,该组件放着的就是这些属性值,并且提供了相应的API给用户去获取,接下来我们就去看一下整个 Environment的结构体系是怎样的
2024-10-17 14:31:04
612
原创 聊一聊Netty优雅停机的实现
何为优雅停机?所谓优雅,指的就是尽可能地去完整地处理每一个任务,更严谨地来讲是保证程序在退出时不再接受新的请求,并且也要保证旧的请求处理完毕。与优雅停机相反的就是暴力停机,也就是程序退出就立刻退出了,如果有正在处理的任务或者还未处理的任务都将中断或抛弃。这样一对比,优雅停机其实是每一个服务程序都需要去实现的功能,比如我们熟知的线程池也有优雅退出的实现,下面我们就来看一下Netty是怎么实现优雅停机的吧
2024-10-17 10:12:01
1127
原创 Netty无锁化设计之对象池实现
池化技术是比较常见的一种技术,在平时我们已经就接触很多了,比如线程池,数据库连接池等等。当我们要使用一个资源的时候从池中去获取,用完就放回池中以便其他线程可以使用,这样的目的就是为了减少资源开销,提升性能。而Netty作为一个高性能的网络框架,在这一块也自然下足了工夫,下面我们就来看一下在Netty中的对象池是如何实现的吧
2024-10-16 16:16:15
1491
2
原创 缓存框架JetCache源码解析-缓存定时刷新
当我们去访问每一个key的时候,JetCache都会对这个key生成一个RefreshTask任务,然后会把这个RefreshTask任务交给定时任务调度器。
2024-10-16 16:05:35
1083
原创 深入了解Spring重试组件spring-retry
在我们的项目中,为了提高程序的健壮性,很多时候都需要有重试机制进行兜底,最多就场景就比如调用远程的服务,调用中间件服务等,因为网络是不稳定的,所以在进行远程调用的时候偶尔会产生超时的异常,所以一般来说我们都会通过手动去写一些重试的代码去进行兜底,而这些重试的代码其实都是模板化的,因此Spring实现了自己的重试机制组件spring-retry,下面我们就一起来学习一下spring-retry这个组件吧。
2024-10-16 15:56:08
1561
原创 Spring事务Transaction rolled back because it has been marked as rollback-only异常是怎样回事?
在平时使用spring事务去开发的时候,可能我们会碰到如下图的一个异常:这个异常是怎么回事?下面就让我们来探究一番当我们两个事务的事务传播级别都是PROPAGATION_REQUIRED的时候,如果嵌套事务发生了异常但是被上层调用方catch掉了异常,也就是说如果上面的OrderService抛出了异常,但是被UserService进行了catch,这时候就会抛出Transaction rolled back because it has been marked as rollback-only,抛出的异常
2024-06-02 17:21:11
1371
1
原创 理清Spring事务的核心关键类
在spring事务源码的内部,会有几个比较核心关键的类,虽然这基本上都是源码内部才使用到的类,但是有时候我们要对其做一些改造的时候免不了要去使用到这些类,并且这些类在spring事务内部都是起到关键的作用,对了解spring事务源码的帮助比较大,所以下面我们重点就来理解下这些关键类。
2023-09-16 17:31:22
294
原创 Netty时间轮HashedWheelTimer原理分析
在该方法中会去根据时钟指针tick计算出时钟已经走了多长时间,然后再计算出时间轮线程已经运行的时间,两个时间相减就是当前离下一个时刻还剩多少时间了,此时让时间轮线程睡眠这段时间,当睡眠过后,如果指针走过的时间小于等于线程走过的时间,就表示这段时间就到达下一个时钟回拨点了,最后就返回当前时间轮线程的运行时间。同时它也不适合时间跨度范围很大的场景,比如往时间轮中扔很多的延时十几天时间的任务,这样这些延时任务在这期间都会以链表的形式存在于时间轮数组中,从而一直占用JVM内存。
2023-09-14 15:21:34
315
原创 深入探讨Seata RPC模块的设计与实现
该类是整个RPC设计的一个顶层抽象类,其主要实现了同步发送与异步发送的功能,此时在这里还没区分客户端与服务端,因为无论是客户端还是服务端,双方都应该有发送数据的功能该类继承于AbstractNettyRemoting,是Netty客户端的抽象基类,基于AbstractNettyRemoting的发送数据能力之上,实现了通过不同的负载均衡策略去选择服务端地址以及批量发送的功能/*** Netty客户端处理接收消息的handler*/@Sharable@Overrideif (!return;
2023-06-30 15:04:57
803
原创 Seata AT异常流程场景梳理
此时回滚重试定时器就能查询出该全局事务,然后对该全局事务下的所有分支事务进行回滚,如果回滚失败,就把状态改为TimeoutRollbackRetrying,然后继续重试回滚,在完成回滚之前全局锁不会被释放。分支事务在执行完业务sql以及undoLog的sql之后,会去往TC注册分支事务信息,同时去获取全局锁,然后再提交本地事务,最后提交完事务之后上报提交结果给TC。通过全局锁的超时机制解决,线程B在等待全局锁超时后会主动释放全局锁,然后进而释放本地锁。
2023-06-29 18:25:06
688
原创 Seata AT模式是如何控制数据源代理的?
在seata-spring-boot-starter模块中,SeataDataSourceAutoConfiguration这个自动配置类往spring容器中加入了SeataAutoDataSourceProxyCreator这个组件 点进去一看可以看到SeataAutoDataSourceProxyCreator继承了spring的AbstractAutoProxyCreator,熟悉spring的同学可能知道AbstractAutoProxyCreator这个组件,该组件实际上是一个BeanPos
2023-06-29 18:07:36
766
原创 RocketMQ中Netty模块的底层设计(一)
在RocketMQ的底层通信是依靠它的rocketmq-remoting模块去支持的,而rocketmq-remoting这个模块的底层实现则是基于Netty去实现的,下面我们就把rocketmq-remoting模块剥离出来,去深挖下其实底层是如何通过Netty去实现支撑RocketMQ的通信
2022-10-30 15:02:31
1060
原创 Sentinel漏桶算法源码解析
漏桶算法是限流算法的一种。从图中我们可以看到,整个算法其实十分简单。首先,我们有一个固定容量的桶,有水流进来,也有水流出去。对于流进来的水来说,我们无法预计一共有多少水会流进来,也无法预计水流的速度。但是对于流出去的水来说,这个桶可以固定水流出的速率。而且,当桶满了之后,多余的水将会溢出。我们将算法中的水换成实际应用中的请求,我们可以看到漏桶算法天生就限制了请求的速度。当使用了漏桶算法,我们可以保证接口会以一个常速速率来处理请求。
2022-10-30 14:32:39
638
原创 Sentinel滑动时间窗口的原理及源码实现
我们一开始先对sentinel中与统计数据相关的对象进行了一个粗略的讲解,从最上层来看我们想要对qps的数据进行统计的都可以使用ArrayMetric,而ArrayMetric底层对qps数据统计是使用了滑动时间窗口算法来进行实现的,也就是基于LeapArray这个类的基础上去实现的。当然,当我们要统计qps的某一项数据时,我们需要先去调用LeapArray的currentWindow方法去对时间窗口进行一次更新,然后才能再去记录某一项的统计数据。
2022-10-30 14:28:10
2637
1
原创 Spring是如何解决循坏依赖的?
什么是循环依赖?举一个例子,所谓的循环依赖就是现在有一个A类和一个B类,A里面属性注入了B,也就是依赖了B,B里面也依赖了A,那么这就是循环依赖了,而我们要探究的是spring是怎么在实例化A并且初始化的时候注入B,然后实例化B并且初始化的时候又是怎么能够注入到A这个过程。我们先来看getBean这个方法,因为这个方法里面实现了一个Bean实例化到初始化最终变成一个完整的bean的过程org.springframework.beans.factory.support.AbstractBeanFa.
2022-01-27 16:54:11
708
3
原创 Nacos集群(二)阿里自研弱一致性Distro协议核心实现
Nacos中有CP和AP两种模式,而这两种模式在实现数据一致性方案上面是完全不一样的,对于CP模式而言,使用的是raft这种强一致性协议,对于AP模式而言,则是使用阿里自创的Distro协议,那么这里我们就来看看这个Distro协议在Nacos中是如何实现的一.@CanDistro注解在Nacos服务中会发现有很多接口上面加了@CanDistro这个注解,例如实例注册接口:而@CanDistro这个注解有什么用呢?通过名字大概知道它应该是跟Distro协议有关的,所以我们通过idea去看一..
2022-01-21 18:05:19
2300
原创 Nacos集群(一)节点启动初始化源码解析
Nacos可以选择单机模式运行和集群模式运行,在生产中基本都要使用集群模式去运行的,而对于集群模式来说,每一个Nacos节点都需要通过配置知道其余节点的地址,比如说三个节点的集群,每个节点都需要知道另外两个节点的地址,才能够形成一个集群,下面我们就来看下Nacos节点在启动时是怎么获取其余节点地址进行集群初始化的Nacos集群节点管理器ServerMemberManagercom.alibaba.nacos.core.cluster.ServerMemberManager在Nacos服务启动.
2022-01-21 17:56:47
2725
原创 Nacos整合SpringCloud的自动注册原理
一.问题引出单独的nacos项目中分为client端和server端,client端会调用register去向server端注册,但是我们在做微服务的时候引入的并不是单独的nacos客户端的jar包,而是springcloud alibaba nacos这个jar包,当我们引入这个jar包之后,就可以在项目启动的时候自动地往nacos服务端去注册这个服务了,那么springcloud alibaba nacos这个包能做到自动注册的原理是什么呢?二.nacos,springcloud ali
2022-01-18 17:50:22
1788
原创 深入理解Nacos源码注册中心之服务发现(订阅拉取)
Nacos的服务发现功能有两种实现方式,一种是客户端主动请求服务端拉取注册的实例,另一种是客户端对服务端进行订阅之后,当服务端注册的实例发生变更之后,服务端会主动推送注册实例给客户端。第一种主动拉取的模式比较简单其实就是客户端发起拉取请求之后然后服务端根据请求的内容去双层map结构中找到对应的注册实例返回给客户端,而第二种方式则比较复杂,需要服务端去进行数据的推送,那么下面我们就来看下Nacos订阅拉取服务是如何实现的1.Nacos客户端发起拉取服务请求我们先来看下订阅拉取服务这个功能在客户端是.
2022-01-18 17:39:11
6914
1
原创 深入解析Nacos源码注册中心AP模式之服务注册
Nacos有两种模式,一个是AP模式(最终一致性),一个是CP模式(强一致性),通常我们平时使用最多的就是它的AP模式,所以这里我们就来看一下对于一个注册中心来说,最基础的服务注册功能在Nacos中的实现原理是怎样的。com.alibaba.nacos.naming.controllers.InstanceController#register 首先先说明一下Nacos的服务端其实就是nacos-naming这个模块,这个模块就是一个springboot项目,所以我们可以通过官方文档直接找到它的.
2022-01-18 17:19:17
2515
原创 RocketMQ消费端消息回退(消费重试)机制源码解析
在看这篇文章之前,我们先要了解过消费者并发消费的底层实现,因为消息消费重试都是在消费完成之后才会去判断是否需要对该消息进行重消费。那么什么时候需要对消息进行重新消费呢,比如说消费失败的时候,此时RockqtMQ不会让这个消息白白浪费掉,而是会让消费者能够有机会重新拿到这个消息对这个消息重新消费,而消息重试的原理其实就是延迟消息的一种运用,在一个消息消费失败的时候,消费者底层会把这个消息重新发送到broker端,并且这次的发送试一次延时消息的发送,然后当延时时间结束之后,消费者就会能够重新拉取到这个消息并对.
2022-01-12 16:52:17
3096
原创 深入了解Spring的@Scope注解中作用域代理proxyMode属性的实现
一.问题引入代码如下:@RestControllerpublic class ConfigController { @Autowired private TestService testService; @GetMapping("/testPrototype") public String testPrototype() { System.out.println(testService); return testService.
2022-01-04 18:28:26
4325
2
原创 RocketMQ中的autoCreateTopicEnable是如何实现自动创建topic?
我们知道在rocketmq的broker中可以设置autoCreateTopicEnable,当autoCreateTopicEnable = true的时候,如果生产者往broker中发送消息并指定了一个broker中不存在的topic,那么也是可以发送成功的,因为broker会自动地去创建这个不存在的topic,下面我们就来看一下rocketmq中是如何实现的一.生产者发送消息问题引出:在生产者发送消息之后,首先它需要知道消息要发送的broker地址,而broker的地址属于路由信息的一部分.
2021-12-24 10:37:53
9333
1
原创 RocketMQ之消费者顺序消费源码解析
RocketMQ对于消费者端顺序消费来说只能保证局部顺序,并不能保证全局顺序消费,局部顺序的意思就是只能对于一个mq的消息达到顺序消费,所以若是想要达到全局顺序消费的效果,对于一个topic来说可以值设置一个mq。RocketMQ实现顺序消费的原理:因为要保证一个mq的消息能够被顺序消费,第一首先这个mq的消息必须要保证不能被一个以上的消费者所消费(并发消费时如果发生mq的负载均衡就可能会产生一个mq的消息被重复消费了,并且还是乱序消费的),那么其实问题就在于消费者之间是不同的系统而产生的,按照正常的.
2021-12-24 10:21:15
2111
原创 RocketMQ之消费者并发消费源码解析
一.并发消费使用示例:public class BalanceComuser { public static void main(String[] args) throws Exception { // 实例化消息生产者,指定组名 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumerGroup"); // 指定Namesrv地址信息. consum
2021-12-23 18:30:45
4303
原创 从源码角度分析RocketMQ同步刷盘与异步刷盘的异同
同步刷盘:当生产者发送消息到broker端的时候,需要等待broker端把消息进行落盘之后,才会返回响应结果给生产者异步刷盘:当生产者发送消息到broker端的时候,此时无需等待broker端对消息进行落盘的过程,直接就可以返回响应结果给生产者按照正常逻辑去理解,我们都会以为同步刷盘和异步刷盘的实现不同之处肯定就在于同步刷盘是生产者线程同步执行刷盘逻辑完成的,异步刷盘是由一个子线程去完成刷盘的操作的,那么事实真的是如此吗?下面我们通过源码的角度去探讨下两者之间的异同同步刷盘fin..
2021-12-23 17:14:21
838
原创 分析RocketMQ消费端长轮询的源码实现
我们通常使用的DefaultMQPushConsumer是通过推拉两种模式结合的长轮询机制去进行工作的,消费者通过这种机制对消息进行消费,既能保证主动权在客户端,又能保证数据的实时性。而什么是长轮询呢?长轮询的本质仍然是轮询,只不过又与普通的轮询不同,不同点在于:当服务端接收到客户端的请求后,服务端不会立即将数据返回给客户端,而是会先将这个请求hold住,判断服务器端数据是否有更新。如果有更新,则对客户端进行响应,如果一直没有数据,则它会在长轮询超时时间之前一直hold住请求并检测是否有数据更新,直到有数.
2021-12-23 17:05:55
1297
原创 RocketMQ延迟消息底层实现源码解析
在RocketMQ中,发送一个消息我们都是需要指定消息投递到哪个topic,但是如果这个消息设置了消息的延迟级别,那么该消息投递的就不是目标topic的,而是一个叫SCHEDULE_TOPIC_XXXX的topic,由于ConsumeQueue文件是顺序写的,这个topic下每一个ConsumeQueue文件就存储着对应不同延迟级别的消息,比如延迟5s的消息都会在同一个ConsumeQueue文件中,这样既能遵守ConsumeQueue文件顺序写的特性,又能每一个消息的延迟结束时间天然地与写入顺序一致。
2021-12-23 16:26:49
1721
原创 从源码寻找RocketMQ消费者消费起始位置的问题
RocketMQ消费者中有一个consumeFromWhere属性,该属性从语义上来看就是说该消费者从队列的哪里开始消费,并且可以通过setConsumeFormWhere方法去进行设置,可设置的有三个值,分别是CONSUME_FROM_LAST_OFFSET,CONSUME_FROM_FIRST_OFFSET,CONSUME_FORM_TIMESTAMP,按照语义上来理解就是从队列的最后开始消费,从队列的初始位置开始消费,从消息指定的时间戳开始消费,但是事实上真的是这么简单吗,下面我们就来看一下这三个值.
2021-12-23 16:13:33
3382
原创 SpringCloud整合Feign的调用源码流程解析
Feign的内部组件在说feign的整个初始化过程之前,我们先来看看feign的内部组件有哪些我们直接来到Feign这个类,里面有一个内部类Builder,不难猜到创建一个Feign对象应该就是使用构造者模式public static class Builder { private final List<RequestInterceptor> requestInterceptors = new ArrayList<RequestInterceptor&g
2021-07-18 21:02:10
537
1
原创 SpringCloud与Ribbon整合的时候是如何提供RestTemplate负载均衡功能?
当我们在项目中加上springcloud-ribbon依赖之后,RestTemplate就具有了负载均衡的功能,这是为什么呢?下面我们来主要分析下其原理的实现首先我先说出原理,这个原理就是RestTemplate中能够添加一组拦截器,而一旦添加了拦截器,在RestTemplate真正地发请请求的时候,会先经过这些拦截器,而springcloud在与ribbon整合中就提供了一个拦截器,在RestTemplate发起请求之前可以通过ribbon获取目标服务实例并且能够重写urlLoadBalanc.
2021-07-18 20:51:49
234
1
原创 深入理解Sentinel如何构建Node调用树
sentinel在node调用树的基础去通过一系列的规则slot去达到限流流控降级功能的实现,并且这些规则slot是通过链表的数据结构去进行级联调用的,它们都分别对应着一个功能点,而在slot调用链中可以分为两种类型的slot,一种就是用于构建node调用树的slot,一种就是用于根据不同的规则去对资源限定访问的slot。
2021-07-18 20:40:09
1258
5
原创 Spring缓存切面源码解析
@EnableCaching这个注解的作用就是开启缓存,使得加在方法上面的缓存注解生效,我们看下这个注解是做了什么@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(CachingConfigurationSelector.class)public @interface EnableCaching { boolean proxyTargetClass() default fal
2021-07-17 21:07:30
456
1
原创 SpringAOP之@EnableAspectJAutoProxy注解如何实现自动代理?
前面我们主要说了关于SpringAOP底层的API,这篇文章就来说说这些底层的API与SpringIOC容器的结合是如何实现对象的自动代理的@EnableAspectJAutoProxy通常我们在一个spring项目中要使用SpringAOP的功能的时候,除了要加上AOP和AspectJ的依赖,还要在配置类上面加上@EnableAspectJAutoProxy注解,该注解的作用就是开启SpringAOP的自动代理功能,下面我们来看这个注解的作用@EnableAspectJAutoProxy..
2021-07-15 19:28:47
2879
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人