IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 【架构师面试-大厂内部面试题-1】-JAVA开发工程师精选面试100题-三万字面经 -> 正文阅读

[网络协议]【架构师面试-大厂内部面试题-1】-JAVA开发工程师精选面试100题-三万字面经

1:Dubbo

1.?服务调用超时问题怎么解决?

消费者调用服务超时会引起服务降级的发生,即从发出调用请求到?获取到提供者的响应结果这个时间超出了设定的时限。默认服务调用超时时限为 1 秒。可以 在消费者端与提供者端设置超时时限来解决。

总的来说还是要设计好业务代码来减少调用时长,设置准确RPC调用的超时时间才能更好的解决这个问题。

2.?Dubbo支持哪些序列化方式?

默认使用Hessian序列化,还有Duddo、FastJson、Java自带序列化。

3.?Dubbo和SpringCloud的关系?

Dubbo是SOA时代的产物,它的关注点主要在于服务的调用,流量分发、流量监控和熔断。而

SpringCloud诞生于微服务架构时代,考虑的是微服务治理的方方面面,另外由于依托了Spirng、

SpirngBoot的优势之上,两个框架在开始目标就不一致,Dubbo定位服务治理、SpirngCloud是一个生态。

4.?Dubbo的架构设计?

Dubbo框架设计一共划分了10个层:

服务接口层(Service):该层是与实际业务逻辑相关的,根据服务提供方和服务消费方的业务设计对应的接口和实现。

配置层(Config):对外配置接口,以ServiceConfig和ReferenceConfig为中心。

服务代理层(Proxy):服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton。??服务注册层(Registry):封装服务地址的注册与发现,以服务URL为中心。

集群层(Cluster):封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心。?????监控层(Monitor):RPC调用次数和调用时间监控。

远程调用层(Protocol):封将RPC调用,以Invocation和Result为中心,扩展接口为Protocol、

Invoker和Exporter。

信息交换层(Exchange):封装请求响应模式,同步转异步,以Request和Response为中心。网络传输层(Transport):抽象mina和netty为统一接口,以Message为中心。

5.?Dubbo的默认集群容错方案?

FailoverCluster

6.?Dubbo使用的是什么通信框架?

默认使用NIO Netty框架

7.?Dubbo的主要应用场景?

透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。软 负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。服务自动注册与发??现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加 或删除服务提供者。

8.??Dubbo服务注册与发现的流程?

流程说明:

Provider(提供者)绑定指定端口并启动服务·指供者连接注册中心,并发本机IP、端口、应用信息和提供服务信息发送至注册中心存储

Consumer(消费者),连接注册中心,并发送应用信息、所求服务信息至注册中心·注册中心根据消费者所求服务信息匹配对应的提供者列表发送至Consumer应用缓存。

Consumer在发起远程调用时基于缓存的消费者列表择其一发起调用。Provider状态变更会实时通知注册中心、在由注册中心实时推送至Consumer?

设计的原因:

Consumer与Provider解偶,双方都可以横向增减节点数。

注册中心对本身可做对等集群,可动态增减节点,并且任意一台宕掉后,将自动切换到另一台?去中心化,双方不直接依懒注册中心,即使注册中心全部宕机短时间内也不会影响服务的调用 服务提供者无状态,任意一台宕掉后,不影响使用

9.?Dubbo的四大组件

1、Provider:服务提供者。

2、Consumer:服务消费者。

3、Registry:服务注册与发现的中心,提供目录服务,亦称为服务注册中心

4、Monitor:统计服务的调用次数、调用时间等信息的日志服务,并可以对服务设置权限、 降级处理等,称为服务管控中心

10.??Dubbo在安全机制方面是如何解决的

Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方。

11.??Dubbo和SpringCloud的区别?

最大的区别:Dubbo底层是使用Netty这样的NIO框架,是基于TCP协议传输的,配合以Hession序列化??完成RPC通信。

而SpringCloud是基于Http协议+Rest接口调用远程过程的通信,相对来说,Http请求会有更大的报??文,占的带宽也会更多。但是REST相比RPC更为灵活。

12.?Dubbo支持哪些协议,每种协议的应用场景,优缺点?

dubbo 协议 :

Dubbo 默认传输协议

连接个数:单连接连接方式:长连接协议:TCP

传输方式:NIO 异步传输

适用范围:传入传出参数数据包较小(建议小于 100K),消费者比提供者个数多,单一 消费者无法压满提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。

rmi:采用JDK标准的rmi协议实现,传输参数和返回参数对象需要实现Serializable接口,使用java标准?序列化机制,使用阻塞式短连接,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输?协议TCP。多个短连接,TCP协议传输,同步传输,适用常规的远程服务调用和rmi互操作。在依赖低版本的Common-Collections包,java序列化存在安全漏洞;

webservice:基于WebService的远程调用协议,集成CXF实现,提供和原生WebService的互操作。多?个短连接,基于HTTP传输,同步传输,适用系统集成和跨语言调用;

http:基于Http表单提交的远程调用协议,使用Spring的HttpInvoke实现。多个短连接,传输协议

HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器JS调用;

hessian:集成Hessian服务,基于HTTP通讯,采用Servlet暴露服务,Dubbo内嵌Jetty作为服务器时默认实现,提供与Hession服务互操作。多个短连接,同步HTTP传输,Hessian序列化,传入参数较???大,提供者大于消费者,提供者压力较大,可传文件;

memcache:基于memcached实现的RPC协议redis:基于redis实现的RPC协议

13.?Dubbo的核心功能有哪些?

主要就是如下3个核心功能:

Remoting:网络通信框架,提供对多种NIO框架抽象封装,包括“同步转异步”和“请求-响应”模式的信息?????交换方式。

Cluster:服务框架,提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。

Registry:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明, 使服务提供方可以平滑增加或减少机器。

14.??Dubbo的注册中心集群挂掉,发布者和订阅者之间还能通信么?

可以的,启动dubbo时,消费者会从zookeeper拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用。

15.?Dubbo的集群容错方案有哪些?

FailoverCluster:失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更 ?长延迟。

FailfastCluster:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增??记录。FailsafeCluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

FailbackCluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

ForkingCluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作, ?但需要浪费更多服务资源。可通过forks=”2″来设置最大并行数。

BroadcastCluster:广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供 ?者更新缓存或日志等本地资源信

16.??Dubbo集群的负载均衡有哪些策略

Dubbo提供了常见的集群策略实现,并预扩展点予以自行实现。

A、 random :随机算法,是 Dubbo 默认的负载均衡算法。存在服务堆积问题。

B、 roundrobin :轮询算法。按照设定好的权重依次进行调度。

C、 leastactive :最少活跃度调度算法。即被调度的次数越少,其优选级就越高,被调度到的机率就越高。

D、 consistenthash :一致性 hash 算法。对于相同参数的请求,其会被路由到相同的提供者。

17.?为什么需要服务治理?

服务治理是主要针对分布式服务框架的微服务,处理服务调用之间的关系、服务发布和发现、故障监控?与处理,服务的参数配置、服务降级和熔断、服务使用率监控等。

原因:

过多的服务URL配置困难

负载均衡分配节点压力过大的情况下也需要部署集群服务依赖混乱,启动顺序不清晰

过多服务导致性能指标分析难度较大,需要监控故障定位与排查难度较大

18.?Dubbo超时时间怎样设置?

Dubbo超时时间设置有两种方式:

服务提供者端设置超时时间,在Dubbo的用户文档中,推荐如果能在服务端多配置就尽量多配置,因为 服务提供者比消费者更清楚自己提供的服务特性。

服务消费者端设置超时时间,如果在消费者端设置了超时时间,以消费者端为主,即优先级更高。因为?服务调用方设置超时时间控制性更灵活。如果消费方超时,服务端线程不会定制,会产生警告。

19.?Dubbo框架源码最重要的设计原则是什么?从架构设计角度谈一下你对这个设计原则的理解。

Dubbo在设计时具有两大设计原则:

“微内核+插件”的设计模式。内核只负责组装插件(扩展点),Dubbo的功能都是由插件实现的,也就是 Dubbo 的所有功能点都可被用户自定义扩展类所替换。Dubbo的高扩展性、开放性在这里被充分体现。

采用 URL 作为配置信息的统一格式,所有扩展点都通过传递 URL 携带配置信息。简单来说就是,在

Dubbo中,所有重要资源都是以URL的形式来描述的。

20.?为什么Dubbo使用URL,而不使用JSON,使用URL的好处是什么?

关于这个问题,官方是没有相关说明的,下面我谈两点我个人的看法:

首先,Dubbo是将URL作为公共契约出现的,即希望所有扩展点都要遵守的约定。既然是约定,那么可以这样约定,也可以那样约定。只要统一就行。所以,在Dubbo创建之初,也许当时若采用了JSON作为这个约定也是未偿不可的。

其次,单从JSON与URL相比而言,都是一种简洁的数据存储格式。但在简洁的同时,URL与Dubbo应用???场景的契合度更高些。因为Dubbo中URL的所有应用场景都与通信有关,都会涉及到通信协议、通信主机、端口号、业务接口等信息。其语义性要强于JSON,且对于这些数据就无需再给出相应的key了,会使传输的数据量更小。

21.?请简述一下Dubbo四大组件间的关系

Dubbo的四大组件为:Consuer、Provider、Registry与Monitor。它们间的关系可以描述为如下几个过程:

start:Dubbo服务启动,Spring容器首先会创建服务提供者。

register:服务提供者创建好后,马上会注册到服务注册中心Registry,这个注册过程称为服务暴露。服?????务暴露的本质是将服务名称(接口)与服务提供者主机写入到注册中心Registry的服务映射表中。注册中心充当着“DNS域名服务器”的角色。

subscribe:服务消费者启动后,首先会向服务注册中心订阅相关服务。

notify:消费者可能订阅的服务在注册中心还没有相应的提供者。当相应的提供者在注册中心注册后, 注册中心会马上通知订阅该服务的消费者。但消费者在订阅了指定服务后,在没有收到注册中心的通知?之前是不会被阻塞的,而是可以继续订阅其它服务。

invoke:消费者以同步或异步的方式调用提供者提供的请求。消费者通过远程注册中心获取到提供者列表,然后消费者会基于负载均衡算法选一台提供者处理消费者的请求。

count:每个消费者对各个服务的累计调用次数、调用时间;每个提供者被消费者调用的累计次数和时 间,消费者与调用者都会定时发送到监控中心,由监控中心记录。这些统计数据可以在Dubbo的可视化 界面看到。

22.?什么是SPI?请简单描述一下SPI要解决的问题.

SPI,Service?Provider?Interface,服务提供者接口,是一种服务发现机制。其主要是解决面向抽象编程中上层对下层接口实现类的依赖问题,可以实现这两层间的解耦合。

23.?JDK的SPI机制存在什么问题?

JDK的SPI机制将所有配置文件中的实现类全部实例化,无论是否能够用到,浪费了宝贵的系统资源。

24.?简述Dubbo的Wrapper机制

Wrapper机制,即扩展类的包装机制。就是对扩展类中的SPI接口方法进行增强,进行包装,是AOP思想的体现,是Wrapper设计模式的应用。一个SPI可以包含多个Wrapper,即可以通过多个Wrapper对???同一个扩展类进行增强,增强出不现的功能。Wrapper机制不是通过注解实现的,而是通过一套Wrapper规范实现的。

25.?Dubbo的Wrapper类是否属于扩展类?

wrapper类仅仅是对现有的扩展类功能上的增强,并不是一个独立的扩展类,所以其不属于扩展类范畴。

26.?简述Dubbo的Active机制

Activate机制,即扩展类的激活机制。通过指定的条件来实现一次激活多个扩展类的目的。激活机制没有增强扩展类,也没有增加扩展类,其仅仅是为原有的扩展类添加了更多的识别标签,而不像之前的,?每个扩展类仅有一个“功能性扩展名”识别标签。其是通过@Active注解实现的。

27.?Dubbo的Activate类是否属于扩展类?

Activate机制仅用于为扩展类添加激活标识的,其是通过在扩展类上添加@Activate注解来实现的,所以Activate类本身就是扩展类。

28.?简述Dubbo中配置中心与注册中心的关系

Dubbo中的注册中心是用于完成服务发现的,而配置中心是用于完成配置信息的统一管理的。若没有专 门设置配置中心,系统会默认将注册中心服务器作为配置中心服务器。

29.??Dubbo内核工作原理的四个构成机制间的关系是怎样的?或者说,一个扩展类实例获取过程是怎样的?

获取一个扩展类实例,一般需要经过这样几个环节:

获取到该SPI接口的ExtensionLoader。而这个获取的过程会将该SPI接口的所有扩展类(四类)加载并??缓存。

通过extensionLoader获取到其自适应实例。通常SPI接口的自适应实例都是由Adaptive方法自动生成 的,所以需要对这个自动生成的Adaptive类进行动态编译。

在通过自适应实例调用自适应的业务方法时,才会获取到其真正需要的扩展类实例。所以说,一个扩展?类实例一般情况下是在调用自适应方法时才创建。

在获取这个真正的扩展类实例时,首先会根据要获取的扩展类实例的“功能性扩展名”,从扩展类缓存中 找到其对应的扩展类,然后调用其无参构造器,创建扩展类实例instance。

通过injectExtension(instance)方法,调用instance实例的setter完成初始化。

遍历所有该SPI的Wrapper,逐层包装这个setter过的instance。此时的这个instance,即wrapper实例就是我们需要获取的扩展类实例。

2:ElasticSearch

1.??你们公司的ES集群,一个node一般会分配几个分片?

我们遵循官方建议,一个 Node 最好不要多于三个 shards。

2.?Elasticsearch是如何实现Master选举的?

Elasticsearch的选主是ZenDiscovery模块负责的,主要包含Ping(节点之间通过这个RPC来发现彼此) 和Unicast(单播模块包含一个主机列表以控制哪些节点需要ping通)这两部分;

对所有可以成为master的节点(node.master:?true)根据nodeId字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。

如果对某个节点的投票数达到一定的值(可以成为master节点数n/2+1)并且该节点自己也选举自己, 那这个节点就是master。否则重新选举一直到满足上述条件。

3.?你是如何做写入调优的?

1)写入前副本数设置为0;????????????????????????????????????????

2)写入前关闭refresh_interval设置为-1,禁用刷新机制;

3)写入过程中:采取bulk批量写入;

4)?写入后恢复副本数和刷新间隔;

5)?尽量使用自动生成的id。

4.??如何避免脑裂?

可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题。

5.?Elasticsearch对于大数据量(上亿量级)的聚合如何实现?

Elasticsearch 提供的首个近似聚合是cardinality 度量。它提供一个字段的基数,即该字段的distinct或者unique值的数目。它是基于HLL算法的。HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。

其特点是:

可配置的精度,用来控制内存的使用(更精确 =?更多内存); 小的数据集精度是非常高的;

我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用?量只与你配置的精确度相关 。

6.?ES主分片数量可以在后期更改吗?为什么?

不可以,因为根据路由算法shard?= hash(document_id)?% (num_of_primary_shards),当主分片数量变化时会影响数据被路由到哪个分片上。

7.??如何监控集群状态?

Marvel 让你可以很简单的通过 Kibana 监控 Elasticsearch。你可以实时查看你的集群健康状态和性能,也可以分析过去的集群、索引和节点指标。

8.?ElasticSearch中的副本是什么?

一个索引被分解成碎片以便于分发和扩展。副本是分片的副本。一个节点是一个属于一个集群的

ElasticSearch的运行实例。一个集群由一个或多个共享相同集群名称的节点组成。

9.??ES更新数据的执行流程?

(1)?将原来的doc标识为deleted状态,然后新写入一条数据。

(2)?buffer每refresh一次,就会产生一个segmentfile,所以默认情况下是1s一个segmentfile, segmentfile会越来越多,此时会定期执行merge。

(3)?每次merge时,会将多个segmentfile合并成一个,同时这里会将标识为deleted的doc给物理删除掉,?然后将新的segmentfile写入磁盘,这里会写一个commitpoint,标识所有新的segmentfile,然后打开segmentfile供搜索使用,同时删除旧的segmentfile。

10.??shard里面是什么组成的?

是多个segment组成的。

11.?ElasticSearch中的分析器是什么?

在ElasticSearch中索引数据时,数据由为索引定义的Analyzer在内部进行转换。 分析器由一个

Tokenizer和零个或多个TokenFilter组成。编译器可以在一个或多个CharFilter之前。分析模块允许您在逻辑名称下注册分析器,然后可以在映射定义或某些API中引用它们。Elasticsearch附带了许多可以随????时使用的预建分析器。或者,您可以组合内置的字符过滤器,编译器和过滤器器来创建自定义分析器。

12.?客户端在和集群连接时,如何选择特定的节点执行请求的?

TransportClient利用transport模块远程连接一个elasticsearch集群。它并不加入到集群中,只是简单的获得一个或者多个初始化的transport地址,并以 轮询 的方式与这些地址进行通信。

13.??Elasticsearch中的倒排索引是什么?

倒排索引是搜索引擎的核心。搜索引擎的主要目标是在查找发生搜索条件的文档时提供快速搜索。倒排?索引是一种像数据结构一样的散列图,可将用户从单词导向文档或网页。它是搜索引擎的核心。其主要?目标是快速搜索从数百万文件中查找数据。

14.??什么是脑裂?

一个正常es集群中只有一个主节点,主节点负责管理整个集群,集群的所有节点都会选择同一个节点作 为主节点所以无论访问那个节点都可以查看集群的状态信息。而脑裂问题的出现就是因为从节点在选择 主节点上出现分歧导致一个集群出现多个主节点从而使集群分裂,使得集群处于异常状态。

15.?什么是索引?

索引(名词) 一个索引(index)就像是传统关系数据库中的数据库,它是相关文档存储的地方,index的复数是indices indexes

索引(动词)??「索引一个文档」表示把一个文档存储到索引(名词)里,以便它可以被检索或者查询。这很像SQL中的INSERT?关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。

16.?详细描述一下Elasticsearch更新和删除文档的过程

删除和更新也都是写操作,但是Elasticsearch中的文档是不可变的,因此不能被删除或者改动以展示其??????变更;

磁盘上的每个段都有一个相应的.del文件。当删除请求发送后,文档并没有真的被删除,而是在.del文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在.del文件中被标记为删除的文档将不会被写入新段。

在新的文档被创建时,Elasticsearch会为该文档指定一个版本号,当执行更新时,旧版本的文档在.del

文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果?中被过滤掉。

3:JVM

1.?JVM参数主要有几种分类

标准参数

标准参数,顾名思义,标准参数中包括功能以及输出的结果都是很稳定的,基本上不会随着JVM版本的变化而变化。标准参数以-开头,如:java -version、java -jar等,通过java -help可以查询所有的标准参数,

非标准参数

非标准参数以-X开头,是标准参数的扩展。对应前?讲的标准化参数,这是非标准化参数。表示在将来 的JVM版本中可能会发生改变,但是这类以-X开始的参数变化的?较小。

不稳定参数

这是我们日常开发中接触到最多的参数类型。这也是?标准化参数,相对来说不稳定,随着JVM版本的变化可能会发生变化,主要用于JVM调优和debug。

不稳定参数以-XX?开头,此类参数的设置很容易引起JVM??性能上的差异,使JVM存在极大的不稳定性。如果此类参数设置合理将大大提?JVM的性能及稳定性。

不稳定参数分为三类:

性能参数:用于JVM的性能调优和内存分配控制,如内存大小的设置; 行为参数:用于改变JVM的基础?为,如GC的?式和算法的选择;

调试参数:用于监控、打印、输出jvm的信息;

2.?Java中会存在内存泄漏吗,简述一下。

理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程???的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因??此也会导致内存泄露的发生。例如hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器???是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露。下面例子中的代码也会导致内存泄露

3.?Java 中都有哪些引用类型

强引用:发生 gc 的时候不会被回收。 new

软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。SoftReference??弱引用:有用但不是必须的对象,在下一次GC时会被回收。WeakReference

虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。

4.?在 Java 中,对象什么时候可以被垃圾回收?

首先先由可达性算法去判断对象是否可回收二次标记,相当于二次审判。finalize方法其次再去根据GC的回收机制,择时回收

5.?StackOverflow异常有没有遇到过?一般你猜测会在什么情况下被触发?

答:栈内存溢出,一般由栈内存的局部变量过爆了,导致内存溢出。出现在递归方法,参数个数过多,?递归过深,递归没有出口。

6.?堆空间分哪?个部分?以及如何设置各个部分大小?

Java堆被所有线程共享,在Java虚拟机启动时创建。是虚拟机管理最大的?块内存。

Java堆是垃圾回收的主要区域,而且主要采用分代回收算法。堆进?步划分主要是为了更好的回收内存或更快的分配内存。

Java虚拟机规范的描述是:所有的对象实例以及数组都要在堆上分配。堆内存空间在物理上可以不连续,逻辑上连续即可。

堆大小 = 新生代 + ?年代。

堆的大小可通过参数 –Xms(堆的初始容量)、-Xmx(堆的最大容量) 来指定。

其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为

from 和 to,以示区分。

默认的,Eden : from : to = 8 : 1 : 1 。(可以通过参数 –XX:SurvivorRatio 来设定 。) 即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。

JVM 每次只会使用 Eden 和其中的?块 Survivor 区域来为对象服务,所以?论什么时候,总是有?块

Survivor 区域是空闲着的。

新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。

-Xmn:?于这个参数则是对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置,也就是说如果通过- Xmn来配置新生代的内存大小,那么-XX:newSize = -XX:MaxnewSize = -Xmn,虽然会很?便,但需要注意的是这个参数是在JDK1.4版本以后才使用的。

7.?什么是栈帧?栈帧存储了什么?

虚拟机栈也是线程私有,而且生命周期与线程相同,每个Java?法在执?的时候都会创建?个栈帧

(Stack Frame)。栈帧(Stack Frame)是用于?持虚拟机进??法调用和?法执?的数据结构。栈帧存储了?法的局部变量表、操作数栈、动态连接和?法返回地址等信息。每?个?法从调用?执?完成的?过程,都对应着?个栈帧在虚拟机栈?从?栈到出栈的过程。

8.?如何设置参数生成GC日志

设置JVM GC格式日志的主要参数包括如下8个:

-XX:+PrintGC 输出简要GC日志

-XX:+PrintGCDetails 输出详细GC日志

-Xloggc:gc.log 输出GC日志到?件

-XX:+PrintGCTimeStamps 输出GC的时间戳(以JVM启动到当期的总时?的时间戳形式)

-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2020-04- 26T21:53:59.234+0800)

-XX:+PrintHeapAtGC 在进?GC的前后打印出堆的信息

-verbose:gc : 在JDK 8中, -verbose:gc 是 -XX:+PrintGC ?个别称,日志格式等价与: - XX:+PrintGC 。不过在JDK 9中 -XX:+PrintGC被标记为deprecated。

-verbose:gc是?个标准的选项,-XX:+PrintGC是?个实验的选项,建议使用-verbose:gc 替代 -

XX:+PrintGC

-XX:+PrintReferenceGC 打印年轻代各个引用的数量以及时?

开启GC日志

多种?法都能开启GC的日志功能,其中包括:使用-verbose:gc或-XX:+PrintGC这两个标志中的任意???个能创建基本的GC日志(这两个日志标志实际上互为别名,默认情况下的GC日志功能是关闭的)使用XX:+PrintGCDetails标志会创建更详细的GC日志推荐使用-XX:+PrintGCDetails标志(这个标志默认情况????下也是关闭的);通常情况下使用基本的GC日志很难诊断垃圾回收时发生的问题。

开启GC时间提示

除了使用详细的GC日志,我们还推荐使用-XX:+PrintGCTimeStamps或者-XX:+PrintGCDateStamps,??便于我们更精确地判断?次GC操作之间的时间。这两个参数之间的差别在于时间戳是相对于0(依据 JVM启动的时间)的值,而日期戳(date stamp)是实际的日期字符串。由于日期戳需要进?格式化, 所以它的效率可能会受轻微的影响,不过这种操作并不频繁,它造成的影响也很难被我们感知。

指定GC日志路径

默认情况下GC日志直接输出到标准输出,不过使用-Xloggc:filename标志也能修改输出到某个?件。除

?显式地使用-PrintGCDetails标志,否则使用-Xloggc会?动地开启基本日志模式。使用日志循环(Log rotation)标志可以限制保存在GC日志中的数据量;对于需要?时间运?的服务器而?,这是?个?常有用的标志,否则累积?个?的数据很可能会耗尽服务器的磁盘。

开启日志滚动输出

通过-XX:+UseGCLogfileRotation?-XX:NumberOfGCLogfiles=N??-XX:GCLogfileSize=N标志可以控制日志?件的循环。默认情况下,UseGCLogfileRotation标志是关闭的。它负责打开或关闭GC日志滚动记?录功能的。要求必须设置 -Xloggc参数开启UseGCLogfileRotation标志后,默认的?件数?是0(意味着不作任何限制),默认的日志?件大小是0(同样也是不作任何限制)。因此,为了让日志循环功能?真正生效,我们必须为所有这些标志设定值。

需要注意的是:

The size of the log file at which point the log will be rotated, must be >= 8K. 设置滚动日志?件的大小,必须大于8k。当前写日志?件大小超过该参数值时,日志将写?下?个?件设置滚动日志?件的个 数,必须大于等于1必须设置 -Xloggc 参数

9.?GC 是什么?为什么要有 GC?

答:GC?是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。Java 程序员不用担心内存管理, 因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但 JVM 可以屏蔽掉显示的垃圾回收调用。

垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低?优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回?收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在 Java 诞生初期,垃圾回收是 Java 最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今 Java 的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得 iOS 的系统比 Android 系统有更好的用户体验,其中一个深层次的原因就在于 Android 系统中垃圾回收的不可预知性。

第 3 行中生成的 object在第几行执行后成为 garbage collection 的对象?

答:第 7 行

10.?Java 虚拟机是如何判定两个 Java 类是相同的?

① 类的全限定名是否相等

②类加载器是否相等

即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。比如一个 Java 类com.example.Sample,编译之后生成了字节代码文件 Sample.class。两个不同的类加载器ClassLoaderA和 ClassLoaderB分别读取了这个 Sample.class文件,并定义出两个 java.lang.Class类的实例来表示这个类。这两个实例是不相同的。对于 Java 虚拟机来说,它们是不同的类。

11.?JVM运?时数据区区域分为哪?部分?

线程共享:堆、?法区

线程私有:虚拟机栈、本地?法栈、程序计数器

jdk1.7之前,HotSpot虚拟机对于?法区的实现称之为“永久代”, Permanent Generation 。

jdk1.8之后,HotSpot虚拟机对于?法区的实现称之为“元空间”, Meta Space 。

?法区是Java虚拟机规范中的定义,是?种规范,而永久代和元空间是 HotSpot 虚拟机不同版本的两种实现。

12.?是否了解类加载器双亲委派模型机制和破坏双亲委派模型?

双亲委派模型机制:皇子的例子

破坏双亲委派模型:JDK1.0的时候写好了一些类和类加载器,但是JDK1.2的时候才出现了双亲委派模??型。比如说DriverManager去加载Driver的时候,就是破坏了双亲委派模型。

DriverManager相当于是皇上去处理

Driver实现类(第三方提供)相当于皇子去处理

13.?逃逸分析有?种类型?

逃逸分析(Escape Analysis)是?前Java虚拟机中?较前沿的优化技术。这是?种可以有效减少Java 程序中同步负载和内存堆分配压?的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够分析出?个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。

逃逸分析的基本?为就是分析对象动态作用域:当?个对象在?法中被定义后,它可能被外部?法所引

用,例如作为调用参数传递到其他地?中,称为?法逃逸。逃逸分析包括:

全局变量赋值逃逸

?法返回值逃逸实例引用发生逃逸

线程逃逸:赋值给类变量或可以在其他线程中访问的实例变量

14.?使用过哪些jdk命令,并说明各?的作用是什么

jps

jps:Java Virtual Machine Process Status Tool

查看Java进程 ,相当于Linux下的ps命令,只不过它只列出Java进程。

jstat

jstat:JVM Statistics Monitoring Tool

jstat可以查看Java程序运?时相关信息,可以通过它查看堆信息的相关情况

jinfo

jinfo:Java Configuration Info

jinfo可以用来查看正在运?的java程序的扩展参数,甚??持运?时,修改部分参数

jmap

jmap:Memory Map

jmap用来查看堆内存使用状况,?般结合jhat使用。

jstack

jstack:Java Stack Trace,jstack是java虚拟机?带的?种堆栈跟踪?具。jstack用于生成java虚拟

机当前时刻的线程快照。线程快照是当前java虚拟机内每?条线程正在执?的?法堆栈的集合,生成线程快照的主要?的是定位线程出现?时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的??时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。???如果java程序崩溃生成core?件,jstack?具可以用来获得core?件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack?具还可以附属到正在运?的java程序中,看到当时运?的java程序的java stack和native stack的信息, 如果现在运?的java程序呈现hung的状态,jstack是?常有用的。

jconsole

Jconsole:Java Monitoring and Management Console,Java 5引?,?个内置 Java 性能分析器, 可以从命令?或在 GUI shell 中运?。您可以轻松地使用 JConsole来监控 Java 应用程序性能和跟踪Java 中的代码。

15.?-Xms这些参数的含义是什么?

堆内存分配:

JVM初始分配的内存由-Xms指定,默认是物理内存的1/64。JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。

16.?你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,包括原理,流程,优缺点。

几种垃圾收集器:

Serial收集器:单线程的收集器,收集垃圾时,必须stoptheworld,使用复制算法。ParNew收集器:Serial收集器的多线程版本,也需要stoptheworld,复制算法。

ParallelScavenge收集器:新生代收集器,复制算法的收集器,并发的多线程收集器,目标是达到一个???可控的吞吐量。如果虚拟机总共运行100分钟,其中垃圾花掉1分钟,吞吐量就是99%。

SerialOld收集器:是Serial收集器的老年代版本,单线程收集器,使用标记整理算法。

ParallelOld收集器:是ParallelScavenge收集器的老年代版本,使用多线程,标记-整理算法。CMS(ConcurrentMarkSweep)收集器:

是一种以获得最短回收停顿时间为目标的收集器,标记清除算法,运作过程:初始标记,并发标记,重?新标记,并发清除,收集结束会产生大量空间碎片。

G1收集器:标记整理算法实现,运作流程主要包括以下:初始标记,并发标记,最终标记,筛选标记。 不会产生空间碎片,可以精确地控制停顿。

CMS收集器和G1收集器的区别:CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收??集器一起使用;G1收集器收集范围是老年代和新生代,不需要结合其他收集器使用;CMS收集器以最小的停顿时间为目标的收集器;G1收集器可预测垃圾回收的停顿时间CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了 内存空间碎片。

17.?JVM的内存结构,Eden和Survivor比例是多少?

Eden区是一块,Survivor区是两块。Eden区和Survivor区的比例是8:1:1。

4:多线程/高并发

1.?负载平衡的意义什么?

在计算中,负载平衡可以改善跨计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器等多种计?算资源的工作负载分布。负载平衡旨在优化资源使用,最大化吞吐量,最小化响应时间并避免任何单一?资源的过载。使用多个组件进行负载平衡而不是单个组件可能会通过冗余来提高可靠性和可用性。负载?平衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务器进程。

2.?请说出同步线程及线程调度相关的方法?

wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;

notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;

notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;注意:java5通过Lock接口提供了显示的锁机制,Lock接口???中定义了加锁(lock())方法)和解锁(unLock()方法),增强了多线程编程的灵活性及对线程的协调

3.?启动一个线程是调用run()方法还是start()方法?

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM???调度并执行,这并不意味着线程就会立即运行。run()方法是线程启动后要进行回调(callback)的方法。

4.?如何确保N个线程可以访问N个资源同时又不导致死锁?

使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的?顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

5.?编写多线程程序的几种实现方式(换个问法:创建多线程的方式)?

通过继承Thread类

通过实现Runnable接口(推荐使用,因为Java中是单继承,一个类只有一个父类,若继承了

Thread类,就无法在继承其它类,显然实现Runnable接口更为灵活

通过实现Callable接口(Java5之后)

6.?线程和进程的区别?

进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行资源分配和调度?的一个独立单位线程:是进程的一个实体,是cpu调度和分派的基本单位,是比进程更小的可以独立运 行的基本单位

特点:1)线程的划分尺度小于进程,这使多线程程序拥有高并发性;2)进程在运行时各自内存单元相 互独立,线程之间内存共享,这使多线程编程可以拥有更好的性能和用户体验。

7.?什么是线程池,有哪些常用线程池?

就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,?使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。

8.?什么是死锁?

两个线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程都陷入了无?限的等待中。

9.?怎么保证缓存和数据库数据的一致性?

合理设置缓存的过期时间。

新增、更改、删除数据库操作时同步更新 Redis,可以使用事物机制来保证数据的一致性。

5:消息中间件

1.?消费者获取消息有几种模式?

消费者获取消息有两种模式:推送模式和拉取模式。

2.?RocketMQ的特点有哪些?

支持严格的消息顺序支持Topic与Queue两种模式亿级消息堆积能力比较友好的分布式特性同时支持Push与Pull方式消费消息

3.?kafka?同时设置了 7?天和 10G?清除数据,到第五天的时候消息达到了 10G,这个时候 kafka将如何处理?

这个时候 kafka 会执行数据清除工作,时间和大小不论那个满足条件,都会清空数据。

4.?为何需要Kafka集群

本地开发,一台Kafka足够使用。在实际生产中,集群可以跨服务器进行负载均衡,再则可以使用复制功能来避免单独故障造成的数据丢失,同时集群可以提供高可用性。

5.?Kafka?数据存储设计

partition 的数据文件(offset,MessageSize,data)

partition 中的每条 Message 包含了以下三个属性:offset,essageSize,data,其中 offset 表示Message 在这个 partition 中的偏移量,offset 不是该 Message 在 partition 数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了 partition 中的一条 Message,可以认为 offset 是partition 中Message 的 id;MessageSize 表示消息内容 data 的大小;data 为Message 的具体内容。

数据文件分段 segment(顺序读写、分段命令、二分查找)

partition?物理上由多个 segment?文件组成,每个 segment?大小相等,顺序读写。每个 segment数据文件以该段中最小的 offset?命名,文件扩展名为.log。这样在查找指定 offset?的 Message?的时候,用二分查找就可以定位到该 Message?在哪个 segment?数据文件中。

数据文件索引(分段索引、稀疏存储)

Kafka?为每个分段后的数据文件建立了索引文件,文件名与数据文件的名字是一样的,只是文件扩展名为 .index。index 文件中并没有为数据文件中的每条 Message 建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。

6.?Kafka如何判断一个节点是否存活?

(1)?节点必须可以维护和ZooKeeper的连接,Zookeeper通过心跳机制检查每个节点的连接

(2)?如果节点是个follower,他必须能及时的同步leader的写操作,延时不能太久

7.?kafka消息发送的可靠性机制有几种?

生产者向 kafka 发送消息时,可以选择需要的可靠性级别。通过 acks 参数的值进行设置。

(1)?0?值 异步发送。生产者向 kafka?发送消息而不需要 kafka?反馈成功 ack。该方式效率最高,但 可靠性最低。其可能会存在消息丢失的情况。

(2)?1?值 同步发送,默认值。生产者发送消息给 kafka,broker?的 partition?leader?在收到消息后 马上发送成功 ack(无需等待 ISR?中的 follower?同步完成),生产者收到后知道消息发送成功, 然后会再发送消息。如果一直未收到 kafka?的 ack,则生产者会认为消息发送失败,会重发 消息。

(3)?-1?值 同步发送。其值等同于 all。生产者发送消息给 kafka,kafka?收到消息后要等到 ISR?列表中的所有副本都同步消息完成后,才向生产者发送成功 ack。如果一直未收到 kafka?的 ack, 则认为消息发送失败,会自动重发消息。

该方式存在 follower 重复接收的情况。注意,重复接收,与重复消费是两个概念

8.?请详细说一下推送模式和拉取模式。

1.?PushConsumer

推送模式(虽然 RocketMQ 使用的是长轮询)的消费者。消息的能及时被消费。使用非常简单, 内部已处理如线程池消费、流控、负载均衡、异常处理等等的各种场景。

2.?PullConsumer

拉取模式的消费者。应用主动控制拉取的时机,怎么拉取,怎么消费等。主动权更高。但要自己处?理各种场景。

9.?Kafka?与传统消息系统之间有三个关键区别

(1).Kafka 持久化日志,这些日志可以被重复读取和无限期保留

(2).Kafka 是一个分布式系统:它以集群的方式运行,可以灵活伸缩,在内部通过复制数据提升容错能力和高可用性

(3).Kafka 支持实时的流式处理

10.?RocketMQ?由哪些角色组成?

生产者(Producer):负责产生消息,生产者向消息服务器发送由业务应用程序系统生成的消息。消费者(Consumer):负责消费消息,消费者从消息服务器拉取信息并将其输入用户应用程序。

消息服务器(Broker):是消息存储中心,主要作用是接收来自 Producer 的消息并存储, Consumer从这里取得消息。

名称服务器(NameServer):用来保存 Broker 相关 Topic 等元信息并给 Producer ,提供 Consumer查找 Broker 信息。

11.?Kafka的消费者如何消费数据

消费者每次消费数据的时候,消费者都会记录消费的物理偏移量(offset)的位置等到下次消费时,他会接着上次位置继续消费。

12.?Kafka的优点

多生产者和多消费者基于磁盘的数据存储,换句话说,Kafka的数据天生就是持久化的。

高伸缩性,Kafka一开始就被设计成一个具有灵活伸缩性的系统,对在线集群的伸缩丝毫不影响整体系统的可用性。

高性能,结合横向扩展生产者、消费者和broker,Kafka可以轻松处理巨大的信息流,同时保证亚秒级的消息延迟。

13.?Kafka?的设计时什么样的呢?

Kafka 将消息以 topic 为单位进行归纳

将向 Kafka topic 发布消息的程序成为 producers.

将预订 topics 并消费消息的程序成为 consumer.

Kafka 以集群的方式运行,可以由一个或多个服务组成,每个服务叫做一个 broker. producers 通过网络将消息发送到 Kafka 集群,集群向消费者提供消息

14.?说说你对Consumer的了解?

1、获得Topic-Broker的映射关系。Consumer启动时需要指定Namesrv地址,与其中一个Namesrv建立长连接。消费者每隔30秒从Namesrv获取所有Topic的最新队列情况,Consumer跟Broker是长连接,会每隔30秒发心跳信息到Broker。

2、消费者端的负载均衡。根据消费者的消费模式不同,负载均衡方式也不同。

15.?Kafka新建的分区会在哪个目录下创建

在启动Kafka集群之前,我们需要配置好log.dirs参数,其值是Kafka数据的存放目录,这个参数可以配???置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性能。当然我?们也可以配置log.dir参数,含义一样。只需要设置其中一个即可。如果log.dirs参数只配置了一个目录,那么分配到各个Broker上的分区肯定只能在这个目录下创建文件夹用于存放数据。但是如果log.dirs参数配置了多个目录,那么Kafka会在哪个文件夹中创建分区目录呢?答案是:Kafka会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为Topic名+分区ID。注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录!也就是说,如果你给log.dirs参数新增了一个新的磁盘, 新的分区目录肯定是先在这个新的磁盘上创建直到这个新的磁盘目录拥有的分区目录不是最少为止。

16.?说一下kafka消费者消费过程

生产者将消息发送到 topic 中,消费者即可对其进行消费,其消费过程如下:

1)?consumer?向 broker?集群提交连接请求,其所连接上的任意 broker?都会向其发送 broker controller?的通信 URL,即 broker?controller?主机配置文件中的 listeners?地址

2)?当 consumer?指定了要消费的 topic?后,其会向 broker?controller?发送 poll?请求

3)?broker?controller?会为 consumer?分配一个或几个 partition?leader,并将该 partitioin?的当 前

offset 发送给 consumer

4)?consumer?会按照 broker?controller?分配的 partition?对其中的消息进行消费

5)?当消费者消费完该条消息后,消费者会向 broker?发送一个该消息已被消费的反馈,即 该消息的

offset

若为手动提交:可以是消费完一条消息就提交一个 offset,也可以是消费完这一批消息 后,提交最后一个消息的 offset。关键看代码怎么写。

若为自动提交:提交最后一个消息的 offset。

6)?当 broker?接到消费者的 offset?后,会更新到相应的_consumeroffset?中

7)?以上过程一直重复,直到消费者停止请求消息

8)?消费者可以重置 offset,从而可以灵活消费存储在 broker?上的消息

17.?介绍下Kafka

Kafka是一种高吞吐量、分布式、基于发布/订阅的消息系统,最初由LinkedIn公司开发,使用Scala??语言编写,目前是Apache的开源项目。

broker:Kafka服务器,负责消息存储和转发topic:消息类别,Kafka按照topic来分类消息

partition:topic的分区,一个topic可以包含多个partition,topic消息保存在各个partition上

offset:消息在日志中的位置,可以理解是消息在partition上的偏移量,也是代表该消息的唯一序号Producer:消息生产者

Consumer:消息消费者

ConsumerGroup:消费者分组,每个Consumer必须属于一个group

Zookeeper:保存着集群broker、topic、partition等meta数据;另外,还负责broker故障发现, partitionleader选举,负载均衡等功能

18.?什么情况会导致kafka运行变慢?

cpu性能瓶颈

磁盘读写瓶颈

网络瓶颈

6:Spring Cloud

1.?你曾阅读过Spring?Cloud的源码吗?我们知道,Spring?Cloud是通过Spring?Boot集成了很多第三方框架构成的。现在准备解析Spring?Cloud中某子框架的源码,若还没有找到合适的入手位置, 那么从哪里开始解析可能是一个不错的选择?

我自己曾阅读过Spring Cloud中的Eureka、OpenFeign、Ribbon等的源码。对于一个未曾阅读过的子框架源码,我认为从自动配置类开始解析可能是一个不错的选择。

我们知道Spring Cloud是通过Spring Boot将其它第三方框架集成进来的。Spring Boot最大的特点就是自动配置,我们可以通过导入相关Starter来实现需求功能的自动配置、相关核心业务类实例的创建等。也就是说,核心业务类都是集中在自动配置类中的。所以从这里下手分析应该是个不错的选择。

那么从哪里可以找到这个自动配置类呢?从导入的starter依赖工程的META-INF目录中的spring.factory 文件中可以找到。该文件的内容为key-value对,查找EnableAutoConfiguration的全限定性类名作为 key的value,这个value就是我们要找到的自动配置类。

2.?@EnableConfigurationProperties注解对于Starter的定义很?重要,请谈一上你对这个注解的认识。

@EnableConfigurationProperties注解在Starter定义时主要用于读取application.yml配置文件中相关?????的属性,并封装到指定类型的实例中,以备Starter中的核心业务实例使用。

具体来说,它就是开启了对@ConfigurationProperties注解的Bean的自动注册,注解到Spring容器

中。这种Bean有两种注册方式:在配置类使用@Bean方法注册,或直接使用该注解的value属性进行注册。若在配置类中使用@Bean注册,则需要在配置类中定义一个@Bean方法,该方法的返回值为“使用@ConfigurationProperties注解标注”的类。若直接使用该注解的value属性进行注册,则需要将这个“使?用@ConfigurationProperties注解标注”的类作为value属性值出现即可。

3.?Spring?Boot中定义了很多条件注解,这些注解一般用于对配置类的控制。在这些条件注解中有一个@ConditionalOnMissingBean?注解,你了解过嘛?请谈一下你对它的认识。

@ConditionalOnMissingBean注解是Spring?Boot提供的众多条件注册中的一个。其表示的意义是,当容器中没有指定名称或指定类型的Bean时,该条件为true。不过,这里需要强调一点的是,这里要查 找的“容器”是可以指定的。通过search属性指定。其search的范围有三种:仅搜索当前配置类容器;搜???索所有层次的父类容器,但不包含当前配置类容器;搜索当前配置类容器及其所有层次的父类容器,这?个是默认搜索范围。

4.?Spring?Cloud中默认情况下对于Eureka?Client实例的创建中, @RefreshScope注解是比较重要的,请谈一下你对这个注解的认识。

@RefreshScope注解是Spring???Cloud中定义的一个注解。该注解用于配置类,可以添加在配置类上,也可以添加在@Bean方法上。其表示的意思是,该@Bean方法会以多例的形式生成会自动刷新的Bean实例。这种方式就等价于在Spring的xml配置文件中指定标签的scope属性值为refresh。当然,若一个配???置类上添加了该注解,则表示该配置类中的所有@Bean方法创建的实例都是@RefreshScope的。

5.?Spring?Cloud中默认情况下对于Eureka?Client实例的创建是在EurekaClient的自动配置类中通过@Bean方法完成的。但在源码 中,这个@Bean方法上同时出现了@RefreshScope、

@ConditionalOnMissionBean,与@Lazy注解,从这些注解的意 义来分析,是否存在矛盾呢?它们联合使用又是什么意思呢?请谈一下你的看法。

首先来说,这三个注解的意义都是比较复杂的。

@RefreshScope注解是Spring?Cloud中定义的一个注解。其表示的意思是,该@Bean方法会以多例的形式生成会自动刷新的Bean实例。

@ConditionalOnMissionBean注解表示的意思是,只有当容器中没有@Bean要创建的实例时才会创建???新的实例,即这里创建的@Bean实例是单例的。

@Lazy注解表示延迟实例化。即在当前配置类被实例化时并不会调用这里的@Bean方法去创建实例,而是在代码执行过程中,真正需要这个@Bean方法的实例时才会创建。

这三个注解的联用不存在矛盾,其要表达的意思是,这个@Bean会以延迟实例化的形式创建一个单例的 对象,而该对象具有自动刷新功能。

6.?Spring?Cloud中大量地使用了条件注解,其中@ConditionalOnRefreshScope注解对于Eureka Client的创建非常重要。请谈一下你对这个注解的认识。

首先,关于条件注解,实际是Spring Boot中出现的内容,其一般应用于配置类中。表示只有当该条件满足时才会创建该实例。而您提到的@ConditionalOnRefreshScope注解,其实际是Eureka Client的自动配置类中的一个内部注解。该注解不同于Spring Boot中的一般性注解的是,其是一个复合条件注

解,其复合的条件有三个:

在当前类路径下具有RefreshScope类

在容器中要具有RefreshAutoConfiguration类的实例

指定的eureka.client.refresh.enable属性值为true。不过,其缺省值就是true。这也就是为什么我们的配置文件默认支持自动更新的原因。

只有当这个复合注解中的三个条件均成立时,@ConditionalOnRefreshScope注解才满足条件。此时才???有可能会调用创建Eureka?Client的@Bean方法。所以,该注解对于Eureka?Client的创建非常重要。

7.?你刚才已经谈过了对@ConditionalOnRefreshScope注解的认识,非常不错。不过,与这个注解相对应的另一个注解@ConditionalOnMissingRefreshScope,你是否了解?若关注过,谈一下你的认识。

@ConditionalOnMissingRefreshScope我也曾了解过。这个注解就像@ConditionalOnRefreshScope??注解一样,也是一个复合条件注解,其也包含了三个条件。不同的是,这个注解中的条件是或的关系,?只要满足其中一条这个注解就匹配上了。而@ConditionalOnRefreshScope注解中的三个条件是与的关???系,必须所有条件均满足其才能匹配上。

这个或的关系是通过让一个复合条件类继承自一个能够表示或关系的复合条件父类AnyNestedCondition实现的。这样的话,这个复合条件类中定义的多个内部条件类中,只要有一个匹?????配上,那么这个复合条件类就算匹配上了。

8.?Spring?Cloud中Eureka?Client的源码中有一个非常重要的类Applications,其被称为客户端注册表。请谈一下你对它的认识。

Applications类实例中封装了来自于Eureka?Server的所有注册信息,通常称其为“客户端注册表”。只所以要强调“客户端”是因为,服务端的注册表不是这样表示的,是一个Map。

该类中封装着一个非常重要的Map集合,key为微服务名称,而Value则为Application实例。Application类中封装了一个Set集合,集合元素为“可以提供该微服务的所有主机的InstanceInfo”。也就是说,Applications中封装着所有微服务的所有提供者信息。

9.?Spring?Cloud中Eureka?Client与Eureka?Server的通信,及Eureka?Server间的通信是如何实现的?请简单介绍一下。

Spring Cloud中Eureka Client与Eureka Server的通信,及Eureka Server间的通信,均采用的是Jersey框架。

Jersey框架是一个开源的RESTful框架,实现了JAX-RS规范。该框架的作用与SpringMVC是相同的,其也是用户提交URI后,在处理器中进行路由匹配,路由到指定的后台业务。这个路由功能同样也是通过处?理器完成的,只不过这里的处理器不叫Controller,而叫Resource。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-12-07 12:22:55  更:2021-12-07 12:25:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/8 9:23:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码