Dubbo第三讲:Dubbo的可扩展机制SPI源码解析

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
全局流量管理 GTM,标准版 1个月
简介: Dubbo第三讲:Dubbo的可扩展机制SPI源码解析

1、Dubbo SPI机制

1.1、Dubbo具有良好拓展性的原因
  • 1、整个框架中针对不同的场景,恰到好处地使用了各种设计模式
  • 2、基于Dubbo SPI 加载机制,让整个框架的接口和具体实现完全解耦合
  • Dubbo SPI 扩展
  • 与Java SPI类似,需要在META-INF/dubbo/下放置对应的SPI配置文件,文件名称需要命名为接口的全路径名。配置文件的内容为 key=扩展点实现类全路径名,如果有多个实现类则需要使用换行符分割
  • 在Dubbo启用时,会默认扫描这三个目录下的配置文件:META-INF/services/、META-INF/dubbo/、META-INF/dubbo/internal/
  • 1、dubbo filter详解
  • todo
1.2、Dubbo SPI和Java SPI的区别?

Dubbo的扩展点加载从JDK标准SPI(Service provider Interface)扩展点发现机制加强而来。

改进了JDK标准SPI的以下问题:

1、JDK标准的SPI会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但是没用上也加载,会很浪费资源。(我的代码中初始化配置项也存在这样的问题)

2、如果扩展点加载失败,连扩展点的名称都拿不到了

3、增加了对扩展点IOC和AOP的支持,一个扩展点可以直接setter注入其他扩展点。

1.3、Dubbo SPI可认为是IOC实现吗?

todo

2、SPI机制在商品中心的应用

2.1、TMF校验器

详情见这个项目

项目实战第十六讲:使用开闭原则实现商品价格规则引擎

2.2、在AfterImage应用中的使用
2.2.1、整体流程图如下所述

2.2.2、业务逻辑

残影系统,使用切面实现的

  • 注解:Afterimage
  • 包含的字段有
  • captorConfig 本次使用的captor(捕获)配置
  • 该类包含两字段 Captor,dubbo接口或其他 config dubbo接口详情,具体结构见下文
  • expireMills 超时时间,单位是毫秒,小于1:不过期;大于1:过期;不配置:使用captor侧配置的过期时间
  • 使用场景:缓存dubbo调用结果,用于优化在执行上下文重复同一dubbo调用
  • 当同个线程执行链路,多次使用此注解时,只有最外层的注解生效
  • 加上此注解的方法,耗时调用将被暂存起来,直到退出方法
  • 注意事项:
  • 必须使用在能被spring AOP代理的方法上
  • 如何使用:
  • 引入依赖
<dependency>
    <groupId>cn.gov.zcy</groupId>
    <artifactId>afterimage-integration-zcy</artifactId>
    <version>2.0.0-SNAPSHOT</version>
</dependency>
  • 如果是spring,请使用注解@EnableAfterimage开启, 然后在需要的方法(可被spring aop切面)加上注解@Afterimage开启。
  • eg: 1、启动时开启Afterimage,如果是spring boot 环境,会自动配置开启,
  • 如果spring-boot,不想启动时自动开启可配置afterimage.spring.bootstrap.enabled=false
@EnableAfterimage
public class Application{
}
  • 开启后,使用在需要优化的方法(可被spring aop切面),使被注解的方法开启afterimage
  • 如果想在运行时关闭,请配置:afterimage.spring.enabled=false
public class ItemServiceImpl{
    @Afterimage
    public Item find(){        
    }
}
  • 执行流程
  • 1、afterimage-config 以扩展配置读取、监听的扩展
  • 第一块:apollo配置获取,监听事件变更
  • 第二块:spring配置 ,将残影实例自动配置到Spring中
  • config 扩展
  • 作用:统计每个dubbo方法的缓存时间
  • 定义的方法:default get(key,defaultValue)、get(key)、default ddListener(key,configListenr) 如果对应key发生变化,调用listener、default removeListener(configListenr) 移除监听器、default removeListener(key, configListenr) 移除监听器
  • 实现类1
  • ApolloConfig(apollo配置)
  • 继承apollo的ConfigChangeListener接口实现了ApolloListener,实现其onChange事件
  • onChange方法里面,遍历所有改变的key,如果等于当前key,监听其改变
  • 补充了addListener方法和removeListener方法
  • 使用了写时复制ArraySet,因为配置读取的场景读多写少
  • 组合apolloConfig,并实现了Config的get方法,底层调用apolloConfig的getProperty方法
  • 实现了addListener(key,configListenr)方法,先创建监听,然后添加监听,如果apolloListener监听的数量等于1,底层调用apolloConfig的addChangeListener方法
  • 实现类removeListener(configListenr)方法,apolloListener移除监听,检查ApolloListener,为空则移除
  • 实现类removeListener(key, configListenr)方法,获取apolloListener监听器,如果为空,返回,否则,移除监听器,检查ApolloListener,为空则移除
  • 实现类2
  • SpringConfig(Spring配置)
  • 先实例化自身,然后获取系统参数
  • 实现了get(key)方法,如果系统参数为空,抛错,否则,有key获取系统参数
  • 实现类3
  • CompositeConfig(组合配置)
  • 实现了get(String key)方法,遍历每一个configList,查询config,如果能找到值,返回,否则,返回null
  • 实现了addListener(key, ConfigListener),给configList添加监听器
  • 实现了removeListener(ConfigListener)方法, 给configList移除监听器
  • 实现了removeListener(key, ConfigListener)方法, 给configList移除监听器
  • 实现类4
  • SystemConfig (系统配置)
  • 实现了get(key)方法,获取系统的值
  • 读取配置的顺序
  • apollo配置
  • 在resources资源文件夹下的META-INF/afterimage/ConfigProvider.def中配置, 格式如:order,name,providerClass,选择时,order小的优先,可以以#开头在上一行添加注释

100,ApolloConfig,cn.gov.zcy.afterimage.config.apollo.ApolloConfigProvider

  • Apollo环境可引入afterimage-config-apollo来支持apollo的配置读取、以及动态配置监听
<dependency>
    <groupId>cn.gov.zcy</groupId>
    <artifactId>afterimage-config-apollo</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

  • Spring配置
  • 在resources资源文件夹下的META-INF/afterimage/ConfigProvider.def中配置

0,SpringConfig,cn.gov.zcy.afterimage.config.spring.SpringConfigProvider

  • 系统配置
  • 在resources资源文件夹下的META-INF/afterimage/ConfigProvider.def中配置

1000,SystemConfig,cn.gov.zcy.afterimage.core.config.SystemConfigProvider

  • 默认配置为spring优先、apollo次之、System.getProperty最低
  • 配置的读取将按照spi的order配置,顺序从小到大读取,取到第一个不为null则返回
  • 也可以再启动时,设置-Dafterimage.config.order=SpringConfig,ApolloConfig 指定顺序,未指定的配置扩展将按默认顺序对应追加在后面
  • ObjectProvider 接口
  • 提供的方法:get()
  • 实现类
  • 实现类1、ApolloConfigProvider
  • NameSpace:afterimage.apollo.namespace
  • 实现了get()方法 --》从系统参数中获取名称空间,如果名称空间非空,获取apollo中当前名称空间的配置,否则:获取apollo “application”名称空间的配置项
  • 实现类2:SpringConfigProvider
  • 实现了get()方法 --》从SpringConfig获取实例
  • 实现类3:SystemConfigProvider
  • 实现了get()方法 --》获取SystemConfig实例
  • 实现类4:NopAlbumProvider
  • 实现了get()方法 --》获取NopAlbum实例
  • 实现类5:SoftReferenceAlbumProvider
  • 实现了get()方法 --》获取软引用类型ReferenceAlbum实例
  • 实现类6:StrongReferenceAlbumProvider
  • 实现了get()方法 --》获取强引用类型ReferenceAlbum实例
  • 实现类7:WeakReferenceAlbumProvider
  • 实现了get()方法 --》获取虚引用类型ReferenceAlbum实例
  • 2、afterimage-album 扩展调用结果的存储
  • 作用:存储dubbo接口调用结果
  • 定义的方法
  • init() 初始化,
  • destory() 销毁,
  • write(contextId,key,value,超期时间)存入数据,获取残影系统上下文数据,如果值为空,返回;如果上下文为空,抛错,获取上下文中的超期时间,如果这个时间为空,取入参中传递过来的超期时间,写入;
  • dowrite(contextId,key,value,超期时间)方法, 为null或小于1,将不过期
  • read(ContextId contextId, String key) 读取
  • clear(ContextId contextId, String key) 清理
  • clear(ContextId contextId) 清空整个context
  • 实现类
  • 实现类1:抽象类 AbstractAlbum
  • 实现了dowrite(contextId,key,value,超期时间)方法,获取-当不存在时,创建新的上下文,组装ValueWrapper(value,超期时间,系统时间)
  • 实现了read(ContextId contextId, String key),获取上下文,如果为空,return,否则 --》获取valueWrapper ,如果没有超期(时间为空或者小于1ms)–》返回valueWrapper中值 --》如果有配置超期时间,获取当前时间,减去valueWrapper中的系统时间,比较valueWrapper中的超期时间,如果大于 --》移除上下文,否则返回valueWrapper中的值
  • 实现了clear(ContextId contextId, String key), 获取上下文,移除对应的key
  • 提供了两抽象类
  • 1、getOrCreate(contextId) 获取或创建上下文
  • 2、get(ContextId contextId) 获取上下文
  • 实现类:ReferenceAlbum
  • Map类型 字段album,使用了ValueReference(有三个实现类,后面讲解)
  • 字段strength,枚举类型(STRONG强引用 SOFT软引用 -在内存不足时回收,每MB空余可保留1s,WEAK弱引用-GC就被回收 )
  • 提供了一个抽象方法referenceValue
  • 实现了三个静态内部类
  • StrongValueReference实现ValueReference接口,实现了get方法
  • SoftValueReference继承了SoftReference 实现了ValueReference
  • WeakValueReference继承了WeakReference 实现了ValueReference
  • 实现了方法init()
  • 实现了方法destory() 调用 album的清理
  • 实现了方法clear() 调用 album的remove
  • 实现了父类的抽象方法getOrCreate(contextId) 由context获取album Map的value,如果为空,说明需要初始化,给album初始化一个空的map,否则,返回map
  • 实现了父类的抽象方法get(contextId) 由context获取album Map的value,如果为空,返回空,否则,返回map
  • 实现类2:NopAlbum
  • 实现了这几个方法,都是空实现
  • init()方法初始化
  • destory() 销毁
  • doWrite(ContextId contextId, String key, Object value, Integer expireTimeMills) 存入
  • read(ContextId contextId, String key) 返回null
  • clear(ContextId contextId, String key) 清除第一个
  • clear(ContextId contextId) 清空
  • 实现类3:ReferenceAlbum 使用了引用实现,方便帮助GC 见上文
  • Album配置
  • 在resources资源文件夹下的META-INF/afterimage/AlbumProvider.def中配置,格式如:order,name,providerClass,选择时,order小的优先,可以以#开头在上一行添加注释
0,SoftReferenceAlbum,cn.gov.zcy.afterimage.core.album.reference.SoftReferenceAlbumProvider
100,WeakReferenceAlbum,cn.gov.zcy.afterimage.core.album.reference.WeakReferenceAlbumProvider
1000,StrongReferenceAlbum,cn.gov.zcy.afterimage.core.album.reference.StrongReferenceAlbumProvider
10000,NopAlbum,cn.gov.zcy.afterimage.core.album.NopAlbumProvider
  • 默认实现:
  • 0,SoftReferenceAlbum,cn.gov.zcy.afterimage.core.album.reference.SoftReferenceAlbumProvider
  • 软引用map实现,help gc
  • 100,WeakReferenceAlbum,cn.gov.zcy.afterimage.core.album.reference.WeakReferenceAlbumProvider
  • 弱引用map实现,help gc
  • 1000,DefaultAlbum,cn.gov.zcy.afterimage.core.album.reference.StrongReferenceAlbumProvider
  • map实现
  • 10000,NopAlbum,cn.gov.zcy.afterimage.core.album.NopAlbumProvider
  • 空实现
  • 只能使用一个具体实现,默认取order最小的那一个
  • 3、afterimage-captor 用来按需捕获调用结果进行存储
  • 背景知识:dubbo SPI 见上文dubbo filter的使用
  • 配置项为:afterimage.captor.dubbo.config
  • 配置格式:接口名1#方法名1=过期时间毫秒&方法名2=过期时间毫秒,接口名2#方法名1=过期时间&方法名2=过期时间
  • 可用*匹配所有方法名;过期时间单位为毫秒,当未配置或者小于1时,代表不过期,特别注意:当被优化方法执行完毕时,执行期间存储的调用将自动失效。
  • 配置eg: com.A#a=1&b&c=2,com.B#*=1
  • 目前不支持重载方法不同配置
  • AfterimageCaptorFilter实现了dubbo filter,使用代理设计模式,在调用dubbo接口前,先查询album是否有返回结果,在dubbo接口调用之后,将调用id和rpc结果放入到album中
  • 执行时机:消费方
  • **执行过程简述:**先获取dubbo配置,查询db(album)中是否存在该dubbo接口执行结果,有结果,直接返回该数据,否则,执行远程rpc调用,然后将方法入参和调用结果缓存到db(album)中
  • 类似于查询redis,查不到就查询db,并将结果放到redis中
  • 添加Activate注解,标识其为被代理对象,其注解含义如下
  • group :所属组:消费者,只能在消费端使用
  • order: 多个filter的执行顺序(越小越早)
  • 文件名:com.alibaba.dubbo.rpc.Filter 对于Filter的接口
  • 执行过程详述:在resources目录下新建META-INF文件夹,然后建立子文件夹dubbo,最后新建文件com.alibaba.dubbo.rpc.Filter --》key为过滤器的实例名,value为过滤器的全类名 --》在dubbo接口执行之前,会进入拦截器里面 --》
  • 在拦截器里面 --》先获取CompositeConfig配置,如果配置项不存在或者开关未开启,提前return --》否则,获取配置项,优先上下文配置,获取dubbo接口全路径,不存在的话,获取Config中的数据 --》读取配置项,入参为原始配置 + dubbo执行信息,在工具类里面获取dubboConfig --》获取超期时间 --》如果获取的配置为空,执行invoke方法调用远程rpc,否则获取上下文,然后生成调用id --》获取应用程序信息,group信息,版本信息,接口名和方法名,入参类型信息(用逗号链接),入参信息(用逗号链接) --》使用 + 将上述全部信息连接后返回 --》获取db数据(album),由上下文+dubbo信息查询album中是否存在数据,如果为空,返回null,否则 --》判断是否有设置超期时间,如果没有设置,返回album对应的值,–》如果已经超期了,从album中删除数据,否则,返回album对应的值 --》有值,说明近期有调用,AsyncRpcResult返回该值,否则,没有结果
  • 执行rpc调用,拿到返回结果,如果返回结果没有异常,将结果写入到album中,入参为上下文id,dubbo组装参数后的id,rpc调用的结果,超期时间 --》album如果没有key,初始化,然后以dubbo组装参数后的id为key,rpc结果,超期时间,当前时间这三个字段组装的对象为value,存入map中
  • 如果这个过程中发生了异常,分类讨论,如果执行了远程rpc,并且结果非空,返回执行结果,结果为空,抛出异常 --》没有执行远程rpc,此时调用远程rpc接口,并返回
  • Action:这个兜底逻辑中,执行远程rpc后,没有把执行结构放入到album中
  • 4、afterimage-boot 启动afterimage
  • 实现了切面逻辑 ,源码分析如下
  • 注入切面的逻辑
  • 5、afterimage-core 核心类,
  • 定义了spi拓展接口:
  • cn.gov.zcy.afterimage.core.config.Config:可用于配置读取、监听的扩展
  • cn.gov.zcy.afterimage.core.album.Album:用于存储调用结果
  • 6、afterimage-boot-dubbo模块
  • AfterimageBootFilter实现了dubbo filter,使用代理设计模式,在调用dubbo接口前,先查询album是否有返回结果,在dubbo接口调用之后,将调用id和rpc结果放入到album中
  • 执行时机:生产方
  • 执行过程简述:先获取dubbo配置,查询Config中配置是否开启,没开启,执行远程rpc,否则,查询配置项,有方法入参查询超期时间,配置超期时间,执行rpc调用,最后清理db(album) 数据
  • 可以类似于redis中:缓存时间到期了,清理redis缓存
  • Action:这个操作不优雅,它是在每次调用dubbo接口时,判断当前执行的方法有没有过期,可以模仿redis删除key的实现思路
  • 添加Activate注解,标识其为被代理对象,其注解含义如下
  • group :所属组:提供者,只能在服务提供端使用
  • 前提:需要引入对应captor才会优化相应的调用
  • 配置项为:afterimage.boot.dubbo.config
  • 配置格式:接口名1#方法名1=过期时间毫秒&方法名2=过期时间毫秒,接口名2#方法名1&方法名2=过期时间
  • 可用 * 匹配所有方法名;过期时间单位为毫秒,当未配置或者小于1时,代表不过期,特别注意:当被优化方法执行完毕时,执行期间存储的调用将自动失效。
  • 配置eg: com.A#a=1&b&c=2,com.B#*=1
  • 目前不支持重载方法不同配置
  • 在resources目录下新建META-INF文件夹,然后建立子文件夹dubbo,最后新建文件com.alibaba.dubbo.rpc.Filter --》key为过滤器的实例名,value为过滤器的全类名
  • 在服务提供端接口返回之前,会进入拦截器里面 --》首先获取CompositeConfig配置,如果配置项不存在或者开关未开启,执行dubbo接口invoke业务逻辑 --》否则,获取配置项详情,原始配置 格式如:接口名#方法名=过期时间&方法名=过期时间,接口名#方法名=过期时间&方法名=过期时间 --》获取配置详情,如果为空,跳过,否则 --》去除全部空格,接口的配置用’,'隔开,接口名和方法使用“#”分割,如果不合规范,跳过 --》如果当前的接口名与入参接口名相符,继续匹配方法的参数,使用“&”分割,然后使用 “=” 分割入参的key和value,如果key value不是一个pair,跳过,否则,获取入参的key --》如果key为通配符“*” 或者符合入参方法名,执行DubboConfig方法 --》设置超期时间,目前只有expireMills一个配置项,返回DubboConfig —》如果获取到的DubboConfig对象为null,执行dubbo业务逻辑并返回,否则 --》调用startAfterimageManage,底层为AfterimageManage的start1方法,入参为超期时间 --》然后执行dubbo invoke执行业务方法 --》最后,调用AfterimageManage的end方法清理数据
  • Action:这个过滤器如果执行报错,不需要补偿吗?
  • 残影系统使用的设计模式:
  • 1、代理模式 在dubbo invoke之前和之后执行某些操作
  • 2、filter模式:拦截器设计模式
  • 源码分析:
  • 入口:切面AfterimageAspectj
  • 在构造器里面初始化,如果已经初始化,提前return,否则,调用AfterimageManage初始化数据 --》对ConfigLoader进行初始化 --》对AlbumLoader进行初始化 --》环切操作,先判断ConfigLoader中“afterimage.spring.enabled”配置项是否打开,如果没有打开,直接执行业务逻辑,否则 --》调用start0开始执行切面逻辑,然后执行业务逻辑,最后执行残影的清理操作(end方法)
  • AfterimageManage --》初始化init,如果已经初始化,return,否则 --》初始化项目,
  • ConfigLoader
  • order_key:afterimage.config.order
  • PATH = “META-INF/afterimage/ConfigProvider.def” 使用系统配置
  • order:1000
  • name:SystemConfig
  • providerClassName:cn.gov.zcy.afterimage.core.config.SystemConfigProvider
  • CompositeConfig CONFIG
  • 初始化,如果CONFIG非空,说明已经被初始化了,提前return --》 由固定的PATH查询Spi order_key拓展信息 --》加载资源,由path获取类加载器中的urls,–》如果加载出的资源为空,return,否则 --》解析路径,如果路径长度不等于3,抛出异常,否则 --》定义SpiModel,并组装顺序、名称、类名 --》按顺序排序 --》定义组合配置CompositeConfig,将SpiModel转换为CompositeConfig --》按key为name,value为spiModel构建为map --》指定顺序排序(afterimage–config–order) --》循环遍历SpiModel,通过类名获取类实例,然后添加到配置中
  • AlbumLoader
  • ALBUM_KEY = “afterimage.album”
  • PATH = “META-INF/afterimage/AlbumProvider.def”
  • ALBUM
  • List < SpiModel> SPI_MODELS
  • order :0
  • name:SoftReferenceAlbum
  • providerClassName:cn.gov.zcy.afterimage.core.album.reference.SoftReferenceAlbumProvider
  • 初始化 --》如果CONFIG非空,说明已经被初始化了,提前return --》 由固定的PATH查询Spi拓展信息 --》加载资源,由path获取类加载器中的urls,–》如果加载出的资源为空,return,否则 --》解析路径,如果路径长度不等于3,抛出异常,否则 --》定义SpiModel,并组装顺序、名称、类名 --》按顺序排序 --》按key为name,value为spiModel构建为map --》指定顺序排序(afterimage–config–order) --》循环遍历SpiModel,通过类名获取类实例,然后添加到配置中
  • 加载:–》获取SPI_MODELS的第一条数据, --》如果指定了CompositeConfig,使用指定的,否则 --》调用ConfigLoader初始化接口,返回CONFIG --》从配置项中读取“afterimage.album”,使用指定的spiModel --》获取单签拓展点实例信息 --》添加钩子函数,在程序结束时自动销毁album
  • 强制清除方法 forceClear --》获取残影上下文,如果为空,提前return,否则 --》由AlbumLoader获取ALBUM,做清理工作 --》然后由残影上下文中移除ThreadLocal数据
  • start0
  • 执行时机
  • 当进入切面后
  • 业务逻辑:
  • 当某线程连续调用start时,只有第一次的配置生效 --》入参为残影注解,如果没有配置过期时间,返回null --》入参中的captor非空,循环遍历captorConfig --》组装captor(目前仅为dubbo接口),config(dubbo接口的全路径)–》组装到配置项AfterimageConfig中 --》然后调用start(afterimageConfig)方法执行后续逻辑 --》
  • 当嵌套多次start时,计数器会加1,调用end是减1,当为0时,代表上下文安全结束 --》判断是否是新的上下文,如果通过Local能获取上下文,返回该数据,否则 --》 创建一个空的上下文到Local中,返回Local --》计数器自增,如果计数器值不为1,返回false,否则,将入参中的配置放入上下文中,然后返回true
  • start1
  • 执行时机
  • 对于每一个执行的dubbo,都会进入拦截器里面去,然后判断有没有匹配上,有配置上,重新计算超期时间
  • 业务逻辑
  • 当某线程连续调用start时,只有第一次的配置生效 --》过期时间毫秒-为null或小于1,将不过期 --》获取Local里面的上下文,如果数据非空,返回上下文,否则 --》初始化Local后返回 --》计数器自增,如果计数器不为1,返回false,否则,组装配置后,返回true
  • Action:计数器起的作用是啥? 返回的true,false是啥意思?
  • 计数器是为空防止一次请求中,进入切面里面多次
  • Action:提供的两filter方法会拦截全部的dubbo接口,这样做不会影响性能吗?
  • start(expireMills, captorConfigList) 当某线程连续调用start时,只有第一次的配置生效
  • end 在结束后必须调用end --》获取Local中的上下文,如果上下文为空,抛错异常,否则 --》计数器自减 --》如果数量不为0,返回false,标识在其它上下文之中,不用清理数据,否则 --》返回true,获取Album,做清理操作,清理上下文信息,return
  • SystemConfigProvider 系统配置提供方
  • SoftReferenceAlbumProvider

3、SPI总结

1、利用Dubbo SPI机制提供的良好拓展性

  • 1、整个框架中针对不同的场景,恰到好处地使用了各种设计模式
  • 2、基于Dubbo SPI 加载机制,让整个框架的接口和具体实现完全解耦合

2、缓存思想的运用

  • 先获取dubbo配置,查询db(album)中是否存在该dubbo接口执行结果,有结果,直接返回该数据,否则,执行远程rpc调用,然后将方法入参和调用结果缓存到db(album)中
  • 先获取dubbo配置,查询Config中配置是否开启,没开启,执行远程rpc,否则,查询配置项,有方法入参查询超期时间,配置超期时间,执行rpc调用,最后清理db(album) 数据
相关文章
|
26天前
|
存储 缓存 算法
分布式锁服务深度解析:以Apache Flink的Checkpointing机制为例
【10月更文挑战第7天】在分布式系统中,多个进程或节点可能需要同时访问和操作共享资源。为了确保数据的一致性和系统的稳定性,我们需要一种机制来协调这些进程或节点的访问,避免并发冲突和竞态条件。分布式锁服务正是为此而生的一种解决方案。它通过在网络环境中实现锁机制,确保同一时间只有一个进程或节点能够访问和操作共享资源。
59 3
|
10天前
|
负载均衡 监控 Dubbo
Dubbo 原理和机制详解(非常全面)
本文详细解析了 Dubbo 的核心功能、组件、架构设计及调用流程,涵盖远程方法调用、智能容错、负载均衡、服务注册与发现等内容。欢迎留言交流。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Dubbo 原理和机制详解(非常全面)
|
2月前
|
传感器 C# Android开发
深度解析Uno Platform中的事件处理机制与交互设计艺术:从理论到实践的全方位指南,助您构建响应迅速、交互流畅的跨平台应用
Uno Platform 是一款开源框架,支持使用 C# 和 XAML 开发跨平台原生 UI 应用,兼容 Windows、iOS、Android 及 WebAssembly。本文将介绍 Uno Platform 中高效的事件处理方法,并通过示例代码展示交互设计的核心原则与实践技巧,帮助提升应用的用户体验。事件处理让应用能响应用户输入,如点击、触摸及传感器数据变化。通过 XAML 或 C# 添加事件处理器,可确保及时反馈用户操作。示例代码展示了一个按钮点击事件处理过程。此外,还可运用动画和过渡效果进一步增强应用交互性。
144 57
|
10天前
|
存储 缓存 安全
🌟Java零基础:深入解析Java序列化机制
【10月更文挑战第20天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
19 3
|
15天前
|
Java 开发者 UED
Java编程中的异常处理机制解析
在Java的世界里,异常处理是确保程序稳定性和可靠性的关键。本文将深入探讨Java的异常处理机制,包括异常的类型、如何捕获和处理异常以及自定义异常的创建和使用。通过理解这些概念,开发者可以编写更加健壮和易于维护的代码。
|
25天前
【通信协议讲解】单片机基础重点通信协议解析与总结之SPI(二)
【通信协议讲解】单片机基础重点通信协议解析与总结之SPI(二)
中断处理机制解析
【10月更文挑战第5天】中断处理需定义中断处理函数`irq_handler_t`,参数包括中断信号`irq`和通用指针`dev_id`。返回值`IRQ_NONE`表示非本设备中断,`IRQ_HANDLED`表示已处理,`IRQ_WAKE_THREAD`表示需唤醒等待进程。处理程序常分上下半部,关键部分在中断处理函数中完成,延迟部分通过工作队列处理。注册中断处理函数需调用`request_irq`,参数包括中断信号、处理函数、标志位、设备名和通用指针。
|
2月前
|
移动开发 Android开发 数据安全/隐私保护
移动应用与系统的技术演进:从开发到操作系统的全景解析随着智能手机和平板电脑的普及,移动应用(App)已成为人们日常生活中不可或缺的一部分。无论是社交、娱乐、购物还是办公,移动应用都扮演着重要的角色。而支撑这些应用运行的,正是功能强大且复杂的移动操作系统。本文将深入探讨移动应用的开发过程及其背后的操作系统机制,揭示这一领域的技术演进。
本文旨在提供关于移动应用与系统技术的全面概述,涵盖移动应用的开发生命周期、主要移动操作系统的特点以及它们之间的竞争关系。我们将探讨如何高效地开发移动应用,并分析iOS和Android两大主流操作系统的技术优势与局限。同时,本文还将讨论跨平台解决方案的兴起及其对移动开发领域的影响。通过这篇技术性文章,读者将获得对移动应用开发及操作系统深层理解的钥匙。
|
22天前
|
JavaScript 前端开发 开发者
原型链深入解析:JavaScript中的核心机制
【10月更文挑战第13天】原型链深入解析:JavaScript中的核心机制
26 0
|
2月前
|
存储 关系型数据库 MySQL
深入解析MySQL数据存储机制:从表结构到物理存储
深入解析MySQL数据存储机制:从表结构到物理存储
104 1

推荐镜像

更多