面试-java 高级 进阶一

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1. Java反射

JAVA反射机制是在运行状态中对于任意一个类都能够知道这个类的所有属性和方法对于任意一个对象都能够调用它的任意一个方法和属性这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

1). 调用私有方法, 能Class c1 = obj.getClass();

        Method dm = c1.getDeclaredMethod("doSomingPrivate");

        dm.setAccessible(true); //调用private方法关键设置是false一样会报错。

        dm.invoke(obj);

2). 反射机制优点反射提高了程序的灵活性和扩展性降低耦合性提高自适应能力。它允许程序创和控制任何类的对象无需提前硬编码目标类。可扩展性 应用程序可以利用全限定名创建可扩展对象的实例。

缺点性能开销反射涉及了动态类型的解析所以 JVM 无法对这些代码进行优化。因此反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。安全限制使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行如 Applet那么这就是个问题了。内部暴露由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法所以使用反射可能会导致意料之外的副作用这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性因此当平台发生改变的时候代码的行为就有可能也随着变化。

2. 高并发下的性能优化?

1) html静态化效率最高、消耗最小的就是纯静态化的html页面所以我们尽可能使我们的网站上的页面采用静态页面来实现这个最简单的方法其实也是最有效的方法。

同时可以将页面上常用的查询但更新量很小的数据(如公告信息缓存在页面这样避免了大量的数据库访问请求。

2) 图片服务器分离图片是最消耗资源的于是我们有必要将图片与页面进行分离这是基本上大型网站都会采用的策略他们都有独立的、甚至很多台的图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力并且可以保证系统不会因为图片问题而崩溃。

3) 缓存为了避免每次都向数据库取数据把用户常常访问到的数据放到内存中甚至缓存十分大的时候我们可以把内存中的缓存放到硬盘中。还有高级的分布式缓存数据库使用都可以增加系统的抗压力。

4) 分批传送java+ajax实现数据分批加载到前端: 这里是java后台的一个action函数JSONArray.fromObject(loadPageList).toString()

5) 数据库集群

6) 优化数据库连接, 应用程序和数据库最大连接数量之间要配套根据用户并发量确定最大连接量

7) 程序代码优化

8) 优化日志输出a)用户登录信息等重要事件日志存放在日志表中;b)系统运行时日志通过logger打印到日志文件中。

9) SQL优化

a避免使用select * 查询;模糊查询时尽量百分号在模糊字段后;

b对查询尽量避免全表扫描首先应考虑在 where 及 order by 涉及的列上建立索引。

c应避免在 where 子句中使用!=或<>操作符否则将引擎放弃使用索引而进行全表扫描。

d应避免在 where 子句中对字段进行null值判断否则将导致引擎放弃用索引而全表扫描。

10) 负载均衡, 负载均衡概念公司会建立很多的服务器这些服务器组成了服务器集群然后当用户访问网站的时候先访问一个中间服务器再让这个中间服务器在服务器集群中选择一个压力较小的服务器然后将该访问请求引入选择的服务器。这样都会保证服务器集群中的每个服务器压力趋于平衡分担了服务器压力避免了服务器崩溃的情况。

11) 使用消息队列, 消息队列中间件是分布式系统中重要的组件主要解决应用耦合异步消息流量削锋等问题实现高性能高可用可伸缩最终一致性架构使用较多的消息队列有ActiveMQRabbitMQZeroMQKafkaMetaMQRocketMQ

3. 说说双亲委派

任何一个类都需要这个类本身和加载它的类加载器一同来确定其在虚拟机的唯一性。两个好处1.类伴随它的类加载器一起具备了一种带有优先级的层次关系确保了在各种加载环境的加载顺序。2.保证了运行的安全性防止不可信类扮演可信任的类.

首先得先了解一下类加载阶段。类加载阶段分为加载、连接、初始化三个阶段而加载阶段需要通过类的全限定名来获取定义了此类的二进制字节流。

Java特意把这一步抽出来用类加载器来实现。把这一步骤抽离出来使得应用程序可以按需自定义类加载器。并且得益于类加载器OSGI、热部署等领域才得以在JAVA中得到应用。在Java中任意一个类都是由这个类本身和加载这个类的类加载器来确定这个类在JVM中的唯一性。

Java自身提供了3种类加载器: 1,启动类加载器(Bootstrap ClassLoader),它是属于虚拟机自身的一部分用C++实现的主要负责加载 <JAVA_HOME>\lib目录中或被-Xbootclasspath指定的路径中的并且文件名是被虚拟机识别的文件。它等于是所有类加载器的爸爸。2, 扩展类加载器(Extension ClassLoader),它是Java实现的独立于虚拟机主要负责加载<JAVA_HOME>\lib\ext目录中或被java.ext.dirs系统变量所指定的路径的类库。3,应用程序类加载器(Application ClassLoader),它是Java实现的独立于虚拟机。主要负责加载用户类路径(classPath)上的类库如果我们没有实现自定义的类加载器那这玩意就是我们程序中的默认加载器。双亲委派模型

 双亲委派的意思是如果一个类加载器需要加载类那么首先它会把这个类请求委派给父类加载器去完成每一层都是如此。一直递归到顶层当父加载器无法完成这个请求时子类才会尝试去加载。这里的双亲其实就指的是父类父类也不是我们平日所说的那种继承关系只是调用逻辑是这样。
双亲委派模型不是一种强制性约束也就是你不这么做也不会报错怎样的它是一种JAVA设计者推荐使用类加载器的方式。
双亲委派有啥好处呢?它使得类有了层次的划分。就拿java.lang.Object来说你加载它经过一层层委托最终是由Bootstrap ClassLoader来加载的也就是最终都是由Bootstrap ClassLoader去找<JAVA_HOME>\lib中rt.jar里面的java.lang.Object加载到JVM中。这样如果有不法分子自己造了个java.lang.Object,里面嵌了不好的代码如果我们是按照双亲委派模型来实现的话最终加载到JVM中的只会是我们rt.jar里面的东西也就是这些核心的基础类代码得到了保护。因为这个机制使得系统中只会出现一个java.lang.Object。不会乱套了。你想想如果我们JVM里面有两个Object,那岂不是天下大乱了。

Java就搞了个线程上下文类加载器通过setContextClassLoader()默认情况就是应用程序类加载器然后Thread.current.currentThread().getContextClassLoader()获得类加载器来加载。

Tomcat的webappClassLoader加载自己的目录下的class文件不会传递给父类加载器。tomcat之所以造了一堆自己的classloader大致是出于下面三类目的

对于各个 webapp中的 class和 lib需要相互隔离不能出现一个应用中加载的类库会影响另一个应用的情况而对于许多应用需要有共享的lib以便不浪费资源。

与 jvm一样的安全性问题。使用单独的 classloader去装载 tomcat自身的类库以免其他恶意或无意的破坏;热部署。tomcat修改文件不用重启就自动重新装载类库惊叹吧。

4. Mq的消费一致性

独立消息服务最终一致性目前较为主流的MQ如ActiveMQ、RabbitMQ、Kafka、RocketMQ等只有RocketMQ支持事务消息。早年阿里对MQ增加事务消息也是因为支付宝那边因为业务上的需求而产生的。因此如果我们希望强依赖一个MQ的事务消息来做到消息最终一致性的话在目前的情况下技术选型上只能去选择RocketMQ来解决。分析事务消息所存在的异常情况即MQ存储了待发送的消息但是MQ无法感知到上游处理的最终结果。对于RocketMQ而言它的解决方案非常的简单就是其内部实现会有一个定时任务去轮训状态为待发送的消息然后给producer发送check请求而producer必须实现一个check监听器监听器的内容通常就是去检查与之对应的本地事务是否成功(一般就是查询DB)如果成功了则MQ会将消息设置为可发送否则就删除消息。

事务消息由于传统的处理方式无法解决消息生成者本地事务处理成功与消息发送成功两者的一致性问题因此事务消息就诞生了它实现了消息生成者本地事务与消息发送的原子性保证了消息生成者本地事务处理成功与消息发送成功的最终一致性问题。处理流程

 注意由于MQ通常都会保证消息能够投递成功因此如果业务没有及时返回ACK结果那么就有可能造成MQ的重复消息投递问题。因此对于消息最终一致性的方案消息的消费者必须要对消息的消费支持幂等不能造成同一条消息的重复消费的情况。
不选择RocketMQ为系统的MQ做到消息的最终一致性呢?答案是可以。
基于本地消息的最终一致性方案的最核心做法就是在执行业务操作的时候记录一条消息数据到DB并且消息数据的记录与业务数据的记录必须在同一个事务内完成这是该方案的前提核心保障。在记录完成后消息数据后后面我们就可以通过一个定时任务到DB中去轮训状态为待发送的消息然后将消息投递给MQ。这个过程中可能存在消息投递失败的可能此时就依靠重试机制来保证直到成功收到MQ的ACK确认之后再将消息状态更新或者消息清除;而后面消息的消费失败的话则依赖MQ本身的重试来完成其最后做到两边系统数据的最终一致性。基于本地消息服务的方案虽然可以做到消息的最终一致性但是它有一个比较严重的弊端每个业务系统在使用该方案时都需要在对应的业务库创建一张消息表来存储消息。针对这个问题我们可以将该功能单独提取出来做成一个消息服务来统一处理。

5. 什么情况下链表会转红黑树

1).链表长度大于8。

2).当满足条件1以后调用treeifyBin方法转化红黑树。该方法中数组如果长度小于MIN_TREEIFY_CAPACITY(64就选择扩容而不是转化为红黑树。

为什么链表是8次以后就转换为红黑树?红黑树插入为O(lgn),查询为O(lgn)链表插入为O(1)查询为O(n)。个数少时插入删除成本高用链表;个数多时查询成本高用红黑树。需要定一个值比这个值大就转红黑树比这个值小就转链表而且要避免频繁的转换。根据泊松分布在负载因子0.75(HashMap默认的情况下单个hash槽内元素个数为8的概率小于百万分之一将7作为一个分水岭等于7时不做转换大于等于8才转红黑树小于等于6才转链表。

6. rpc实现原理

RPC(Remote Procedure Call Protocol)远程过程调用协议它是一种通过网络从远程计算机程序上请求服务而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在如TCP/IP或UDP为通信程序之间携带信息数据。RPC将原来的本地调用转变为调用远端的服务器上的方法给系统的处理能力和吞吐量带来了近似于无限制提升的可能。在OSI网络通信模型中RPC跨域了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

RPC架构一个完整的RPC架构里面包含了四个核心的组件分别是ClientClient StubServer以及Server Stub这个Stub可以理解为存根。

• 客户端(Client)服务的调用方。

• 客户端存根(Client Stub)存放服务端的地址消息再将客户端的请求参数打包成网络消息然后通过网络远程发送给服务方。

• 服务端(Server)真正的服务提供者。

• 服务端存根(Server Stub)接收客户端发送过来的消息将消息解包并调用本地的方法。

RPC调用过程:

(1) 客户端(client以本地调用方式(即以接口的方式调用服务;

(2) 客户端存根(client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体(将消息体对象序列化为二进制;

(3) 客户端通过sockets将消息发送到服务端;

(4) 服务端存根( server stub收到消息后进行解码(将消息对象反序列化;

(5) 服务端存根( server stub根据解码结果调用本地的服务;

(6) 本地服务执行并将结果返回给服务端存根( server stub;

(7) 服务端存根( server stub将返回结果打包成消息(将结果消息对象序列化;

(8) 服务端(server通过sockets将消息发送到客户端;

(9) 客户端存根(client stub接收到结果消息并进行解码(将结果消息发序列化;

(10) 客户端(client得到最终结果。

RPC的目标是要把2、3、4、7、8、9这些步骤都封装起来。注意无论是何种类型的数据最终都需要转换成二进制流在网络上进行传输数据的发送方需要将对象转换为二进制流而数据的接收方则需要把二进制流再恢复为对象。

RPC需要解决的问题Call ID映射

我们怎么告诉远程机器我们要调用funA而不是funB或者funC呢?在本地调用中函数体是直接通过函数指针来指定的我们调用funA编译器就自动帮我们调用它相应的函数指针。但是在远程调用中函数指针是不行的因为两个进程的地址空间是完全不一样的。

所以在RPC中所有的函数都必须有自己的一个ID。这个ID在所有进程中都是唯一确定的。客户端在做远程过程调用时必须附上这个ID。然后我们还需要在客户端和服务端分别维护一个 {函数 <–> Call ID} 的对应表。两者的表不一定需要完全相同但相同的函数对应的Call ID必须相同。

【Note】当客户端需要进行远程调用时它就查一下这个表找出相应的Call ID然后把它传给服务端服务端也通过查表来确定客户端需要调用的函数然后执行相应函数的代码。

常用的RPC框架

gRPC是Google公布的开源软件基于最新的HTTP2.0协议并支持常见的众多编程语言。 我们知道HTTP2.0是基于二进制的HTTP协议升级版本目前各大浏览器都在快马加鞭的加以支持。 这个RPC框架是基于HTTP协议实现的底层使用到了Netty框架的支持。

Thrift是Facebook的一个开源项目主要是一个跨语言的服务开发框架。它有一个代码生成器来对它所定义的IDL定义文件自动生成服务代码框架。用户只要在其之前进行二次开发就行对于底层的RPC通讯等都是透明的。不过这个对于用户来说的话需要学习特定领域语言这个特性还是有一定成本的。

Dubbo是阿里开源的一个极为出名的RPC框架在很多互联网公司和企业应用中广泛使用。协议和序列化框架都可以插拔是及其鲜明的特色。同样的远程接口是基于Java Interface并且依托于spring框架方便开发。可以方便的打包成单一文件独立进程运行和现在的微服务概念一致。

 7.一个for循环找数组中的第二大数

8. 如何自己实现一个栈

栈(先进后出)常见操作有出栈(POP)从栈中弹出一个元素;入栈(PUSH)将一个元素压入栈中访问栈顶元素(TOP)判断栈是否为空等。

可以选择数组或者链表来实现它们各有特点前者容量有限且固定但操作简单而后者容量理论上不受限但是操作并不如数组方便每次入栈要进行内存申请出栈要释放内存稍有不慎便造成内存泄露。

9. Https原理及握手过程

1). 浏览器向DNS服务器查找输入URL对应的IP地址。

2). DNS服务器根据IP地址与目标web服务器在80端口上建立TCP连接。

3). TCP/IP协议中TCP协议提供可靠的连接服务采用三次握手建立一个连接。

        第一次建立连接时客户端A发送SYN包(SYN=j到服务器B并进入SYN_SEND状态等待服务器B确认。

        第二次服务器B收到SYN包必须确认客户A的SYN(ACK=j+1同时自己也发送一个SYN包(SYN=k即SYN+ACK包此时服务器B进入SYN_RECV状态。

    第三次客户端A收到服务器B的SYN+ACK包向服务器B发送确认包ACK(ACK=k+1此包发送完毕客户端A和服务器B进入ESTABLISHED状态完成三次握手。 完成三次握手客户端与服务器开始传送数据。

4).浏览器获取请求页面的html代码JSP是Servlet的一种特殊形式每个JSP页面就是一个Servlet实例——JSP页面由系统编译成ServletServlet再负责响应用户请求。html代码是通过out.write()形式传到浏览器。tomcat/work目录下有jsp生成的java文件

5).浏览器在显示的窗口内渲染html

6).浏览器窗口关闭时终止与服务器的连接

HTTP是运行在TCP层之上的而HTTPS则是在HTTP和TCP层直接多加了一个SSL/TSL层SSL层向上提供加密和解密的服务对HTTP来说是透明的。

加密和解密都使用同一种算法的加密方法称之为对称加密。加密和解密使用不同的算法则为非对称加密。对称加密需要一把钥匙就够了因为加密和解密使用的是同一把钥匙。非对称加密算法需要两把钥匙公钥和私钥它们是一对。用公钥加密的密文只能用相应的私钥解开用私钥加密的密文只能用相应的公钥解开。其中公钥是公开的私钥是不对外公开的。两者的主要区别在于密钥的长度不同长度越长相应的加/解密花费的时间就会更长对称加密使用的密钥长度会短一些。SSL 结合了这两种加密算法的有点。利用非对称加密算法来协商生成对称加密的密钥然后之后就用对称加密来进行通信。发送密文的一方使用对方的公钥进行加密处理“对称的密钥”然后对方用自己的私钥解密拿到“对称的密钥”这样可以确保交换的密钥是安全的前提下使用对称加密方式进行通信。所以HTTPS采用对称加密和非对称加密两者并用的混合加密机制。

解决报文可能遭篡改问题使用数字签名将一段文本先用Hash函数生成消息摘要然后用发送者的私钥加密生成数字签名与原文文一起传送给接收者。接下来就是接收者校验数字签名的流程了。

HTTPS一般使用的加密与HASH算法如下非对称加密算法RSADSA/DSS

对称加密算法AESRC43DES。 HASH算法MD5SHA1SHA256

Http工作之前Web浏览器通过网络和Web服务器建立链连接该连接是通过Tcp来完成的该协议和Ip共同组成了Internet即著名的Tcp/Ip协议族因此Internet也被称为Tcp/Ip网络Http是比Tcp更高的应用层协议一般Tcp接口的端口好是80。这个过程中http建立连接Tcp经过了3次握手。终止协议的时候tcp进行了4次握手。

 

 http是直接与TCP进行数据传输而https是经过一层SSL(OSI表示层用的端口也不一样前者是80(需要国内备案后者是443。注意https加密是在传输层https报文在被包装成tcp报文的时候完成加密的过程无论是https的header域也好body域也罢都是会被加密的。

10. scheduler如何保证单实例

若是scheduler与web配置在一起在高可用的情况下如果有多个web容器实例scheduler会在多个实例上同时运行。

方法1部署的时候针对不同实例使用不同的配置。比如tomcat_1打开schedulertomcat_2关闭。带来的问题是增加部署成本。要是tomcat_1挂了scheduler就不能运行了高可用落空。

方法2在task的基类加入一些逻辑当开始运行时将状态(运行机器的IP、时间等写入数据库、缓存或者zk运行结束时重置状态。其它实例看到有这样的数据就直接返回。带来的问题是需要所有实例上的机器时间同步不然一个刚结束另一个才开始状态的维护就没有用了。一定要保证结束运行后将状态重置否则下一个运行周期所有的task都会返回的。实在不行还得写一个task做这个事。因为读写状态并非原子操作偶尔也会发生task同时运行的事。

方法3将scheduler与web分开。这样还能避免后台任务影响web端。带来的问题是增加部署成本。scheduler的高可用需要重新考虑。

SchedulerFactoryBean的代码里面一个参数叫做schedulerNameSchedulerFactoryBean通过 StdSchedulerFactory返回一个具体的Scheduler的。而且每个Scheduler是注册在 SchedulerRepository中的。 SchedulerRepository中的每个Scheduler都是放在一个MAP中的根据名字作为KEY。

11. Restful接口怎么设计遵循那些规范

示例参考RESTful API Design and header_Mynah886的博客-CSDN博客

REST是一套风格约定RESTful是它的形容词形式。比如一套实现了REST风格的接口可以称之为RESTful接口。

URI 表示资源资源一般对应服务器端领域模型中的实体类。是统一资源定位器。URI表示资源的两种方式资源集合、单个资源。

URL 用来定位资源跟要进行的操作区分开这就意味着URL不该有任何动词。

 12. webservice设计底层知道吗

webservice就是一个服务发现服务查找服务绑定和使用的三个模块。

webservice是用SOAP协议来传输的实际上就是HTTP + XMLHttp就是传输数据而XML就是封装数据.SOAP协议是基于HTTP协议的两者的关系就好比高速公路是基于普通公路改造的在一条公路上加上隔离栏后就成了高速公路。商店的服务员只要收到了钱就给客户提供货物商店服务员不用关心客户是什么性质的人客户也不用关心商店服务员是什么性质的人。同样WebService客户端只要能使用HTTP协议把遵循某种格式的XML请求数据发送给WebService服务器WebService服务器再通过HTTP协议返回遵循某种格式的XML结果数据就可以了WebService客户端与服务器端不用关心对方使用的是什么编程语言。

HTTP协议和XML是被广泛使用的通用技术各种编程语言对HTTP协议和XML这两种技术都提供了很好的支持WebService客户端与服务器端使用什么编程语言都可以完成SOAP的功能所以WebService的很容易实现跨编程语言跨编程语言自然也就跨了操作系统平台。

WSDL文件WebService客户端要调用一个WebService服务首先要有知道这个服务的地址在哪以及这个服务里有什么方法可以调用所以WebService务器端首先要通过一个WSDL文件来说明自己家里有啥服务可以对外调用服务是什么(服务中有哪些方法方法接受的参数是什么返回值是什么服务的网络地址用哪个url地址表示服务通过什么方式来调用。

WSDL(WebServiceDescription语言是基于XML格式的它是WebService客户端和服务器端都能理解的标准格式其中描述的信息可以分为什么在哪里如何等部分

WSDL文件保存在网络服务器上通过一个URL地址就可以访问到它。客户端要调用一个WebService的服务之前要知道该服务的WSDL文件的地址.WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址

1.注册到UDDI服务器以便被人查找

2.直接告诉给客户端调用者例如在自己网站给出信息或邮件告诉。

一般用户都是在服务端发布一个服务到指定的url上面进行注册而客户端就根据当前的url来查找对应的服务来绑定服务。图可以看出SOA结构中共有三种角色

1.服务提供者服务提供商发布自己的服务并且对使用自身服务的请求进行响应。

2.服务经纪人服务注册中心注册已经发布的服务提供商对其进行分类并提供搜索服务这是可搜索的服务描述注册中心服务提供者在此发布他们的服务描述。在静态绑定开发或动态绑定执行期间服务请求者查找服务并获得服务的绑定信息(在服务描述中。对于静态绑定的服务请求者服务注册中心是体系结构中的可选角色因为服务提供者可以把描述直接发送给服务请求者。同样服务请求者可以从服务注册中心以外的其它来源得到服务描述例如本地文件FTP站点网站点广告和服务发现(广告与发现 of ServicesADS或发现Web服务(发现Web服务DISCO。

3.服务请求者服务请求者利用服务经纪人查找所需的服务然后使用该服务.

13. 任务调度框架用过几个

Quartz是OpenSymphony开源组织在任务调度领域的一个开源项目完全基于java实现。作为一个优秀的开源框架Quartz具有以下特点强大的调度功能、灵活的应用方式、分布式和集群能力另外作为spring默认的调度框架很容易实现与Spring集成实现灵活可配置的调度功能。

Quartz框架的核心对象 Scheduler核心调度器就是任务调度、分配的控制器Job任务代表具体要执行的任务是个接口里面有默认方法开发者需要实现该接口并且业务逻辑写在默认的execute方法中, JobDetail任务描述描述job的静态消息是调度器需要的数据跟Job区分开来主要是为了一个Job可以在多台机器并行每个调度器new一个Job的实现类, Trigger触发器用于定义任务调度的时间规则。

Elastic-job要解决这个分布式的水平扩展、效率问题我们知道需要引入注册中心进行协调当当推出的Elastic-job就是Quartz的基础上引入ZK做注册中心。并且在2.0版本后出现了两个相互独立的产品线Elastic-job-lite和Elastic-job-cloud。Elastic-job-lite定位为轻量级无中心化的解决方案使用jar包的形式提供分布式任务的协调服务外部依赖仅依赖于zookeeper。

 xxl-job是一个轻量级的分布式任务调度框架其核心设计目标是开发迅速、学习简单、轻量级、易扩展。设计思想为

1). 将调度行为抽象形成“调度中心”公共平台而平台自身并不承担业务逻辑“调度中心”负责发起调度请求。

2). 将任务抽象成分散的JobHandler交由执行器统一管理执行器负责接收调度请求并执行对应的JobHandler中业务逻辑。 因此“调度”和“任务”可以互相解偶提高系统整体的稳定性和扩展性。

, xxl_job中心部署

a.部署前需要初始化调度中心需要的几个表这个脚本在源码的文件tables_xxl_job.sql中(如果mysql做主从,调度中心集群节点务必强制走主库。

b.设置模板xxl-job-admin中的application.properties的服务端口数据库信息和邮件配置信息。

c.可以打包模板xxl-job-admin为单个jar包可以部署到对应的服务器中。登录页面。页面最常用的就是任务管理和调度日志页面如果开发了新的任务需要在任务管理页面添加。

二,开发执行器

a.首先需要配置一个XxlJobSpringExecutor可以在配置文件或者配置类中。如果想自动注册必须设置xxl.job.admin.addresses和xxl.job.executor.appname

b. Bean模式的有两种实现类形式和方法形式。类形式继承IJobHandler接口实现execute方法返回ReturnT实例。最后在类上添加XxlJob注解。

方法形式要求方法的格式为“public ReturnT<String> execute(String param)”在方法上添加XxlJob注解。

三,在调度中心注册执行器和添加任务

a.打开admin页面在执行器管理菜单中添加一个执行器可以是自动注册或者是手动注册。

b.注册好后等待一会可以看到注册的信息在OnLine 机器地址列点击查看可以看到注册的地址和端口。

c添加任务在任务管理菜单点击添加添加一个任务我们选择Bean模式JobHandler就是我们用XxlJob注解方法或者类的名称。

d.任务添加后可以启动或者执行这个任务。

14. 熔断、降级、限流概念和区别

保障服务稳定的三大利器缓存、限流、熔断降级。缓存的目的是提升系统访问速度和增大系统能处理的容量可谓是抗高并发流量的银弹;而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉待高峰或者问题解决后再打开;而有些场景并不能用缓存和降级来解决比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询(评论的最后几页)因此需有一种手段来限制这些场景的并发/请求量即限流。

1) 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统一旦达到限制速率则可以拒绝服务(定向到错误页或告知资源没有了)、排队或等待(比如秒杀、评论、下单)、降级(返回兜底数据或默认数据如商品详情页库存默认有货)。

一般开发高并发系统常见的限流有限制总并发数(比如数据库连接池、线程池)、限制瞬时并发数(如nginx的limit_conn模块用来限制瞬时并发连接数)、限制时间窗口内的平均速率(如Guava的RateLimiter、nginx的limit_req模块限制每秒的平均速率);其他还有如限制远程接口调用速率、限制MQ的消费速率。另外还可以根据网络连接数、网络流量、CPU或内存负载等来限流。限流算法有计数器、漏桶、令牌桶。

计数器算法采用计数器实现限流有点简单粗暴一般是限制一秒钟的能够通过的请求数比如限流qps为50算法的实现思路就是从第一个请求进来开始计时在接下去的1s内每来一个请求就把计数加1如果累加的数字达到了50那么后续的请求就会被全部拒绝。等到1s结束后把计数恢复成0重新开始计数。弊端如果我在单位时间1s内的前10ms已经通过了100个请求后面的990ms只能把请求拒绝这种现象称为“突刺现象”不平滑。

漏桶为了消除"突刺现象"可以采用漏桶算法实现限流漏桶算法这个名字就很形象算法内部有一个容器类似生活中的漏斗当请求进来时相当于水倒入漏斗然后从下端小口慢慢匀速的流出。不管上面流量多大下面流出的速度始终保持不变。不管服务调用方多么不稳定通过漏桶算法进行限流每10毫秒处理一次请求。因为处理的速度是固定的请求进来的速度是未知的可能突然进来很多请求没来得及处理的请求就先放在桶里既然是个桶肯定是有容量上限如果桶满了那么新进来的请求就丢弃。

 

算法实现思路可以准备一个队列用来保存请求另外通过一个线程池定期从队列中获取请求并执行可以一次性获取多个并发执行。弊端无法应对短时间的突发流量。

令牌桶算法是对漏桶算法的一种改进桶算法能够限制请求调用的速率而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中存在一个桶用来存放固定数量的令牌。算法中存在一种机制以一定的速率往桶中放令牌。每次请求调用需要先获取令牌只有拿到令牌才有机会继续执行否则选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行如果桶中令牌数达到上限就丢弃令牌所以就存在这种情况桶中一直有大量的可用令牌这时进来的请求就可以直接拿到令牌执行比如设置qps为100那么限流器初始化完成一秒后桶中就已经有100个令牌了这时服务还没完全启动好等启动完成对外提供服务时该限流器可以抵挡瞬时的100个请求。所以只有桶中没有令牌时请求才会进行等待最后相当于以一定的速率执行。

算法实现思路可以准备一个队列用来保存令牌另外通过一个线程池定期生成令牌放到队列中每来一个请求就从队列中获取一个令牌并继续执行。通过Google开源的guava包使用它可以很轻松的创建一个令牌桶算法的限流器。

2) 熔断假设微服务A调用B和C微服务B和C又调用其它的微服务。如果调用链路上某个微服务的调用响应时间过长或者不可用对微服务A的调用就会占用越来越多的系统资源进而引起系统崩溃所谓的“雪崩效应”。熔断机制是应对雪崩效应的一种微服务链路保护机制。

服务熔断的作用类似于我们家用的保险丝当某服务出现不可用或响应超时的情况时为了防止整个系统出现雪崩暂时停止对该服务的调用。熔段解决如下几个问题

•当所依赖的对象不稳定时能够起到快速失败的目的

•快速失败后能够根据一定的算法动态试探所依赖对象是否恢复

3) 服务降级是从整个系统的负荷情况出发和考虑的对某些负荷会比较高的情况为了预防某些功能(业务场景出现负荷过载或者响应慢的情况。在其内部暂时舍弃对一些非核心的接口和数据的请求而直接返回一个提前准备好的fallback(退路错误处理信息。这样虽然提供的是一个有损的服务但却保证了整个系统的稳定性和可用性。

例如当活动高峰把无关交易的服务统统降级如查看蚂蚁深林查看历史订单商品历史评论只显示最后100条等等。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java