• 关于

    开发数据总线介绍

    的搜索结果

回答

一、 Afinal官方介绍:Afinal是一个Android的ioc,orm框架,内置了四大模块功能:FinalAcitivity,FinalBitmap,FinalDb,FinalHttp。通过finalActivity,我们可以通过注解的方式进行绑定ui和事件。通过finalBitmap,我们可以方便的加载bitmap图片,而无需考虑oom等问题。通过finalDB模块,我们一行代码就可以对android的sqlite数据库进行增删改查。通过FinalHttp模块,我们可以以ajax形式请求http数据。详情请通过以下网址查看。Afinal 是一个android的sqlite orm 和 ioc 框架。同时封装了android中的http框架,使其更加简单易用;使用finalBitmap,无需考虑bitmap在android中加载的时候oom的问题和快速滑动的时候图片加载位置错位等问题。Afinal的宗旨是简洁,快速。约定大于配置的方式。尽量一行代码完成所有事情。项目地址:https://github.com/yangfuhai/afinal功能:一个android的ioc,orm框架,内置了四大模块功能:FinalAcitivity,FinalBitmap,FinalDb,FinalHttp。通过finalActivity,我们可以通过注解的方式进行绑定ui和事件。通过finalBitmap,我们可以方便的加载bitmap图片,而无需考虑oom等问题。通过finalDB模块,我们一行代码就可以对android的sqlite数据库进行增删改查。通过FinalHttp模块,我们可以以ajax形式请求http数据。优点:功能比较全面,文档完善,代码效率比较高。缺点:没有项目demo,框架的时间比较久,代码冗余比较多(这也是无可避免的),文档比较老跟不上代码更新进度。(这个评价是其他高人评的,他自己也有写了框架。我个人觉得以前Afinal算是经典了 用的人多)。二、 xUtilsGit地址:https://github.com/wyouflf/xUtilsxUtils:可以说是Afinal的升级版。xUtils 包含了很多实用的android工具。xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响...xUitls 最低兼容android 2.2 (api level 8)三、 ThinkAndroid项目地址:https://github.com/white-cat/ThinkAndroid官方介绍:ThinkAndroid是一个免费的开源的、简易的、遵循Apache2开源协议发布的Android开发框架,其开发宗旨是简单、快速的进行Android应用程序的开发,包含Android mvc、简易sqlite orm、ioc模块、封装Android httpclitent的http模块,具有快速构建文件缓存功能,无需考虑缓存文件的格式,都可以非常轻松的实现缓存,它还基于文件缓存模块实现了图片缓存功能,在android中加载的图片的时候,对oom的问题,和对加载图片错位的问题都轻易解决。他还包括了一个手机开发中经常应用的实用工具类,如日志管理,配置文件管理,android下载器模块,网络切换检测等等工具优点:功能看起来比较完善。个人觉得名字起的好。缺点:从2013年就停止维护了,没有项目文档。四、 LoonAndroid官方介绍:如果你想看ui方面的东西,这里没有,想要看牛逼的效果这里也没有。这只是纯实现功能的框架,它的目标是节省代码量,降低耦合,让代码层次看起来更清晰。整个框架一部分是网上的,一部分是我改的,为了适应我的编码习惯,还有一部分像orm完全是网上的组件。在此感谢那些朋友们。 整个框架式的初衷是为了偷懒,之前都是一个功能一个jar,做项目的时候拉进去,这样对于我来说依然还是比较麻烦。最后就导致我把所有的jar做成了一个工具集合包。 有很多框架都含有这个工具集合里的功能,这些不一定都好用,因为这是根据我个人使用喜欢来实现的,如果你们有自己的想法,可以自己把架包解压了以后,源码拉出来改动下。 目前很多框架都用到了注解,除了androidannotations没有入侵我们应用的代码以外,其他的基本上都有,要么是必须继承框架里面的activity,要么是必须在activity的oncreat里面调用某个方法。 整个框架式不同于androidannotations,Roboguice等ioc框架,这是一个类似spring的实现方式。在整应用的生命周期中找到切入点,然后对activity的生命周期进行拦截,然后插入自己的功能。开源地址:https://github.com/gdpancheng/LoonAndroid功能:1自动注入框架(只需要继承框架内的application既可)2图片加载框架(多重缓存,自动回收,最大限度保证内存的安全性)3网络请求模块(继承了基本上现在所有的http请求)4 eventbus(集成一个开源的框架)5验证框架(集成开源框架)6 json解析(支持解析成集合或者对象)7 数据库(不知道是哪位写的 忘记了)8 多线程断点下载(自动判断是否支持多线程,判断是否是重定向)9 自动更新模块10 一系列工具类有点:功能多缺点:文档方面五、 KJFrameForAndroid项目地址:https://github.com/kymjs/KJFrameForAndroid官方介绍:KJFrameForAndroid 又叫KJLibrary,是一个android的orm 和 ioc 框架。同时封装了android中的Bitmap与Http操作的框架,使其更加简单易用;KJFrameForAndroid的设计思想是通过封装Android原生SDK中复杂的复杂操作而达到简化Android应用级开发,最终实现快速而又安全的开发APP。我们提倡用最少的代码,完成最多的操作,用最高的效率,完成最复杂的功能。功能:一个android的orm 和 ioc 框架。同时封装了android中的Bitmap与Http操作的框架,使其更加简单易用; KJFrameForAndroid开发框架的设计思想是通过封装Android原生SDK中复杂的复杂操作而达到简化Android应用级开发,最终实现快速而又安全的开发APP。总共分为五大模块:UILibrary,UtilsLibrary,HttpLibrary,BitmapLibrary,DBLibrary。优点:功能比较全面,代码效率很高,文档完善,有项目demo,出来的比较晚借鉴了很多大型框架经验。缺点:项目文档是html页面,查看起来很不方便,项目交流平台没多少人说话(难道大神都是不说话的?)(这两个评价是KJFrameForAndroid的作者对自己的评价,个人觉得作者是个天才。他的评价可能刚写完网上发布后写的。我在给他更新评价。因为现在已经过去了几个月一直在时不时更新。功能很全,项目文档也很全面,而且代码里注释最多 这方面这个很难得。交流平台人很多挺热闹,作者希望更热闹这样框架越来越完善。对于初学者希望看到Demo更完善)六、 dhroid官方介绍:dhroid 是基于android 平台, 极速开发框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展.使你更快,更好的开发商业级别应用开源地址: http://git.oschina.net/tengzhinei/dhroid功能:1.Ioc容器: (用过spring的都知道)视图注入,对象注入,接口注入,解决类依赖关系2.Eventbus: android平台事件总线框架,独创延时事件,事件管理轻松3.Dhnet: 网络http请求的解决方案,使用简单,减少代码,自带多种网络访问缓存策略4.adapter模块: 数据绑定轻松,不用写多余的adapter,天生网络支持(一行代码搞定加载,刷新问题)5.DhDb: android中sqlite的最轻量orm框架(增删改查轻松搞定)6.Perference: android自带Perference 升级版,让你的Perference更强大,更方便工具集合 JSONUtil(安全处理json),ViewUtil(数据绑定更快) ThreadWorker(异步任务工具)...优点:功能全面,有demo,作者也是为公司开发的框架。缺点:文档方面现在不是很好,就eoe上的那些。七、 SmartAndroid项目地址:http://www.aplesson.com/smartAndroid/demos官方介绍:SmartAndroid是一套给 Android开发者使用的应用程序开发框架和工具包。它提供一套丰富的标准库以及简单的接口和逻辑结构,其目的是使开发人员更快速地进行项目开发。使用 SmartAndroid可以减少代码的编写量,并将你的精力投入到项目的创造性开发上。功能:SmartAndroid 拥有全范围的类库,可以完成大多数通常需要的APP开发任务,包括: 异步网络操作相关所有功能、强大的图片处理操作、轻量级ORM数据库Sqlite库、zip操作 、动画特效、Html等解析采集、事件总线EventBus/Otto、Gson(Json)、AQuery、主流所有UI控件(例如:ActionbarSherlock,SlidingMenu,BottomView,Actionbar,DragListView等10多种UI库)等。优点:功能非常全,超出你索要、文档完善(作者很全面,官方网站是web响应式网站,框架里功能有UI各种特效应该最全了,一直更新中)缺点:jar包大点?(功能多不可避免,不是问题),在线文档(随响应式的手机访问也方便,但是网速慢就不好了,页面打开不是很流畅)八、 andBase官方介绍:andbase是为Android开发者量身打造的一款开源类库产品开源地址:https://code.jd.com/zhaoqp2010_m/andbase功能:1.andbase中包含了大量的开发常用手段。如网络下载,多线程与线程池的管理,数据库ORM,图片缓存管理,图片文件下载上传,Http请求工具,常用工具类(字符串,日期,文件处理,图片处理工具类等),能够使您的应用在团队开发中减少冗余代码,很大的提高了代码的维护性与开发高效性,能很好的规避由于开发疏忽而导致常犯的错误。2.andbase封装了大量的常用控件。如list分页,下拉刷新,图片轮播,表格,多线程下载器,侧边栏,图片上传,轮子选择,图表,Tab滑动,日历选择器等。3.强大的AbActivity,您没有理由不继承它。继承它你能够获得一个简单强大可设置的操作栏,以及一系列的简单调用,如弹出框,提示框,进度框,副操作栏等。4.提供效率较高图片缓存管理策略,使内存大幅度节省,利用率提高,效率提高。程序中要管理大量的图片资源,andbase提供简单的方法,几步完成下载与显示,并支持缩放,裁剪,缓存功能。5.封装了大量常见工具类。包括日期,字符,文件,图片等各种处理函数,多而全。6.用andbase大量减少handler的使用,而采用回调函数,代码更整洁。handler会产生大量代码,并且不好维护,andbase对handler进行了封装。7.简单轻量支持注解自动建表的ORM框架(支持一/多对多的关联操作)。写sql,建表,工作量大,andbase提供更傻瓜异步增删改查工具类。8.异步请求http框架,网络请求标准化,支持文件上传下载,get,post,进度显示。包含了异步与http请求的工具类,实用。9.热情的支持群体。优点:功能很全,demo做的好 、API文档完善、接近完美缺点:希望文档更详细些。九、 AndroidAnnotations项目地址:https://github.com/excilys/androidannotations功能:完全注解框架,一切皆为注解:声明控件,绑定控件,设置监听,setcontentview,长按事件,异步线程,全部通过注解实现。优点:完全的注解,使开发起来更加便利,程序员写的代码也更少。缺点:文档是全英文的加上功能比较少没有具体研究,由于一切都是注解,感觉效率不高,不过根据官方介绍说并不是使用的反射加载,所以效率比一般注解高很多。十、 volley项目地址: https://github.com/smanikandan14/Volley-demo功能:Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮异步加载网络图片、网络数据优点:Google官方推荐,请看去年的开发者大会介绍。缺点:功能比较少,只有网络数据加载和网络图片加载十一、 android-async-http项目地址:https://github.com/loopj/android-async-http文档介绍:http://loopj.com/android-async-http/ (1) 在匿名回调中处理请求结果 (2) 在UI线程外进行http请求 (3) 文件断点上传 (4) 智能重试 (5) 默认gzip压缩 (6) 支持解析成Json格式 (7) 可将Cookies持久化到SharedPreferences 有点:很简单很实用缺点:功能比较少, (只是针对的功能不是什么缺点)最后来个总结吧: 以上的开发框架网上都可以下载源码,也有demo实例的。当然我没分析和对比框架的效率性能,但是都非常实用,其作者大部分是个人,都是些牛人或天才。你可以直接使用,也可以把有用跳出来用,至少有很多使用工具。如果有发现Bug,作者希望把bug交给他。 Afinal 和 xUtils简单实用但是demo和更新的问题。 KJFrameForAndroid 算是新出的,功能也多,效率也应该好,代码也注释多 用起来也很方便。Dhroid 作者自己公司的框架,也可以直接请教。SmartAndroid 强劲的框架功能俱全。andBase 出来早各个方面算是完整的吧。转自:http://blog.csdn.net/buddyuu/article/details/40503471
元芳啊 2019-12-02 00:55:54 0 浏览量 回答数 0

问题

独家| 对阿里云庞大的技术产品一知半解?这里是16大领域,超过4000个技术问答

hi developers~ 四月初,为解决大家对于云计算问题难以找到正确答案的难题,四位热心大咖做了一件“轰轰烈烈”的事情~我们将阿里云帮助文档中频率出现最高的内容全部整理出来,供大家参考以及查阅...
问问小秘 2020-04-03 13:39:45 14707 浏览量 回答数 10

问题

Nginx性能为什么如此吊

Nginx性能为什么如此吊,Nginx性能为什么如此吊,Nginx性能为什么如此吊 (重要的事情说三遍)的性能为什么如此吊!!!         最近几年,web架构拥抱解耦的...
小柒2012 2019-12-01 21:20:47 15038 浏览量 回答数 3

Quick BI 数据可视化分析平台

2020年入选全球Gartner ABI魔力象限,为中国首个且唯一入选BI产品

回答

相信大家对微服务都不陌生,那我们先来简单回顾下微服务。 微服务架构是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活的服务支持。微服务架构是一种架构思想,实际的开发方式是分布式系统开发。这里只是简单的提一下微服务,接下来直接进入到springcloud微服务架构吧。 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置 和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。 Spring Cloud不是系统架构或某种技术,它是一个生态圈,在这个生态圈内,集合了快速构建分布式系统的一些优秀的组件与框架。 想要使用spring cloud 必须基于 spring boot,SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注于全局的服务治理框架。 在Java生态圈,目前使用较多的微服务框架就是Spring Cloud。它包括: Eureka:服务治理组件,包含服务注册中心、服务注册与发现。 Hystrix:容器管理组件,实现断路器模式,倘若依赖的服务出现延迟或故障,则提供强大的容错功能。 Ribbon:客户端负载均衡的服务调用组件。 Feign:基于Ribbon和Hystrix的声明式服务调用组件。 Zuul:网关组件,提供智能路由、访问过滤等功能。 Spring Cloud Config:配置管理工具,支持使用Git存储配置内容,可以实现应用配置的外部化存储,支持客户端配置信息刷新、加密/解密配置内容等 …… 基于springcloud的微服务总体架构如下: 接下来会对各组件分块进行介绍,本篇文章先介绍Eureka和ribbon。其他组件后续会持续更新。 1、eureka服务发现与注册中心 简介: Spring Cloud Eureka是Spring Cloud Netflix项目下的服务治理模块,负责服务的注册与发现。 组成: 由两个组件组成:Eureka Server和Eureka Client,其中Eureka client可以再分为Service Provider和Service Consumer。 Eureka Server:服务的注册中心,负责维护注册的服务列表。 Service Provider:服务提供方,作为一个Eureka Client,向Eureka Server做服务注册、续约和下线等操作,注册的主要数据包括服务名、机器ip、端口号、域名等等,Eureka Server会存储这些信息 Service Consumer:服务消费方,作为一个Eureka Client,向Eureka Server获取Service Provider的注册信息,并通过远程调用与Service Provider进行通信。 eureka集群 上图为Eureka官方wiki的架构图。 Eureka Server:表示注册中心集群 us-east-xxx:表示集群所在的区域 Application Service:表示服务提供者 Application Client:表示服务消费者 Eureka Client:表示Eureka客户端 如图所示,现在有三个区us-east-1c,us-east-1d,us-east-1e,每个区里都有一个Eureka Server集群,以及不定的Application Service和Application Client。 值得注意的是,注册、续约、下线的请求默认优先选择本区域内的Eureka Server,只有当本区内的Eureka Server都不可用,才会选择其他区的Eureka Server。 2、Ribbon客户端负载均衡组件 Spring Cloud Ribbon 是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。 通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。 Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。 Ribbon 自带的负载均衡策略有如下几个: RoundRibbonRule:轮询。 RandomRule:随机。 AvailabilityFilteringRule:先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,以及并发连接数超过阈值的服务,剩下的服务,使用轮询策略。 WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应越快的服务权重越高,越容易被选中。一开始启动时,统计信息不足的情况下,使用轮询。 RetryRule:先轮询,如果获取失败则在指定时间内重试,重新轮询可用的服务。 BestAvailableRule:先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。 ZoneAvoidanceRule:复合判断 server 所在区域的性能和 server 的可用性选择服务器 3、环境搭建+代码 代码是最好的老师,不多说来敲个例子叭! 本例包含一个Eureka-server集群,和两个Eureka-client。在这里又将Eureka-client分为一个提供者服务provider和一个消费者服务consumer。 一、Eureka-server 1.新建一个空文件夹用IDEA打开 springcloudtest 2.在springcloudtest中新建Module:erueka_server1(erueka_server2,erueka_server3相同,只是yml配置文件不同) pom选择如上图。生成的pom依赖如下 在启动类上加上注释:@EnableEurekaServer yml配置如下: 注意: yml中的hostname: eureka1 需要在当前电脑中进行ip映射: 目录结构如下图 二、Eureka-client 在这里又将Eureka-client分为provider和consumer 先看provider的: 1.新建module:eureka_client_provider pom.xml中依赖为: 2.然后在启动类上加注解:@EnableDiscoveryClient 3.ym配置如下: 4.写一个简单的测试,provider作为consumer的提供者 写一个serviceProviderController类,为consumer调用provider返回一个端口信息。 项目的目录机构如下: 如果有多个提供者写法同上。 再来看consumer的 1.新建module:eureka_client_consumer pom.xml依赖: 2.在启动类上添加注解:@EnableDiscoveryClient 3.yml配置 4.开启ribbon的负载均衡功能 写RestTemplateConfiguration类,加上注释:@LoadBalanced 5.写一个简单的测试! 目录结构如下: 需要多个consumer的时候和上面写法一样。 测试 启动后,访问consumer即可,项目没开就不截图了。 欢迎大家批评指正,有兴趣可以一起探讨呀~
剑曼红尘 2020-03-09 11:53:44 0 浏览量 回答数 0

回答

服务器和操作系统 1、主板的两个芯片分别是什么芯片,具备什么作用? 北桥:离CPU近,负责CPU、内存、显卡之间的通信。 南桥:离CPU远,负责I/O总线之间的通信。 2、什么是域和域控制器? 将网络中的计算机逻辑上组织到一起,进行集中管理,这种集中管理的环境称为域。 在域中,至少有一台域控制器,域控制器中保存着整个域的用户账号和安全数据,安装了活动目录的一台计算机为域控制器,域管理员可以控制每个域用户的行为。 3、现在有300台虚拟机在云上,你如何进行管理? 1)设定堡垒机,使用统一账号登录,便于安全与登录的考量。 2)使用ansiable、puppet进行系统的统一调度与配置的统一管理。 3)建立简单的服务器的系统、配置、应用的cmdb信息管理。便于查阅每台服务器上的各种信息记录。 4、简述raid0 raid1 raid5 三种工作模式的工作原理及特点 磁盘冗余阵列(Redundant Arrays of Independent Disks,RAID),把硬盘整合成一个大磁盘,在大磁盘上再分区,存放数据、多块盘放在一起可以有冗余(备份)。 RAID整合方式有很多,常用的:0 1 5 10 RAID 0:可以是一块盘和N个盘组合 优点:读写快,是RAID中最好的 缺点:没有冗余,一块坏了数据就全没有了 RAID 1:只能2块盘,盘的大小可以不一样,以小的为准 10G+10G只有10G,另一个做备份。它有100%的冗余,缺点:浪费资源,成本高 RAID 5 :3块盘,容量计算10*(n-1),损失一块盘 特点:读写性能一般,读还好一点,写不好 总结: 冗余从好到坏:RAID1 RAID10 RAID 5 RAID0 性能从好到坏:RAID0 RAID10 RAID5 RAID1 成本从低到高:RAID0 RAID5 RAID1 RAID10 5、linux系统里,buffer和cache如何区分? buffer和cache都是内存中的一块区域,当CPU需要写数据到磁盘时,由于磁盘速度比较慢,所以CPU先把数据存进buffer,然后CPU去执行其他任务,buffer中的数据会定期写入磁盘;当CPU需要从磁盘读入数据时,由于磁盘速度比较慢,可以把即将用到的数据提前存入cache,CPU直接从Cache中拿数据要快的多。 6、主机监控如何实现? 数据中心可以用zabbix(也可以是nagios或其他)监控方案,zabbix图形界面丰富,也自带很多监控模板,特别是多个分区、多个网卡等自动发现并进行监控做得非常不错,不过需要在每台客户机(被监控端)安装zabbix agent。 如果在公有云上,可以使用云监控来监控主机的运行。 网络 7、主机与主机之间通讯的三要素有什么? IP地址、子网掩码、IP路由 8、TCP和UDP都可以实现客户端/服务端通信,这两个协议有何区别? TCP协议面向连接、可靠性高、适合传输大量数据;但是需要三次握手、数据补发等过程,耗时长、通信延迟大。 UDP协议面向非连接、可靠性低、适合传输少量数据;但是连接速度快、耗时短、延迟小。 9、简述TCP协议三次握手和四次分手以及数据传输过程 三次握手: (1)当主机A想同主机B建立连接,主机A会发送SYN给主机B,初始化序列号seq=x。主机A通过向主机B发送SYS报文段,实现从主机A到主机B的序列号同步,即确定seq中的x。 (2)主机B接收到报文后,同意与A建立连接,会发送SYN、ACK给主机A。初始化序列号seq=y,确认序号ack=x+1。主机B向主机A发送SYN报文的目的是实现从主机B到主机A的序列号同步,即确定seq中的y。 (3)主机A接收到主机B发送过来的报文后,会发送ACK给主机B,确认序号ack=y+1,建立连接完成,传输数据。 四次分手: (1)当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段,初始化序号seq=x。 (2)主机B收到这个FIN报文段,并不立即用FIN报文段回复主机A,而是想主机A发送一个确认序号ack=x+1,同时通知自己的应用程序,对方要求关闭连接(先发ack是防止主机A重复发送FIN报文)。 (3)主机B发送完ack确认报文后,主机B 的应用程序通知TCP我要关闭连接,TCP接到通知后会向主机A发送一个带有FIN附加标记的报文段,初始化序号seq=x,ack=x+1。 (4)主机A收到这个FIN报文段,向主机B发送一个ack确认报文,ack=y+1,表示连接彻底释放。 10、SNAT和DNAT的区别 SNAT:内部地址要访问公网上的服务时(如web访问),内部地址会主动发起连接,由路由器或者防火墙上的网关对内部地址做个地址转换,将内部地址的私有IP转换为公网的公有IP,网关的这个地址转换称为SNAT,主要用于内部共享IP访问外部。 DNAT:当内部需要提供对外服务时(如对外发布web网站),外部地址发起主动连接,由路由器或者防火墙上的网关接收这个连接,然后将连接转换到内部,此过程是由带有公网IP的网关替代内部服务来接收外部的连接,然后在内部做地址转换,此转换称为DNAT,主要用于内部服务对外发布。 数据库 11、叙述数据的强一致性和最终一致性 强一致性:在任何时刻所有的用户或者进程查询到的都是最近一次成功更新的数据。强一致性是程度最高一致性要求,也是最难实现的。关系型数据库更新操作就是这个案例。 最终一致性:和强一致性相对,在某一时刻用户或者进程查询到的数据可能都不同,但是最终成功更新的数据都会被所有用户或者进程查询到。当前主流的nosql数据库都是采用这种一致性策略。 12、MySQL的主从复制过程是同步的还是异步的? 主从复制的过程是异步的复制过程,主库完成写操作并计入binlog日志中,从库再通过请求主库的binlog日志写入relay中继日志中,最后再执行中继日志的sql语句。 **13、MySQL主从复制的优点 ** 如果主服务器出现问题,可以快速切换到从服务器提供的服务; 可以在从服务器上执行查询操作,降低主服务器的访问压力; 可以在从服务器上执行备份,以避免备份期间影响主服务器的服务。 14、redis有哪些数据类型? (一)String 最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。 (二)hash 这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。 (三)list 使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。 (四)set 因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。 另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。 (五)Zset Zset多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。另外,sorted set可以用来做延时任务。最后一个应用就是可以做范围查找。 15、叙述分布式数据库及其使用场景? 分布式数据库应该是数据访问对应用透明,每个分片默认采用主备架构,提供灾备、恢复、监控、不停机扩容等整套解决方案,适用于TB或PB级的海量数据场景。 应用 16、Apache、Nginx、Lighttpd都有哪些特点? Apache特点:1)几乎可以运行在所有的计算机平台上;2)支持最新的http/1.1协议;3)简单而且强有力的基于文件的配置(httpd.conf);4)支持通用网关接口(cgi);5)支持虚拟主机;6)支持http认证,7)集成perl;8)集成的代理服务器;9)可以通过web浏览器监视服务器的状态,可以自定义日志;10)支持服务器端包含命令(ssi);11)支持安全socket层(ssl);12)具有用户绘画过程的跟踪能力;13)支持fastcgi;14)支持java servlets Nginx特点:nginx是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP代理服务器,处理静态文件,索引文件以及自动索引,无缓存的反向代理加速,简单的负载均衡和容错,具有很高的稳定性,支持热部署。 Lighttpd特点:是一个具有非常低的内存开销,CPU占用率低,效能好,以及丰富的模块,Lighttpd是众多opensource轻量级的webserver中较为优秀的一个,支持fastcgi,cgi,auth,输出压缩,url重写,alias等重要功能。 17、LVS、NGINX、HAPROXY的优缺点? LVS优点:具有很好的可伸缩性、可靠性、可管理性。抗负载能力强、对内存和CPU资源消耗比较低。工作在四层上,仅作分发,所以它几乎可以对所有的应用做负载均衡,且没有流量的产生,不会受到大流量的影响。 LVS缺点:软件不支持正则表达式处理,不能做动静分离,如果web应用比较庞大,LVS/DR+KEEPALIVED实施和管理比较复杂。相对而言,nginx和haproxy就简单得多。 nginx优点:工作在七层之上,可以针对http应用做一些分流的策略。比如针对域名、目录结构。它的正则规则比haproxy更为强大和灵活。对网络稳定性依赖非常小。理论上能PING就能进行负载均衡。配置和测试简单,可以承担高负载压力且稳定。nginx可以通过端口检测到服务器内部的故障。比如根据服务器处理网页返回的状态码、超时等。并且可以将返回错误的请求重新发送给另一个节点,同时nginx不仅仅是负载均衡器/反向代理软件。同时也是功能强大的web服务器,可以作为中层反向代理、静态网页和图片服务器使用。 nginx缺点:不支持URL检测,仅支持HTTP和EMAIL,对session的保持,cookie的引导能力相对欠缺。 Haproxy优点:支持虚拟主机、session的保持、cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态。支持TCP协议的负载均衡;单纯从效率上讲比nginx更出色,且负载策略非常多。 aproxy缺点:扩展性能差;添加新功能很费劲,对不断扩展的新业务很难对付。 18、什么是中间件?什么是jdk? 中间件介绍: 中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源 中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯 是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口 但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递 通过中间件,应用程序可以工作于多平台或OS环境。 jdk:jdk是Java的开发工具包 它是一种用于构建在 Java 平台上发布的应用程序、applet 和组件的开发环境 19、日志收集、日志检索、日志展示的常用工具有哪些? ELK或EFK。 Logstash:数据收集处理引擎。支持动态的从各种数据源搜集数据,并对数据进行过滤、分析、丰富、统一格式等操作,然后存储以供后续使用。 Kibana:可视化化平台。它能够搜索、展示存储在 Elasticsearch 中索引数据。使用它可以很方便的用图表、表格、地图展示和分析数据。 Elasticsearch:分布式搜索引擎。具有高可伸缩、高可靠、易管理等特点。可以用于全文检索、结构化检索和分析,并能将这三者结合起来。Elasticsearch 基于 Lucene 开发,现在使用最广的开源搜索引擎之一,Wikipedia 、StackOverflow、Github 等都基于它来构建自己的搜索引擎。 Filebeat:轻量级数据收集引擎。基于原先 Logstash-fowarder 的源码改造出来。换句话说:Filebeat就是新版的 Logstash-fowarder,逐渐取代其位置。 20、什么是蓝绿发布和灰度发布? 蓝绿:旧版本-新版本 灰度:新旧版本各占一定比例,比例可自定义 两种发布都通过devops流水线实现
剑曼红尘 2020-03-23 15:51:44 0 浏览量 回答数 0

回答

重试作用: 对于重试是有场景限制的,不是什么场景都适合重试,比如参数校验不合法、写操作等(要考虑写是否幂等)都不适合重试。 远程调用超时、网络突然中断可以重试。在微服务治理框架中,通常都有自己的重试与超时配置,比如dubbo可以设置retries=1,timeout=500调用失败只重试1次,超过500ms调用仍未返回则调用失败。 比如外部 RPC 调用,或者数据入库等操作,如果一次操作失败,可以进行多次重试,提高调用成功的可能性。 优雅的重试机制要具备几点: 无侵入:这个好理解,不改动当前的业务逻辑,对于需要重试的地方,可以很简单的实现 可配置:包括重试次数,重试的间隔时间,是否使用异步方式等 通用性:最好是无改动(或者很小改动)的支持绝大部分的场景,拿过来直接可用 优雅重试共性和原理: 正常和重试优雅解耦,重试断言条件实例或逻辑异常实例是两者沟通的媒介。 约定重试间隔,差异性重试策略,设置重试超时时间,进一步保证重试有效性以及重试流程稳定性。 都使用了命令设计模式,通过委托重试对象完成相应的逻辑操作,同时内部封装实现重试逻辑。 Spring-tryer和guava-tryer工具都是线程安全的重试,能够支持并发业务场景的重试逻辑正确性。 优雅重试适用场景: 功能逻辑中存在不稳定依赖场景,需要使用重试获取预期结果或者尝试重新执行逻辑不立即结束。比如远程接口访问,数据加载访问,数据上传校验等等。 对于异常场景存在需要重试场景,同时希望把正常逻辑和重试逻辑解耦。 对于需要基于数据媒介交互,希望通过重试轮询检测执行逻辑场景也可以考虑重试方案。 优雅重试解决思路: 切面方式 这个思路比较清晰,在需要添加重试的方法上添加一个用于重试的自定义注解,然后在切面中实现重试的逻辑,主要的配置参数则根据注解中的选项来初始化 优点: 真正的无侵入 缺点: 某些方法无法被切面拦截的场景无法覆盖(如spring-aop无法切私有方法,final方法) 直接使用aspecj则有些小复杂;如果用spring-aop,则只能切被spring容器管理的bean 消息总线方式 这个也比较容易理解,在需要重试的方法中,发送一个消息,并将业务逻辑作为回调方法传入;由一个订阅了重试消息的consumer来执行重试的业务逻辑 优点: 重试机制不受任何限制,即在任何地方你都可以使用 利用EventBus框架,可以非常容易把框架搭起来 缺点: 业务侵入,需要在重试的业务处,主动发起一条重试消息 调试理解复杂(消息总线方式的最大优点和缺点,就是过于灵活了,你可能都不知道什么地方处理这个消息,特别是新的童鞋来维护这段代码时) 如果要获取返回结果,不太好处理, 上下文参数不好处理 模板方式 优点: 简单(依赖简单:引入一个类就可以了; 使用简单:实现抽象类,讲业务逻辑填充即可;) 灵活(这个是真正的灵活了,你想怎么干都可以,完全由你控制) 缺点: 强侵入 代码臃肿 把这个单独捞出来,主要是某些时候我就一两个地方要用到重试,简单的实现下就好了,也没有必用用到上面这么重的方式;而且我希望可以针对代码快进行重试 这个的设计还是非常简单的,基本上代码都可以直接贴出来,一目了然: 复制代码 public abstract class RetryTemplate { private static final int DEFAULT_RETRY_TIME = 1; private int retryTime = DEFAULT_RETRY_TIME; private int sleepTime = 0;// 重试的睡眠时间 public int getSleepTime() { return sleepTime; } public RetryTemplate setSleepTime(int sleepTime) { if(sleepTime < 0) { throw new IllegalArgumentException("sleepTime should equal or bigger than 0"); } this.sleepTime = sleepTime; return this; } public int getRetryTime() { return retryTime; } public RetryTemplate setRetryTime(int retryTime) { if (retryTime <= 0) { throw new IllegalArgumentException("retryTime should bigger than 0"); } this.retryTime = retryTime; return this; } /** * 重试的业务执行代码 * 失败时请抛出一个异常 * * todo 确定返回的封装类,根据返回结果的状态来判定是否需要重试 * * @return */ protected abstract Object doBiz() throws Exception; //预留一个doBiz方法由业务方来实现,在其中书写需要重试的业务代码,然后执行即可 public Object execute() throws InterruptedException { for (int i = 0; i < retryTime; i++) { try { return doBiz(); } catch (Exception e) { log.error("业务执行出现异常,e: {}", e); Thread.sleep(sleepTime); } } return null; } public Object submit(ExecutorService executorService) { if (executorService == null) { throw new IllegalArgumentException("please choose executorService!"); } return executorService.submit((Callable) () -> execute()); } } 复制代码 使用示例: 复制代码 public void retryDemo() throws InterruptedException { Object ans = new RetryTemplate() { @Override protected Object doBiz() throws Exception { int temp = (int) (Math.random() * 10); System.out.println(temp); if (temp > 3) { throw new Exception("generate value bigger then 3! need retry"); } return temp; } }.setRetryTime(10).setSleepTime(10).execute(); System.out.println(ans); } 复制代码 spring-retry Spring Retry 为 Spring 应用程序提供了声明性重试支持。 它用于Spring批处理、Spring集成、Apache Hadoop(等等)的Spring。 在分布式系统中,为了保证数据分布式事务的强一致性,在调用RPC接口或者发送MQ时,针对可能会出现网络抖动请求超时情况采取一下重试操作。 用的最多的重试方式就是MQ了,但是如果你的项目中没有引入MQ,就不方便了。 还有一种方式,是开发者自己编写重试机制,但是大多不够优雅。 缺陷 spring-retry 工具虽能优雅实现重试,但是存在两个不友好设计: 一个是重试实体限定为 Throwable 子类,说明重试针对的是可捕捉的功能异常为设计前提的,但是我们希望依赖某个数据对象实体作为重试实体, 但 sping-retry框架必须强制转换为Throwable子类。 另一个是重试根源的断言对象使用的是 doWithRetry 的 Exception 异常实例,不符合正常内部断言的返回设计。 Spring Retry 提倡以注解的方式对方法进行重试,重试逻辑是同步执行的,当抛出相关异常后执行重试, 如果你要以返回值的某个状态来判定是否需要重试,可能只能通过自己判断返回值然后显式抛出异常了。只读操作可以重试,幂等写操作可以重试,但是非幂等写操作不能重试,重试可能导致脏写,或产生重复数据。 @Recover 注解在使用时无法指定方法,如果一个类中多个重试方法,就会很麻烦。 spring-retry 结构 BackOff:补偿值,一般指失败后多久进行重试的延迟值。 Sleeper:暂停应用的工具,通常用来应用补偿值。 RetryState:重试状态,通常包含一个重试的键值。 RetryCallback:封装你需要重试的业务逻辑(上文中的doSth) RecoverCallback:封装了多次重试都失败后你需要执行的业务逻辑(上文中的doSthWhenStillFail) RetryContext:重试语境下的上下文,代表了能被重试动作使用的资源。可用于在多次Retry或者Retry 和Recover之间传递参数或状态(在多次doSth或者doSth与doSthWhenStillFail之间传递参数) RetryOperations: 定义了“重试”的模板(重试的API),要求传入RetryCallback,可选传入RecoveryCallback; RetryTemplate :RetryOperations的具体实现,组合了RetryListener[],BackOffPolicy,RetryPolicy。 RetryListener:用来监控Retry的执行情况,并生成统计信息。 RetryPolicy:重试的策略或条件,可以简单的进行多次重试,可以是指定超时时间进行重试(上文中的someCondition),决定失败能否重试。 BackOffPolicy: 重试的回退策略,在业务逻辑执行发生异常时。如果需要重试,我们可能需要等一段时间(可能服务器过于繁忙,如果一直不间隔重试可能拖垮服务器),当然这段时间可以是0,也可以是固定的,可以是随机的(参见tcp的拥塞控制算法中的回退策略)。回退策略在上文中体现为wait(); RetryPolicy提供了如下策略实现: NeverRetryPolicy:只允许调用RetryCallback一次,不允许重试; AlwaysRetryPolicy:允许无限重试,直到成功,此方式逻辑不当会导致死循环; SimpleRetryPolicy:固定次数重试策略,默认重试最大次数为3次,RetryTemplate默认使用的策略; TimeoutRetryPolicy:超时时间重试策略,默认超时时间为1秒,在指定的超时时间内允许重试; CircuitBreakerRetryPolicy:有熔断功能的重试策略,需设置3个参数openTimeout、resetTimeout和delegate delegate:是真正判断是否重试的策略,当重试失败时,则执行熔断策略;应该配置基于次数的SimpleRetryPolicy或者基于超时的TimeoutRetryPolicy策略,且策略都是全局模式,而非局部模式,所以要注意次数或超时的配置合理性。 openTimeout:openWindow,配置熔断器电路打开的超时时间,当超过openTimeout之后熔断器电路变成半打开状态(主要有一次重试成功,则闭合电路); resetTimeout:timeout,配置重置熔断器重新闭合的超时时间 CompositeRetryPolicy:组合重试策略,有两种组合方式,乐观组合重试策略是指只要有一个策略允许重试即可以,悲观组合重试策略是指只要有一个策略不允许重试即可以,但不管哪种组合方式,组合中的每一个策略都会执行。 BackOffPolicy 提供了如下策略实现: NoBackOffPolicy:无退避算法策略,即当重试时是立即重试; FixedBackOffPolicy:固定时间的退避策略,需设置参数sleeper(指定等待策略,默认是Thread.sleep,即线程休眠)、backOffPeriod(休眠时间,默认1秒); UniformRandomBackOffPolicy:随机时间退避策略,需设置sleeper、minBackOffPeriod、maxBackOffPeriod,该策略在[minBackOffPeriod,maxBackOffPeriod之间取一个随机休眠时间,minBackOffPeriod默认500毫秒,maxBackOffPeriod默认1500毫秒; ExponentialBackOffPolicy:指数退避策略,需设置参数sleeper、initialInterval、maxInterval和multiplier。initialInterval指定初始休眠时间,默认100毫秒,maxInterval指定最大休眠时间,默认30秒,multiplier指定乘数,即下一次休眠时间为当前休眠时间*multiplier; ExponentialRandomBackOffPolicy:随机指数退避策略,引入随机乘数,固定乘数可能会引起很多服务同时重试导致DDos,使用随机休眠时间来避免这种情况。 RetryTemplate主要流程实现: 复制代码 //示例一 public void upload(final Map<String, Object> map) throws Exception { // 构建重试模板实例 RetryTemplate retryTemplate = new RetryTemplate(); // 设置重试策略,主要设置重试次数 SimpleRetryPolicy policy =         new SimpleRetryPolicy(3, Collections.<Class<? extends Throwable>, Boolean> singletonMap(Exception.class, true)); // 设置重试回退操作策略,主要设置重试间隔时间 FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy(); fixedBackOffPolicy.setBackOffPeriod(100); retryTemplate.setRetryPolicy(policy); retryTemplate.setBackOffPolicy(fixedBackOffPolicy); // 通过RetryCallback 重试回调实例包装正常逻辑逻辑,第一次执行和重试执行执行的都是这段逻辑 final RetryCallback<Object, Exception> retryCallback = new RetryCallback<Object, Exception>() { //RetryContext 重试操作上下文约定,统一spring-try包装 public Object doWithRetry(RetryContext context) throws Exception { System.out.println("do some thing"); Exception e = uploadToOdps(map); System.out.println(context.getRetryCount()); throw e;//这个点特别注意,重试的根源通过Exception返回 } }; // 通过RecoveryCallback 重试流程正常结束或者达到重试上限后的退出恢复操作实例 final RecoveryCallback recoveryCallback = new RecoveryCallback() { public Object recover(RetryContext context) throws Exception { System.out.println("do recory operation"); return null; } }; try { // 由retryTemplate 执行execute方法开始逻辑执行 retryTemplate.execute(retryCallback, recoveryCallback); } catch (Exception e) { e.printStackTrace(); } } //示例二 protected <T, E extends Throwable> T doExecute(RetryCallback<T, E> retryCallback,RecoveryCallback recoveryCallback,   RetryState state) throws E, ExhaustedRetryException { //重试策略 RetryPolicy retryPolicy = this.retryPolicy; //退避策略 BackOffPolicy backOffPolicy = this.backOffPolicy; //重试上下文,当前重试次数等都记录在上下文中 RetryContext context = open(retryPolicy, state); try { //拦截器模式,执行RetryListener#open boolean running = doOpenInterceptors(retryCallback, context); //判断是否可以重试执行 while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) { try {//执行RetryCallback回调 return retryCallback.doWithRetry(context); } catch (Throwable e) {//异常时,要进行下一次重试准备 //遇到异常后,注册该异常的失败次数 registerThrowable(retryPolicy, state, context, e); //执行RetryListener#onError doOnErrorInterceptors(retryCallback, context, e); //如果可以重试,执行退避算法,比如休眠一小段时间后再重试 if (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) { backOffPolicy.backOff(backOffContext); } //state != null && state.rollbackFor(context.getLastThrowable()) //在有状态重试时,如果是需要执行回滚操作的异常,则立即抛出异常 if (shouldRethrow(retryPolicy, context, state)) { throw RetryTemplate. wrapIfNecessary(e); } } //如果是有状态重试,且有GLOBAL_STATE属性,则立即跳出重试终止;       //当抛出的异常是非需要执行回滚操作的异常时,才会执行到此处,CircuitBreakerRetryPolicy会在此跳出循环; if (state != null && context.hasAttribute(GLOBAL_STATE)) { break; } } //重试失败后,如果有RecoveryCallback,则执行此回调,否则抛出异常 return handleRetryExhausted(recoveryCallback, context, state); } catch (Throwable e) { throw RetryTemplate. wrapIfNecessary(e); } finally { //清理环境 close(retryPolicy, context, state, lastException == null || exhausted); //执行RetryListener#close,比如统计重试信息 doCloseInterceptors(retryCallback, context, lastException); } } 复制代码 有状态or无状态 无状态重试,是在一个循环中执行完重试策略,即重试上下文保持在一个线程上下文中,在一次调用中进行完整的重试策略判断。如远程调用某个查询方法时是最常见的无状态重试: 复制代码 RetryTemplate template = new RetryTemplate(); //重试策略:次数重试策略 RetryPolicy retryPolicy = new SimpleRetryPolicy(3); template.setRetryPolicy(retryPolicy); //退避策略:指数退避策略 ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy(); backOffPolicy.setInitialInterval(100); backOffPolicy.setMaxInterval(3000); backOffPolicy.setMultiplier(2); backOffPolicy.setSleeper(new ThreadWaitSleeper()); template.setBackOffPolicy(backOffPolicy); //当重试失败后,抛出异常 String result = template.execute(new RetryCallback<String, RuntimeException>() { @Override public String doWithRetry(RetryContext context) throws RuntimeException { throw new RuntimeException("timeout"); } }); //当重试失败后,执行RecoveryCallback String result = template.execute(new RetryCallback<String, RuntimeException>() { @Override public String doWithRetry(RetryContext context) throws RuntimeException { System.out.println("retry count:" + context.getRetryCount()); throw new RuntimeException("timeout"); } }, new RecoveryCallback () { @Override public String recover(RetryContext context) throws Exception { return "default"; } }); 复制代码 有状态重试,有两种情况需要使用有状态重试,事务操作需要回滚、熔断器模式。 事务操作需要回滚场景时,当整个操作中抛出的是数据库异常DataAccessException,则不能进行重试需要回滚,而抛出其他异常则可以进行重试,可以通过RetryState实现: 复制代码 //当前状态的名称,当把状态放入缓存时,通过该key查询获取 Object key = "mykey"; //是否每次都重新生成上下文还是从缓存中查询,即全局模式(如熔断器策略时从缓存中查询) boolean isForceRefresh = true; //对DataAccessException进行回滚 BinaryExceptionClassifier rollbackClassifier = new BinaryExceptionClassifier(Collections.<Class<? extends Throwable>>singleton(DataAccessException.class)); RetryState state = new DefaultRetryState(key, isForceRefresh, rollbackClassifier); String result = template.execute(new RetryCallback<String, RuntimeException>() { @Override public String doWithRetry(RetryContext context) throws RuntimeException { System.out.println("retry count:" + context.getRetryCount()); throw new TypeMismatchDataAccessException(""); } }, new RecoveryCallback () { @Override public String recover(RetryContext context) throws Exception { return "default"; } }, state); 复制代码 RetryTemplate中在有状态重试时,回滚场景时直接抛出异常处理代码: //state != null && state.rollbackFor(context.getLastThrowable()) //在有状态重试时,如果是需要执行回滚操作的异常,则立即抛出异常 if (shouldRethrow(retryPolicy,context, state)) { throw RetryTemplate. wrapIfNecessary(e); } 熔断器场景。在有状态重试时,且是全局模式,不在当前循环中处理重试,而是全局重试模式(不是线程上下文),如熔断器策略时测试代码如下所示。 复制代码 RetryTemplate template = new RetryTemplate(); CircuitBreakerRetryPolicy retryPolicy = new CircuitBreakerRetryPolicy(new SimpleRetryPolicy(3)); retryPolicy.setOpenTimeout(5000); retryPolicy.setResetTimeout(20000); template.setRetryPolicy(retryPolicy); for (int i = 0; i < 10; i++) { try { Object key = "circuit"; boolean isForceRefresh = false; RetryState state = new DefaultRetryState(key, isForceRefresh); String result = template.execute(new RetryCallback<String, RuntimeException>() { @Override public String doWithRetry(RetryContext context) throws RuntimeException { System.out.println("retry count:" + context.getRetryCount()); throw new RuntimeException("timeout"); } }, new RecoveryCallback () { @Override public String recover(RetryContext context) throws Exception { return "default"; } }, state); System.out.println(result); } catch (Exception e) { System.out.println(e); } } 复制代码 为什么说是全局模式呢?我们配置了isForceRefresh为false,则在获取上下文时是根据key “circuit”从缓存中获取,从而拿到同一个上下文。 Object key = "circuit"; boolean isForceRefresh = false; RetryState state = new DefaultRetryState(key,isForceRefresh); 如下RetryTemplate代码说明在有状态模式下,不会在循环中进行重试。 if (state != null && context.hasAttribute(GLOBAL_STATE)) { break; } 判断熔断器电路是否打开的代码: 复制代码 public boolean isOpen() { long time = System.currentTimeMillis() - this.start; boolean retryable = this.policy.canRetry(this.context); if (!retryable) {//重试失败 //在重置熔断器超时后,熔断器器电路闭合,重置上下文 if (time > this.timeout) { this.context = createDelegateContext(policy, getParent()); this.start = System.currentTimeMillis(); retryable = this.policy.canRetry(this.context); } else if (time < this.openWindow) { //当在熔断器打开状态时,熔断器电路打开,立即熔断 if ((Boolean) getAttribute(CIRCUIT_OPEN) == false) { setAttribute(CIRCUIT_OPEN, true); } this.start = System.currentTimeMillis(); return true; } } else {//重试成功 //在熔断器电路半打开状态时,断路器电路闭合,重置上下文 if (time > this.openWindow) { this.start = System.currentTimeMillis(); this.context = createDelegateContext(policy, getParent()); } } setAttribute(CIRCUIT_OPEN, !retryable); return !retryable; } 复制代码 从如上代码可看出spring-retry的熔断策略相对简单: 当重试失败,且在熔断器打开时间窗口[0,openWindow) 内,立即熔断; 当重试失败,且在指定超时时间后(>timeout),熔断器电路重新闭合; 在熔断器半打开状态[openWindow, timeout] 时,只要重试成功则重置上下文,断路器闭合。 注解介绍 @EnableRetry 表示是否开始重试。 序号 属性 类型 默认值 说明 1 proxyTargetClass boolean false 指示是否要创建基于子类的(CGLIB)代理,而不是创建标准的基于Java接口的代理。当proxyTargetClass属性为true时,使用CGLIB代理。默认使用标准JAVA注解 @Retryable 标注此注解的方法在发生异常时会进行重试 序号 属性 类型 默认值 说明 1 interceptor String ”” 将 interceptor 的 bean 名称应用到 retryable() 2 value class[] {} 可重试的异常类型 3 include class[] {} 和value一样,默认空,当exclude也为空时,所有异常都重试 4 exclude class[] {} 指定异常不重试,默认空,当include也为空时,所有异常都重试 5 label String ”” 统计报告的唯一标签。如果没有提供,调用者可以选择忽略它,或者提供默认值。 6 maxAttempts int 3 尝试的最大次数(包括第一次失败),默认为3次。 7 backoff @Backoff @Backoff() 重试补偿机制,指定用于重试此操作的backoff属性。默认为空 @Backoff 不设置参数时,默认使用FixedBackOffPolicy(指定等待时间),重试等待1000ms 序号 属性 类型 默认值 说明 1 delay long 0 指定延迟后重试 ,如果不设置则默认使用 1000 milliseconds 2 maxDelay long 0 最大重试等待时间 3 multiplier long 0 指定延迟的倍数,比如delay=5000l,multiplier=2时,第一次重试为5秒后,第二次为10秒,第三次为20秒(大于0生效) 4 random boolean false 随机重试等待时间 @Recover 用于恢复处理程序的方法调用的注释。返回类型必须与@retryable方法匹配。 可抛出的第一个参数是可选的(但是没有它的方法只会被调用)。 从失败方法的参数列表按顺序填充后续的参数。 用于@Retryable重试失败后处理方法,此注解注释的方法参数一定要是@Retryable抛出的异常,否则无法识别,可以在该方法中进行日志处理。 说明: 使用了@Retryable的方法不能在本类被调用,不然重试机制不会生效。也就是要标记为@Service,然后在其它类使用@Autowired注入或者@Bean去实例才能生效。 要触发@Recover方法,那么在@Retryable方法上不能有返回值,只能是void才能生效。 使用了@Retryable的方法里面不能使用try...catch包裹,要在发放上抛出异常,不然不会触发。 在重试期间这个方法是同步的,如果使用类似Spring Cloud这种框架的熔断机制时,可以结合重试机制来重试后返回结果。 Spring Retry不只能注入方式去实现,还可以通过API的方式实现,类似熔断处理的机制就基于API方式实现会比较宽松。 转载于:https://www.cnblogs.com/whatarewords/p/10656514.html
养狐狸的猫 2019-12-02 02:11:54 0 浏览量 回答数 0

云产品推荐

上海奇点人才服务相关的云产品 小程序定制 上海微企信息技术相关的云产品 国内短信套餐包 ECS云服务器安全配置相关的云产品 开发者问答 阿里云建站 自然场景识别相关的云产品 万网 小程序开发制作 视频内容分析 视频集锦 代理记账服务 阿里云AIoT