面试10-20

11.Dubbo的架构设计是怎样的

Dubbo中的架构设计是非常优秀的,分为了很多层次,并且每层都是可以扩展的,比如:

  1. Proxy服务代理层,支持JDK动态代理、javassist等代理机制
  2. Registry注册中心层,支持Zookeeper、Redis等作为注册中心
  3. Protocol远程调用层,支持Dubbo、Http等调用协议
  4. Transport网络传输层,支持netty、mina等网络传输框架
  5. Serialize数据序列化层,支持JSON、Hessian等序列化机制

各层说明

  • config配置层:对外配置接口,以ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过spring解析配置生成配置类
  • proxy 服务代理层:服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton, 以 ServiceProxy为中心,扩展接口ProxyFactory
  • registry 注册中心层:封装服务地址的注册与发现,以服务URL为中心,扩展接口为RegistryFactory , Registry
  • cluster路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster, Directory ,Router , LoadBalance。
  • monitor监控层:RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory ,Monitor, MonitorService
  • protocol远程调用层:封装RPC调用,以Invocation ,Result为中心,扩展接口为 Protocol, Invoker, Expoter
  • exchange信息交换层:封装请求响应模式,同步转异步,以Request,Response为中心,扩展接口为Exchanger,ExchangeChannel , Exchangeclient ,ExchangeServer
  • transport网络传输层:抽象mina和netty为统一接口,以Message为中心,扩展接口为(Channel, Transporter,Client,Server, Codec
  • serialize数据序列化层:可复用的一些工具,扩展接口为Serialization , ObjectInput , ObjectOutput, ThreadPool

关系说明

  • 在RPC中,Protocol是核心层,也就是只要有Protocol + lnvoker + Exporter就可以完成非透明的RPC调用,然后在Tlnvoker的主过程上Fiter拦截点。
  • 图中的Consutmer和Provider是抽象概念,只是想让看图者更直观的了解哪些类分属于客户端与服务器端,不用Client和Sever的原因是Dube 在很多场景下都使用Provider, Consumier, Registry,Monitor划分逻辑拓普节点,保持统一概念。
  • 而Cluster是外围概念,所以Cluster 的目的是将多个Inwvoker仿装成一个 lnvoker,这样其它人只要关注Protocol层Invcker即可,加上Cluster或者去掉(Cluster对其它层都不会造成影响,因为只有一个提供者时,是不需要Cluster的。
  • Proxy 层封装了所有接口的透明化代理,而在其它层都以Inwvoker 为中心,只有到了暴露给用户使用时,才用Prory将 imvoker韩成接口,或将接口实现转成lInwoker ,也就是去掉 Proxy层RPC是可以Run的,只是不那么透明,不那么看起来像调本地服务一样调远程服务。
  • 而Remoting 实现是 Dubo协议的实现,如果你选择RMI协议,整个Remoting 都不会用上,Remoting 内部再划为 Transport传翰层和Exchange信息交换层,Transport层只负责单向消息传输,是对Mina, Netty, Grizly 的抽象,它也可以扩展UDP传输,而 Exchange层是在传输层之上封装了Request-REesponse语义。。
  • Registry和Monitor实际上不算一层,而是一个独立的节点,只是为了全局概览,用层的方式画在一起。

12.Dubbo是如何完成服务导出的

  1. 首先Dubo会将程序员所使用的@DubboService注解或@Sevice注解进行解析得到程序员所定义的服务参数,包括定义的服务名、服务接口、服务超时时间、服务协议等等,得到一个ServiceBean。
  2. 然后调用serviceBean的export方法进行服务导出
  3. 然后将服务信息注册到注册中心,如果有多个协议,多个注册中心,那就将服务按单个协议,单个注册中心进行注册
  4. 将服务信息注册到注册中心后,还会绑定一些监听器,监听动态配置中心的变更
  5. 还会根据服务协议启动对应的Web服务器或网络框架,比如Tomcat、Netty等

13.Dubbo是如何完成服务引入的?

  1. 当程序员使用@Reference注解来引入一个服务时,Dubbo会将注解和服务的信息解析出来,得到当前所引用的服务名
  2. 然后从注册中心进行查询服务信息,得到服务的提供者信息,并存在消费端的服务目录中
  3. 并绑定一些监听器用来监听动态配置中心的变更
  4. 然后根据查询得到的服务提供者信息生成一个服务接口的代理对象,并放入Spring容器中作为Bean

14.Dubbo支持哪些负载均衡策略

  1. 随机:从多个服务提供者随机选择一个来处理本次请求,调用量越大则分布越均匀,并支持按权重设置随机概率
  2. 轮询:依次选择服务提供者来处理请求,并支持按权重进行轮询,底层采用的是平滑加权轮询算法
  3. 最小活跃调用数:统计服务提供者当前正在处理的请求,下次请求过来则交给活跃数最小的服务器来处理
  4. 一致性哈希:相同参数的请求总是发到同一个服务提供者

15.epoll和poll的区别

  1. select模型,使用的是数组来存储Socket连接文件描述符,容量是固定的,需要通过轮询来判断是否发生了10事件
  2. pol模型,使用的是链表来存储Socket连接文件描述符,容量是不固定的,同样需要通过轮询来判断是否发生了10事件
  3. epol模型,epoll和poll是完全不同的, epoll是一 种事件通知模型, 当发生了I0事件时,应用程序才进行I0操作,不需要像polI模型那样主动去轮询

16.Explain语句结果中各个字段分表表示什么

列名 描述
id 查询语询中每出现一个SELECT关键字, MySQL就会
为於分配个唯一的id值, 某些子查询会被优化为
join查询,那么出现的id会一样
select_type SELECT关键字对应的那个查询的类型
table 表名
partitions 匹配的分区信息
type 针对单表的查询方式(全表扫描、索引)
possible_keys 可能用到的索引
key 实际上使用的索引
key_len 实际使用到的索引长度
ref 当使用索引列等值查询时,与索引列进行等值匹配的对象信息
rows 预估的需要读取的记录条数
filtered 某个表经过搜索条件过滤后剩余记录条数的百分比
Extra 一些额外信息,比如排序等

17.HashMap的扩容机制

1.7版本
1.先生成新数组
2.遍历老数组中的每个位置上的链表上的每个元素
3.取每个元素的key,基于新数组长度,计算出每个元素在新数组中的下标
4.将元素添加到新数组中去
5.所有元素转移完了之后,将新数组赋值给HashMap对象的table属性
1.8版本
1.先生成新数组
2.遍历老数组中的每个位置上的链表或红黑树
3.如果是链表,则直接将链表中的每个元索重新计算下标,并添加到新数组中去
4.如果是红黑树,则先遍历红黑树,先计算出红黑树中每个元索对应在新数组中的下标位置
a.统计每个下标位置的元素个数
b.如果该位置下的元索个数超过了8,则生成一个新的红黑树, 并将根节点的添加到新数组的对应位置
c.如果该位置下的元素个数没有超过8,那么则生成一个链表, 将链表的头节点添加到新数组的对应位置
5.所有元素转移完了之后,将新数组赋值给HashMap对象的table属性

18.Innodb是如何实现事务的

lInnodb通过Buffer Pool,LogBuffer,Redo Log,Undo Log来实现事务,以一个update语句为例:

  1. Innodb在收到一个update语句后,会先根据条件找到数据所在的页,并将该页缓存在Buffer Pool中
  2. 执行update语句,修改Buffer Pool中的数据,也就是内存中的数据
  3. 针对update语句生成一个RedoLog对象,并存入LogBuffer中
  4. 针对update语句生成undolog日志,用于事务回滚
  5. 如果事务提交,那么则把RedoLog对象进行持久化,后续还有其他机制将Buffer Pool中所修改的数据页持久化到磁盘中6.如果事务回滚,则利用undolog日志进行回滚

19.Java死锁如何避免

造成死锁的几个原因:
1.一个资源每次只能被一个线程使用
2.—个线程在阻塞等待某个资源时,不释放已占有资源
3.一个线程已经获得的资源,在未使用完之前,不能被强行剥夺
4.若干线程形成头尾相接的循环等待资源关系

这是造成死锁必须要达到的4个条件,如果要避免死锁,只需要不满足其中某一个条件即可。而其中前3个条件是作为锁要符合的条件,所以要避免死锁就需要打破第4个条件,不出现循环等待锁的关系。

在开发过程中:
1.要注意加锁顺序,保证每个线程按同样的顺序进行加锁2.要注意加锁时限,可以针对所设置一个超时时间
3.要注意死锁检查,这是一种预防机制,确保在第一时间发现死锁并进行解决

20.Java中的异常体系是怎样的

  • Java中的所有异常都来自顶级父类Throwable.
  • Throwable下有两个子类Exception和Error。
  • Error表示非常严重的错误,比如java.lang.StackOverFlowError和Java.lang.OutOfMemoryError, 通常这些错误出现时,仅仅想靠程序自己是解决不了的,可能是虚拟机、磁盘、操作系统层面出现的问题了,所以通常也不建议在代码中去捕获这些Error,因为捕获的意义不大,因为程序可能已经根本运行不了了。
  • Exception表示异常,示程序出现Exception时,可以靠程自己来解决的,比如NullPointerException、 llgalAccessException等 ,我们可以捕获这些异常来做特殊处理。
  • Exception的子类通常又可以分为RuntimeException和非RuntimeException两类
  • RunTimeException表示运行期异常,示这个异常是在代码运行过程中抛出的,这些异常是非检查异常,程序中可以选择捕获处理,可以怀处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生,比如NullPointerException、 IndexOutOfBoundsException等。
  • 非RuntimeException表示非运行期异常,也就是我们常说的检查异常,是必须进行处理的异常,如果不处理,程序就不能检查异常通过。如IOException、 SQL Exception等以及
    胪自定义的Exception异常。

21.Java中有哪些类加载器

JDK自带有三个类载器: bootstrap ClassLoader、ExtClassLoader、AppClassLoader。

  • BootStrapClassLoader是ExtClassLoader的父类加载器,默认负责加载%JAVA_ HOME%lib下的jar包和class文件。
  • ExtClassLoader是AppClassLoader的父类加载器,负责加载%JAVA _HOME%/ib/ext文件夹下的jar包和class类。
  • AppClassLoader是自定义类加载器的父类, 负责加载classpath下的类文件。

22.Innodb和Myisam的区别?

1)InnoDB支持事务,MyISAM不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而MyISAM就不可以了。
2)MyISAM适合查询以及插入为主的应用,InnoDB适合频繁修改以及涉及到安全性较高的应用
3)InnoDB支持外键,MyISAM不支持
4)从MySQL5.5.5以后,InnoDB是默认引擎
5)InnoDB不支持FULLTEXT类型的索引
6)InnoDB中不保存表的行数,如select count() from table时,InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含where条件时MyISAM也需要扫描整个表
7)对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立联合索引
8)清空整个表时,InnoDB是一行一行的删除,效率非常慢。MyISAM则会重建表
9)InnoDB支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like ‘%lee%’。

  1. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

  2. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

  3. InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。
    MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
    也就是说:InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针。

  4. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快(注意不能加有任何WHERE条件);
    那么为什么InnoDB没有了这个变量呢?
    因为InnoDB的事务特性,在同一时刻表中的行数对于不同的事务而言是不一样的,因此count统计会计算对于当前事务而言可以统计到的行数,而不是将总行数储存起来方便快速查询。InnoDB会尝试遍历一个尽可能小的索引除非优化器提示使用别的索引。如果二级索引不存在,InnoDB还会尝试去遍历其他聚簇索引。
    如果索引并没有完全处于InnoDB维护的缓冲区(Buffer Pool)中,count操作会比较费时。可以建立一个记录总行数的表并让你的程序在INSERT/DELETE时更新对应的数据。和上面提到的问题一样,如果此时存在多个事务的话这种方案也不太好用。如果得到大致的行数值已经足够满足需求可以尝试SHOW TABLE STATUS

  5. Innodb不支持全文索引,而MyISAM支持全文索引,在涉及全文索引领域的查询效率上MyISAM速度更快高;PS:5.7以后的InnoDB支持全文索引了

  6. MyISAM表格可以被压缩后进行查询操作

  7. InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁
    InnoDB的行锁是实现在索引上的,而不是锁在物理行记录上。潜台词是,如果访问没有命中索引,也无法使用行锁,将要退化为表锁。
    8、InnoDB表必须有唯一索引(如主键)(用户没有指定的话会自己找/生产一个隐藏列Row_id来充当默认主键),而Myisam可以没有
    9、Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI

     Innodb:frm是表定义文件,ibd是数据文件
     
     Myisam:frm是表定义文件,myd是数据文件,myi是索引文件
    

23.JDK1.7到JDK1.8 HashMap发生了什么变化(底层)?

  1. 1.7中底层是数组+链表,1.8中底层是数组+链表+红黑树,加红黑树的目的是提高HashMap插入和查询整体效率
  2. 1.7中链表插入使用的是头插法,1.8中链表插入使用的是尾插法,因为1.8中插入key和value时需要判断铤表元素个数,所以需要遍历链表统计链表元素个数,所以正好就直接使用尾插法
  3. 1.7中哈希算法比较复杂,存在各种右移与异或运算,1.8中进行了简化,因为复杂的哈希算法的目的就是提高散列性,来提供H ashMap的整体效率,而1.中新增了红黑树,所以可以适当的简化哈希算法,节省CPU资源
posted @ 2021-12-05 23:00  正在努力的澎澎  阅读(52)  评论(0)    收藏  举报