Dubbo SPI
Dubbo SPI一、什么是SPI机制?SPI (Service Provider Interface),主要用于扩展的作用。
举个例子来说,假如有一个框架有一个接口,他有自己默认的实现类,但是在代码运行的过程中,你不想用他的实现类或者想扩展一下他的实现类的功能,但是此时你又不能修改别人的源码,那么此时该怎么办?这时spi机制就有了用武之地。一般框架的作者在设计这种接口的时候不会直接去new这个接口的实现类,而是在Classpath路径底下将这个接口的实现类按作者约定的格式写在一个配置文件上,然后在运行的过程中通过java提供的api,从所有jar包中读取所有的这个指定文件中的内容,获取到实现类,用这个实现类,这样,如果你想自己替换原有的框架的实现,你就可以按照作者规定的方式配置实现,这样就能使用你自己写的实现类了。
spi机制其实体现了设计思想中的解耦思想,方便开发者对框架功能进行扩展。
二、Spring中的SPI - SpringFactoriesLoader相信spring大家都不陌生,在spring扩展也是依赖spi机制完成的,只不过spring对于扩展文件约定在Classpa ...
设计模式-建造者模式
设计模式 - 建造者模式建造模式是对象的创建模式。建造模式可以将一个产品的内部表象(internal representation)与产品的生产过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
一、简介建造者模式,相当于是对工厂生产产品的一种装配,由于这种装配可能随时改变,所以需要抽取出来,实现产品局部与整体的解耦(当然话又说回来,单个孤立产品还需要建造者?那就是多此一举)。着重理解装配的含义,对应在程序中就是相当于调用顺序,以及调用参数问题。理解起来还阔以哈,比起那几个工厂模式用的稍微少一丢丢。
一般建造者模式都有以下几种固定的角色:
抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者 (ConcreteBuilder)角色。具体建造者类必须实现这个接口所要求的两种方法:一种是建造方法(buildPart1和 buildPart2),另一种是返还结构方法(retrieveResult)。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有 ...
Spring循环依赖
Spring循环依赖1、为什么会出现循环依赖问题? 在Spring中bean的生命周期大致为:
从文件中得到UserService.class
推断使用的构造方法(有参或无参)
获得Class普通对象
依赖注入
初始化前(@PostConstruct)
初始化(afterPropertiesSet)
初始化后(AOP等操作)
若定义了AOP,生成代理对象(与原先的Class是两个不同的对象)
将对象或代理对象放入单例池
依赖注入问题主要发生在依赖注入缓解,场景如下
12345678910111213@Componentpublic class AService { @Autowired private BService bService;}@Componentpublic class BService { @Autowired private AService aService;}
当AService依赖注入时,需要获取BService,由于BService尚未初始化,在单例池中找不到,需要创建,而 ...
Feign远程调用原理
Feign远程调用原理1、Feign远程调用流程图
2、基于面向接口的动态代理方式生成实现类 在使用feign 时,会定义对应的接口类,在接口类上使用Http相关的注解,标识HTTP请求参数信息
在Feign 底层,通过基于面向接口的动态代理方式生成实现类,将请求调用委托到动态代理实现类,基本原理如下所示:
3、根据Contract协议规则,解析接口类的注解信息,解析成内部表现:
4、基于 RequestBean,动态生成Request 根据传入的Bean对象和注解信息,从中提取出相应的值,来构造Http Request 对象
5、使用Encoder 将Bean转换成 Http报文正文(消息解析和转码逻辑) Feign 最终会将请求转换成http消息发送出去,传入的请求对象最终会解析成消息体,如下所示:
6、拦截器负责对请求和返回进行装饰处理 在请求转换的过程中,Feign 抽象出来了拦截器接口,用于用户自定义对请求的操作,比如,如果希望Http消息传递过程中被压缩,可以定义一个请求拦截器。
7、基于重试器发送HTTP请求 Feig ...
论@Configuration的实现原理
@Configuration的实现原理1234567891011121314151617181920212223242526@EnableTransactionManagement//@Configuration@Component("com.example.config")public class JdbcConfig { @Bean public JdbcTemplate jdbcTemplate(){ return new JdbcTemplate(dataSource()); } @Bean public PlatformTransactionManager transactionManager(){ DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSo ...
HTTP与RPC区别比较分析
HTTP与RPC区别比较分析一、TCP的特点与问题一想到TCP,我想大多数人第一时间想到的应该是:面向连接的、可靠的、基于字节流的。
如果我们需要使用TCP协议的话,就需要使用Socket编程。
12345678910111213public class Client { public static void main(String[] args) throws IOException { //1、创建一个Socket对象请求服务端的连接 Socket socket = new Socket("127.0.0.1", 9999); //2、从Socket对象中获取字节输出流 OutputStream os = socket.getOutputStream(); //3、把字节输出流包装成打印流 PrintStream ps = new PrintStream(os); ps.println("hello server!"); ...
Raft共识算法
Raft共识算法一、简介Raft是分布式系统中最经典且最为易理解的共识算法,共识指分布的多个参与者就值”value”达成一致。一旦参与者对某个值做出决定,这个决定将是最终的。当大多数参与者存活时,共识算法会在存活的参与者间达成值一致,这相当于全部参与者存活时达成的一致。故部分参与者达成的一致是整个系统有效的,这一特性使得分布式系统具备一定的容错能力。
更多细节可以阅读Raft官网文档:https://raft.github.io/
在讲解Raft算法的选举和故障转移过程之前,我们先引入Raft算法中的一些基本概念:
Follower
Follower是请求的被动更新者,主要职责是从Leader接收更新请求,再将日志写入本地文件中。
Candidate
Leader选举中的候选者。如果Follower在一定的时间内,没有收到Leader的心跳,则判断Leader可能已经发生故障,此时启动Leader Election过程,本节点切换为Candidate参与Leader的竞选,直到选举结束。
Leader
所有请求的处理者,接收客户端发起的操作请求,写入本地日志后,同步至其他Foll ...
简易RPC框架 - 4
简易RPC框架 - 网络传输模块1、前言我们在前面的文章中说到了客户端通过代理对象进行远程调用,其中通过Channel与服务端进行网络通信,其实就是通过网络请求来传递类信息、方法信息以及方法参数等数据到服务端。其中网络传输的具体实现在本项目中我们使用的是基于NIO的网络编程框架Netty。
2、网络传输1)网络传输实体类在此我们先定义了一些在网络传输中的数据格式:
RpcRequest请求类,当你要调用远程方法时,需要将你要调用的方法的详细信息传输到服务器端,然后服务端就能根据这些信息去获取方法对象。
123456789101112131415161718192021@AllArgsConstructor@NoArgsConstructor@Data@Builder@ToStringpublic class RpcRequest implements Serializable { private static final long serialVersionUID = 6672133783386466359L; private String requestId; ...
简易RPC框架 - 3
简易RPC框架 - 服务订阅、发现模块1、结构设计首先先看Rpc客户端的设计思路:
2、实现这里也是直接上代码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657@Slf4jpublic class RpcClientAutoConfiguration implements BeanPostProcessor, ApplicationListener<ApplicationReadyEvent> { private static NettyRpcClient client; private volatile boolean needInitClient = false; private volatile boolean hasInitClientConfig = false; @Override public Object postProcessAfterInitializ ...
简易RPC框架 - 2
简易RPC框架 - 服务注册模块1、结构设计紧接上文,结合框架结构图进行讲解:
本节主要讲解服务注册的细节,首先定义了三个注解:@RpcService、@RpcReference、@RpcScan
@RpcService用于标注服务提供者,@RpcReference用于标注服务消费者,@RpcScan用于扫描特定的Bean
123456789101112131415@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Inheritedpublic @interface RpcService { /** * Service version, default value is empty string */ String version() default ""; /** * Service group, default value is empty string */ String group() defaul ...