admin管理员组文章数量:1122852
模拟面试面试题汇总
第一轮面试题
目录
模拟面试面试题汇总
第一轮面试题
一、描述下数据库中的事务--ACID各个的特点。
二、什么是springboot?你们公司是用的哪个版本?
第二轮面试题
第三轮面试题
第四轮面试题
第五轮面试
1.死信、延迟、重试队列
8.微服务
9.java锁机制的问题
英斯特笔试:
软通动力电话面试:
多飞网络科技:
北京爱朗格瑞:
掌缘信息科技:
中科软
端木公司
一、描述下数据库中的事务--ACID各个的特点。
原子性:事务中的操作要么全部成功要么全部失败。
一致性:事务前后数据的完整性必须保持一致。
隔离性:多个并发的事务之间是相互隔离的,互不干扰的。
持久性:事务提交后,数据是永久改变的。
二、什么是springboot?你们公司是用的哪个版本?
SpringBoot是Spring推出用于解决传统框架配置文件冗余,装配组件繁杂的基于Maven的解决方案,旨在快速搭建单个微服务。
版本号:2.1.6
三、什么是redis?
Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
四、如何理解springcloud微服务项目中,eureka,provider,consumer它们之间的关系?
eureka:提供服务注册于发现
provider:服务提供方法将自身注册到eureka,让消费方找到
consumer:服务消费方从eureka获取注册服务列表,能够消费服务
五、mysql默认的存储引擎是什么?
Mysql在V5.1之前默认存储引擎是MyISAM;在此之后默认存储引擎是InnoDB。
MyISAM不支持事务,InnoDB支持事务。
MySIAM不支持外键,InnoDB支持外键,
MySIAM支持全文索引,InnoDB不支持全文索引。
六、什么是跨域?
要了解跨域,先要说说同源策略。所谓同源是指,域名,协议,端口相同,有一个不一样则是跨域。
七、什么是token?
Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌。
当第一次登录后,服务器生成一个Token便将此Token返回给客户端,
以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
八、什么是RESTful?
首先rest是一种API的模式,常以JSON格式编写。符合rest约束风格和原则的应用程序或设计就是RESTful。
九、SpringCloud解决了哪些问题?
与分布式系统相关的复杂性
处理服务发现的能力
解决冗余问题
负载平衡
减少性能问题
十、微服务中什么是熔断?什么是服务降级?
服务熔断的作用是当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。
服务降级是为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback(退路)错误处理信息。
十一、微服务的优缺点是什么?
优点:
易于开发和维护:因为一个服务只关注一个特定的业务,业务就变得比较清晰。同时维护起来也是比较方便。
单个服务启动比较快:单个服务代码量不会很多,启动起来就会很快。
便于伸缩:如果系统中有三个服务ABC,服务B的访问量比较大,我们可以将服务B集群部署。
缺点:
运维要求比较高:之前就一个war包,现在一个系统中会有很多的服务,每个服务都对应一个war包,维护起来就会变得很麻烦。
技术复杂性提高:微服务就会带来一系列的问题,事务问题,Session一致性问题,锁问题等。
十二、微服务之间如何独立通讯的?
同步通信:dobbo通过 RPC 远程过程调用、springcloud通过 REST接口json调用等。
异步:消息队列,如:RabbitMq、ActiveMq、Kafka 等。
十三、SpringCloud 和 Dubbo 有哪些区别?
首先,他们都是分布式管理框架。
dubbo 是二进制传输,占用带宽会少一点。SpringCloud是http 传输,带宽会多一点,同时使用http协议一般会使用JSON报文,消耗会更大。
SpringCloud 接口协议约定比较松散,需要强有力的行政措施来限制接口无序升级。
最大的区别:
Spring Cloud抛弃了Dubbo 的RPC通信,采用的是基于HTTP的REST方式。
十四、SpringBoot 和 SpringCloud 之间关系?
SpringBoot:专注于快速方便的开发单个个体微服务(关注微观);
SpringCloud:关注全局的微服务协调治理框架,将SpringBoot开发的一个个单体微服务组合并管理起来(关注宏观);
SpringBoot可以离开SpringCloud独立使用,但是SpringCloud不可以离开SpringBoot,属于依赖关系。
十五、eureka和zookeeper的区别?
eureka和zookeeper都可以提供服务注册与发现的功能,zookeeper 是CP原则,强一致性和分区容错性。eureka 是AP 原则 可用性和分区容错性。
zookeeper当主节点故障时,zk会在剩余节点重新选择主节点,耗时过长,虽然最终能够恢复,但是选取主节点期间会导致服务不可用,这是不能容忍的。
eureka各个节点是平等的,一个节点挂掉,其他节点仍会正常保证服务。
十六、mycat是什么?你们公司分库分表的分片规则是什么?
Mycat是基于MySQL的数据库中间件,用来协调切分后的数据库,使其可以进行统一管理。
分片规则:取模分片 PartitionByMode
十七、什么是集合?
集合有两个父接口,一个collection,一个Map;
而collection有两个子接口,一个List,一个Set;
List有两个常见的实现类 ArrayList,LinkedList;
Set有两个常见的实现类 HashSet,TreeSet;
Map有两个常见的实现类 HashMap,HashTable。
十八、什么是dubbo?
Dubbo和Springcloud都是分布式服务中常用的框架。dubbo与cloud不同,dubbo基于RPC协议。它提供了三大核心功能: 面向接口的远程方法调用,
智能容错和负载均衡, 以及服务自动注册和发现。
十九、什么是spring?
Spring是一个开源的轻量级的Java开发框架。是一种简化应用程序的开发。
在spring出来之前,service层调用dao层都是用new的方式,在spring出来之后,service层和到dao层都会放在spring容器去管理,
这是spring的第一种特性,我们称之为IOC,控制反转。
spring还有一种特性,我们称之为AOP,大白话,所谓“面向切面”,说白了就是专门的人干专门的事。
在项目很多公有的或是要被重复被调用的模块可以被抽取出来,利用的就AOP的特性,例如日志模块。
第二轮面试题
一、SSM的开发步骤是什么?
"二八"
web.xml
1.前端控制器DispatcherServlet
2.过滤器CharacterEncodingFilter
applicationContext.xml
1.扫描包 <context:component-scan base-package="cn"/>
2.mvc驱动 <mvc:annotation-driven/>
3.事务驱动 <tx:annotation-driven transaction-manager="txManager"/>
4.配置数据源
5.SqlSessionFactoryBean
6.配置事务
7.数据映射器
8.视图解析器
二、设计一个权限模块?
权限模块是数据库的安保系统,决定谁可以使用,谁拥有权限,有user、role、permission表,通过user-role、role-permission关联表(码表)进行关联,
给角色分配权限,角色发放权限给用户。
三、什么是docker?
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,
也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
四、什么是dockfile?
Dockerfile是一个包含用于组合映像的命令的文本文档,可以使用在命令行中调用任何命令。
五、什么是docker-compose?
可以管理多个 Docker 容器组成一个应用,定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。
然后,只要一个命令,就能同时启动/关闭这些容器。
- 什么是Portainer?
Portainer
是Docker的图形化管理工具
七、在公司里使用的docker的版本是什么?
18.09.7
八、镜像和容器的关系?
容器是可写的,镜像是可读的。容器是镜像的实例,镜像是容器的静态备份。
九、分布式锁中的基于redis的setnx的原理以及set和setnx的区别是什么?
分布式锁基于setnx原理,如果 SETNX 返回1,说明该进程获得锁。
如果 SETNX 返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作,以获得锁。
redis中set是将字符串值 value 关联到 key 。如果 key 已经持有其他值, SET 就覆写旧值,无视类型。
setnx是当且仅当 key 不存在时,可以设置 value值 。若给定的 key 已经存在,则 SETNX 不做任何动作。
十、什么是springcloud,springcloud中的组件有哪些?分别描述下它的原理?
SpringCloud架构中最核心的是Eureka注册中心,它是一个通讯录。所有p端和c端都会注册在上面,cloud中c端调用p端应用feign组件进行调用。应用程序导致网络请求出现问题时,hystrix组件实现容错机制。用户请求量变大是,用ribbon组件实现客户端的负载均衡。而服务器端的负载均衡通常使用nginx反向代理。SpringCloud中有类似于servlet过滤器的组件,zuul网关组件对整个服务架构进行安全过滤。当使用一个服务调用多个feign组件的时候,sleuth+zipkin组件用来服务追踪,可以用来调试接口(追踪问题)。config组件进行统一配置。
dubbo基于RPC,SpringCloud基于RESTful。
组件ribbon、feign、hstrix 、eureka、zuul。
十一、什么是jmeter?
Apache JMeter 是 Apache 组织开发的基于 Java 的压力测试工具。用于对软件做压力测试,它最初被设计用于 Web 应用测试,但后来扩展到其他测试领域。
发送请求到服务端,获取目标服务的统计信息,生成不同格式的报告。
第三轮面试题
1.描述一下你上一家公司SSM项目的功能模块有哪些?
2.描述一下你上一家公司dubbo+zookeeper项目的功能模块有哪些?
3.描述一下你上一家公司springcloud项目的功能模块有哪些?
4.描述一下你上一家公司项目中权限模块的思路?
5.描述一下上一家公司项目中的报表模块的思路?
第四轮面试题
一、什么是mybatis?
一种持久层框架,类似于JDBC访问数据库的操作,
我们说JDBC使用到的对象有Connection对象,PreparedStatement对象,ResultSet对象。
而Mybatis框架的核心对象有SqlSessionFactoryBuilder对象,SqlSessionFactory对象,SqlSession对象。
并且myibatis框架和hibernate框架最大的区别就在于mybatis它的灵活性比较高。
二、什么是spring?
在spring出来之前,service层调用dao层都是用new的方式。
在spring出来之后,service层和dao层都会放在spring容器去管理,这是spring的第一种特性,我们称之为IOC,控制反转。
spring还有一种特性,我们称之为AOP,大白话,“面向切面”,说白了就是专门的人干专门的事。在项目很多公有的或是
要被重复被调用的模块可以被抽取出来,利用的就是AOP的特性,例如日志模块。
三、什么是SpringMVC?
当用户发送请求到springmvc中的前端控制器中,通过映射器和适配器返回ModelAndView对象到客户端。这就是SpringMVC的基本原理。
- 什么是SSM?
SSM搭建的版本有很多,例如有一个版本可以这么搭建,两个核心配置文件web.xml,applicationContext.xml。
1.前端控制器DispatcherServlet
2.过滤器CharacterEncodingFilter
applicationContext.xml
1.扫描包 <context:component-scan base-package="cn"/>
2.mvc驱动 <mvc:annotation-driven/>
3.事务驱动 <tx:annotation-driven transaction-manager="txManager"/>
4.配置数据源
5.SqlSessionFactoryBean
6.配置事务
7.数据映射器
8.视图解析器
五、什么是集合?
集合有两个父接口,一个Collection,一个Map,而Collection有两个子接口,一个List,一个Set,List有两个常见的实现类ArrayList,LinkedList,
Set有两个常见的实现类HashSet,TreeSet,Map有两个常见的实现类HashMap,HashTable
六、什么是SpringCloud?
SpringCloud架构中最核心的是Eureka注册中心,它是一个通讯录。所有p端和c端都会注册在上面,cloud中c端调用p端应用feign组件进行调用。应用程序导致网络请求出现问题时,hystrix组件实现容错机制。用户请求量变大时,用ribbon组件实现客户端的负载均衡。而服务器端的负载均衡通常使用nginx反向代理。SpringCloud中有类似于servlet过滤器的组件,zuul网关组件对整个服务架构进行安全过滤。
dubbo基于RPC,SpringCloud基于RESTful。
七、什么是Dubbo?
Dubbo和Springcloud都是分布式服务中常用的框架。dubbo与cloud不同,dubbo基于RPC协议。它提供了三大核心功能: 面向接口的远程方法调用,
智能容错和负载均衡, 以及服务自动注册和发现。
Dubbo按照分层的方式来架构,可以最大限度地松耦合。Dubbo采用一种非常简单的模型, 要么提供方提供服务, 要么是消费方消费服务, 所以基于这一点可以抽象出服务提供方和服务消费方两个角色。
八、什么是消息中间件?
消息中间件利用高效可靠的消息传递机制进行异步的数据传输,并基于数据通信进行分布式系统的集成。通过提供消息队列模型和消息传递机制,可以在分布式环境下扩展进程间的通信。
九、eureka和zookeeper的区别?
首先他们都是服务注册和发现的功能,cloud一般选择eureka作为注册中心,dubbo一般选择zookeeper作为注册中心。基于CAP原则,eurek是AP原则,即可用性和分区容错性,zookeeper是CP原则,即强一致性和分区容错性。
十、分布式锁的概念?
在分布式系统中,由于分布式系统的分布性,即多线程和多进程并且分布在不同机器中,这两种锁将失去原有锁的效果,需要我们自己实现分布式锁——分布式锁。
在多线程的环境下,多个线程同时访问同一个资源,导致线程不安全,使用分布式锁来解决这个线程安全问题。
分布式抢购用到分布式锁,上锁;第二个用户要等待第一个用户完成才能进行抢购;利用setnx设置解决安全性问题,缺点是性能过低。
第五轮面试
1.死信、延迟、重试队列
死信、延迟、重试队列
#死信队列
DLQ(Deal Letter Queue),死信队列。当一个消息在队列中变成死信之后,他能被重新发送到 DLQ 中,与 DLQ 绑定到队列就是死信队列。
#什么情况下需要死信队列
·消息被拒绝
·消息过期
·队列达到最大长度
生产者生产一条消息,存储到普通队列中;设置队列的过期时间为 10 秒,在 10 秒内没有消费者消费消息,那么判定消息过期;此时如果设置了死信队列,过期消息被丢给死信队列交换机,然后被存储在死信队列中。
#延迟队列
顾名思义就是延迟执行消息,比如我们可以增加一个队列并设置其超时时间为 10 秒并且不设置任何消费者,等到消息超时,我们可以将消息放入死信队列,让消费者监听这个死信队列就达到了延迟队列的效果。
#重试队列
重试的消息在延迟的某个时间点(业务可设置)后,再次投递给消费者。而如果一直这样重复消费都持续失败到一定次数,就会投递到死信队列,最后需要进行人工干预。
- 双亲委派模型
双亲委派模型
#类加载器
#加载类的开放性
类加载器(ClassLoader)是 Java 语言的一项创新,也是 Java 流行的一个重要原因。在类加载的第一阶段“加载”过程中,需要通过一个类的全限定名来获取定义此类的二进制字节流,完成这个动作的代码块就是 类加载器。这一动作是放在 Java 虚拟机外部去实现的,以便让应用程序自己决定如何获取所需的类。
虚拟机规范并没有指明二进制字节流要从一个 Class 文件获取,或者说根本没有指明从哪里获取、怎样获取。这种开放使得 Java 在很多领域得到充分运用。
#类加载器与类的唯一性
类加载器虽然只用于实现类的加载动作,但是对于任意一个类,都需要由加载它的类加载器和这个类本身共同确立其在 Java 虚拟机中的 唯一性。通俗的说,JVM 中两个类是否“相等”,首先就必须是同一个类加载器加载的,否则,即使这两个类来源于同一个 Class 文件,被同一个虚拟机加载,只要类加载器不同,那么这两个类必定是不相等的。
这里的“相等”,包括代表类的 Class 对象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回结果,也包括使用 instanceof 关键字做对象所属关系判定等情况。
#双亲委派模型
类加载器种类
从 Java 虚拟机的角度来说,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用 C++ 语言实现(HotSpot 虚拟机中),是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都有 Java 语言实现,独立于虚拟机外部,并且全部继承自 java.lang.ClassLoader。
从开发者的角度,类加载器可以细分为:
- 启动(Bootstrap)类加载器:负责将 Java_Home/lib 下面的类库加载到内存中(比如 rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
- 标准扩展(Extension)类加载器:是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader) 实现的。它负责将 Java_Home /lib/ext 或者由系统变量 java.ext.dir 指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
- 应用程序(Application)类加载器:是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader) 实现的。它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器。由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般称为系统(System)加载器。
除此之外,还有自定义的类加载器,它们之间的层次关系被称为类加载器的 双亲委派模型。该模型要求除了顶层的启动类加载器外,其余的类加载器都应该有自己的父类加载器,而这种父子关系一般通过组合(Composition)关系来实现,而不是通过继承(Inheritance)。
双亲委派模型
#双亲委派模型过程
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
使用双亲委派模型的好处在于 Java 类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类 java.lang.Object ,它存在在 rt.jar 中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的 Bootstrap ClassLoader 进行加载,因此 Object 类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个 java.lang.Object 的同名类并放在 ClassPath 中,那系统中将会出现多个不同的 Object 类,程序将混乱。因此,如果开发者尝试编写一个与 rt.jar 类库中重名的 Java 类,可以正常编译,但是永远无法被加载运行。
#双亲委派模型的系统实现
在 java.lang.ClassLoader 的 loadClass() 方法中,先检查是否已经被加载过,若没有加载则调用父类加载器的 loadClass() 方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父加载失败,则抛出 ClassNotFoundException 异常后,再调用自己的 findClass() 方法进行加载。
注意,双亲委派模型是 Java 设计者推荐给开发者的类加载器的实现方式,并不是强制规定的。大多数的类加载器都遵循这个模型,但是 JDK 中也有较大规模破坏双亲模型的情况,例如线程上下文类加载器(Thread Context ClassLoader)的出
现
- zookeeper假死脑裂
Zookeeper 假死脑裂
该问题就是服务集群因为网络震荡导致的多主多从问题,解决方案就是设置服务切换的超时时间,但也同时会导致无法达到高可用的要求。
- MySQL优化
MySQL 优化
- 表关联查询时务必遵循 小表驱动大表 原则;
- 使用查询语句 where 条件时,不允许出现 函数,否则索引会失效;
- 使用单表查询时,相同字段尽量不要用 OR,因为可能导致索引失效,可以使用 UNION 替代;
- LIKE 语句不允许使用 % 开头,否则索引会失效;
- 组合索引一定要遵循 从左到右 原则,否则索引会失效;
- 索引不宜过多,根据实际情况决定,尽量不要超过 10 个;
- 每张表都必须有 主键,达到加快查询效率的目的;
- 分表,可根据业务字段尾数中的个位或十位或百位(以此类推)做表名达到分表的目的;
- 分库,可根据业务字段尾数中的个位或十位或百位(以此类推)做库名达到分库的目的;
- 表分区,类似于硬盘分区,可以将某个时间段的数据放在分区里,加快查询速度,可以配合 分表 + 表分区 结合使用;
#神器 EXPLAIN 语句
EXPLAIN 显示了 MySQL 如何使用索引来处理 SELECT 语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。
使用方法,在 SELECT 语句前加上 EXPLAIN 即可,如:
EXPLAIN SELECT * FROM tb_item WHERE cid IN (SELECT id FROM tb_item_cat)
-
- id: SELECT 识别符。这是 SELECT 的查询序列号
- select_type: SELECT类型,可以为以下任何一种
- table: 输出的行所引用的表
- partitions: 表分区
- type: 联接类型。下面给出各种联接类型,按照 从最佳类型到最坏类型 进行排序
system: 表仅有一行(=系统表)。这是 const 联接类型的一个特例。
possible_keys:
指出 MySQL 能使用哪个索引在该表中找到行
-
- key: 显示 MySQL 实际决定使用的键(索引)。如果没有选择索引, 键是 NULL。
- key_len: 显示 MySQL 决定使用的键长度。如果键是 NULL, 则长度为 NULL。
- ref: 显示使用哪个列或常数与 key 一起从表中选择行。
- rows: 显示 MySQL 认为它执行查询时必须检查的行数。多行之间的数据相乘可以估算要处理的行数。
- filtered: 显示了通过条件过滤出的行数的百分比估计值。
- Extra: 该列包含 MySQL 解决查询的详细信息
- JDK8新特性
JDK8 新特性
概述
以下列出两点重要特性:
- Lambda 表达式(匿名函数)
- Stream 多线程并行数据处理(重要)
- 接口的默认方法只需要使用 default 关键字即可,这个特征又叫做 扩展方法
- Lambda 表达式
- Functional 接口 函数式接口 是指仅仅只包含一个抽象方法的接口,每一个该类型的 Lambda 表达式都会被匹配到这个抽象方法。你只需要给你的接口添加 @FunctionalInterface 注解
- 使用 :: 双冒号关键字来传递方法(静态方法和非静态方法)
- Predicate 接口和 Lambda 表达式
- Function 接口
- Supplier 接口,返回一个任意范型的值,和 Function 接口不同的是该接口 没有任何参数
- Consumer 接口,接收一个任意范型的值,和 Function 接口不同的是该接口 没有任何值
- Optional 类
新特性
小栗子
package com.funtl.jdk8.feature.lambda;
import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;
/**
* Lambda 基本用法
* <p>Title: BaseLambda</p>
* <p>Description: </p>
*
* @author Lusifer
* @version 1.0.0
* @date 2019/1/6 10:42
*/public class BaseLambda {
public static void main(String[] args) {
testForeach();
testStreamDuplicates();
}
/**
* Lambda 遍历
*/
public static void testForeach() {
// 定义一个数组
String[] array = {
"尼尔机械纪元",
"关于我转生成为史莱姆这件事",
"实力至上主义教师",
"地狱少女"
};
// 转换成集合
List<String> acgs = Arrays.asList(array);
// 传统的遍历方式
System.out.println("传统的遍历方式:");
for (String acg : acgs) {
System.out.println(acg);
}
System.out.println();
// 使用 Lambda 表达式以及函数操作(functional operation)
System.out.println("Lambda 表达式以及函数操作:");
acgs.forEach((acg) -> System.out.println(acg));
System.out.println();
// 在 Java 8 中使用双冒号操作符(double colon operator)
System.out.println("使用双冒号操作符:");
acgs.forEach(System.out::println);
System.out.println();
}
/**
* Stream 去重复
* String 和 Integer 可以使用该方法去重
*/
public static void testStreamDuplicates() {
System.out.println("Stream 去重复:");
// 定义一个数组
String[] array = {
"尼尔机械纪元",
"尼尔机械纪元",
"关于我转生成为史莱姆这件事",
"关于我转生成为史莱姆这件事",
"实力至上主义教师",
"实力至上主义教师",
"地狱少女",
"地狱少女"
};
// 转换成集合
List<String> acgs = Arrays.asList(array);
// Stream 去重复
acgs = acgs.stream().distinct().collect(Collectors.toList());
// 打印
acgs.forEach(System.out::println);
}}
- JavaScript this 关键字
JavaScript this 关键字
概述
任何执行 JavaScript 的环境称之为 执行上下文,默认情况下,执行上下文是全局的,这意味着如果代码作为简单函数调用的一部分执行,则该 this 变量将引用 全局对象 。在浏览器的情况下,全局对象是 windows 对象。但在 NodeJS 环境中,this 值是一个特殊的 global 对象。
简单函数
// 案例 1,简单函数,浏览器下的 this -> window,NodeJS 下的 this -> global
function simple1() {
console.log("案例 1,简单函数");
console.log("我是简单函数,this 指向 window");
console.log(this);
}
simple1();
严格模式
// 案例 2,严格模式,this -> undefined
function simple2() {
'use strict';
console.log("案例 2,严格模式");
console.log("我是严格模式,this 指向 undefined");
console.log(this);
}
simple2();
#构造函数
当我们调用 new User,JavaScript 会在 User 函数内创建一个新对象并把它保存为 this 。接着,name, age 和 info 属性会被添加到新创建的 this 对象上。
// 案例 3,构造函数,此时在执行上下文中创建了 this 对象,并在这个 this 对象中增加了 name, age, info 三个属性
function User(name, age) {
this.name = name;
this.age = age;
this.info = function () {
console.log("我是 User 对象中的 info 属性")
console.log(`${this.name} ${this.age}`);
};
console.log("案例 3,构造函数");
console.log("我是 User 对象,我在执行上下文中创建了 this 对象,并增加了 name, age, info 三个属性");
console.log(this);
}
let andy = new User('Andy', 22);
andy.info();
简单对象 1
当某个属性被发起普通函数调用时,则 this 指向 window 对象
// 案例 4,简单对象
let user = {
name: '小明',
age: userAgeFunction,
sex: function () {
console.log("我是 user 对象的 sex 属性,this 指向 user 对象,而不是全局对象");
console.log(this);
},
talk: function () {
console.log(this);
}
};
function userAgeFunction() {
console.log("我是 user 对象的 age 属性,this 指向 user 对象,而不是全局对象");
console.log(this);
}
console.log("案例 4,简单对象");
user.age();
user.sex();
let talk = user.talk;
console.log("我是 talk,我把 user 对象的 talk 属性当普通函数调用了,所以这里的 this 指向 window");
talk();
简单对象 2
age 函数内部, this 指向 lee 对象,但是,在 innerAge 函数内部,this 指向全局对象,规则告诉我们无论何时一个普通函数被调用时,那么 this 将指向全局对象。
// 案例 5,简单对象 2
let lee = {
name: 'lee',
birth: 1998,
age: function () {
console.log("我是 lee 对象的 age 属性,this 指向 lee 对象,而不是全局对象");
console.log(this);
function innerAge() {
console.log("我虽然是 lee 对象中的 age 属性中的 innerAge() 函数,但我会被普通调用,所以这里的 this 指向 window,而不是 lee 对象");
console.log(this);
}
// 这里发起 lee 对象 age 属性内部的 innerAge() 普通调用,所以该函数中的 this 指向 window
innerAge();
}
};
console.log("案例 5,简单对象");
lee.age();
call、apply、bind
- call:将 this 指向目标对象
- apply:将 this 指向目标对象,在参数形式为数组时使用该方法
- bind:将 this 指向传递的第一个参数并返回一个新方法
function User(username, password) {
this.username = username;
this.password = password;
this.displayUser = function() {
console.log(`User: ${this.username} ${this.password}`);
}
}
let user1 = new User("admin", "123456");
let user2 = new User("guest", "abcdef");
console.log("案例 6,call apply bind");
console.log("我是 user1 对象");
user1.displayUser();
console.log("我是 user2 对象")
user2.displayUser();
console.log("我是 user1 对象,我使用了 call 方法将我的 this 指向了 user2")
user1.displayUser.call(user2);
console.log("我是 user1 对象,我使用了 apply 方法将我的 this 指向了 user2")
user1.displayUser.apply(user2);
console.log("我是 user1 对象,我使用了 bind 方法将我的 this 指向了 user2 并返回了一个新的方法")
let user2Display = user1.displayUser.bind(user2)
user2Display()
- token和session
token和session
什么是token?
token是服务端生成的一串字符串,目的是作为客户端进行请求的一个令牌。当第一次登录后,服务器生成一个token(一串字符串),并将此token返回给客户端,此后页面接收到请求后,只需要找到token即可获取信息,无需再输入登录名和密码。
token一般用于验证表明身份的数据或是别的口令数据;token可以用url传参,也可以是post提交,也可以夹在http的header中。
什么是session?
session从字面上讲就是会话。
为了让服务器知道当前请求是从哪里发过来的,所以服务器给每个客户端分配了不同的“身份标识”(类似id),之后客户端每次发送请求都携带上这个标识(id),这样做,服务端就可以知道是谁发送的请求。
session和token的区别:
服务器在使用session把用户信息临时保存在服务器上,用户离开网站后session就会被销毁。
但session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。
而token最大特点就是支持跨平台操作,不论是在App还是在PC端,token都可以保留。
8.微服务
1.API管理
原理
在SpringMVC中RequestMappingHandlerMapping是比较重要的一个角色,它决定了每个URL分发至哪个Controller。
Spring Boot加载过程如下,所以我们可以通过自定义WebMvcRegistrationsAdapter来改写RequestMappingHandlerMapping。
- 服务熔断
Hystrix的熔断
Netflix’ Hystrix是第一个专门用于熔断的服务中间件。当它在2012年向公众发布,以提供“对延迟和失败有更大容忍度”的微服务架构时,Netflix已经在内部广泛使用了一年多的时间了。根据这个项目的描述,Hystrix一直是Netflix服务中间件的基本组成部分之一,直到2018年底进入维护模式,这标志着“[关注点]转向更适应应用程序实时性能的实现,而不是预先配置的设置。”
Hystrix是一个Java库,开发人员可以使用它用熔断逻辑封装服务调用。它基于阈值,可以立即判定调用失败并执行回滚逻辑,具体参考第一部分。除了提供超时和并发限制之外,它还可以向监视工具发布度量metrics。最后,当与Archaius库一起使用时,它还可以支持动态配置更改。
服务网格中的熔断
Istio
Istio是一个服务网格,它支持基于连接池、每个连接的请求和故障检测参数的熔断。它是在所谓的“目的地规则(destination rules)”的帮助下做到这一点的,该规则告诉每个Envoy代理应用于通信的策略是什么,以及如何应用。这个步骤发生在路由之后,然而这并不总是理想的。目标规则可以指定负载均衡的限制、连接池大小以及最终符合“异常值”条件的参数,以便可以从负载均衡池中删除不健康的实例。这种类型的熔断擅长于使客户端免受服务端故障的影响,但是由于目标规则总是在集群范围内应用,所以它缺乏一种方法来将断路器限制在客户端的一个子集内。为了实现断路器与服务质量模式(quality-of-service)的组合,必须创建多个客户机子集的路由规则,并且每个子集都有自己的目标规则。
3.微服服务跟踪
服务追踪系统实现
上面是服务追踪系统架构图,你可以看到一个服务追踪系统可以分为三层。
数据采集层,负责数据埋点并上报。
数据处理层,负责数据的存储与计算。
数据展示层,负责数据的图形化展示
服务追踪的作用
第一,优化系统瓶颈。
通过记录调用经过的每一条链路上的耗时,我们能快速定位整个系统的瓶颈点在哪里。比如你访问微博首页发现很慢,肯定是由于某种原因造成的,有可能是运营商网络延迟,有可能是网关系统异常,有可能是某个服务异常,还有可能是缓存或者数据库异常。通过服务追踪,可以从全局视角上去观察,找出整个系统的瓶颈点所在,然后做出针对性的优化。
第二,优化链路调用。
通过服务追踪可以分析调用所经过的路径,然后评估是否合理。比如一个服务调用下游依赖了多个服务,通过调用链分析,可以评估是否每个依赖都是必要的,是否可以通过业务优化来减少服务依赖。
此外,一般业务都会在多个数据中心都部署服务,以实现异地容灾,这个时候经常会出现一种状况就是服务 A 调用了另外一个数据中心的服务 B,而没有调用同处于一个数据中心的服务 B。跨数据中心的调用视距离远近都会有一定的网络延迟,像北京和广州这种几千公里距离的网络延迟可能达到 30ms 以上,这对于有些业务几乎是不可接受的。通过对调用链路进行分析,可以找出跨数据中心的服务调用,从而进行优化,尽量规避这种情况出现。
第三,生成网络拓扑。
通过服务追踪系统中记录的链路信息,可以生成一张系统的网络调用拓扑图,它可以反映系统都依赖了哪些服务,以及服务之间的调用关系是什么样的,可以一目了然。除此之外,在网络拓扑图上还可以把服务调用的详细信息也标出来,也能起到服务监控的作用。
第四,透明传输数据。
除了服务追踪,业务上经常有一种需求,期望能把一些用户数据,从调用的开始一直往下传递,以便系统中的各个服务都能获取到这个信息。比如业务想做一些 A/B 测试,这时候就想通过服务追踪系统,把 A/B 测试的开关逻辑一直往下传递,经过的每一层服务都能获取到这个开关值,就能够统一进行 A/B 测试。
服务追踪系统原理
它的核心理念就是调用链:通过一个全局唯一的 ID 将分布在各个服务节点上的同一次请求串联起来,从而还原原有的调用关系,可以追踪系统问题、分析调用数据并统计各种系统指标。
可以说后面的诞生各种服务追踪系统都是基于 Dapper 衍生出来的,比较有名的有 Twitter 的Zipkin、阿里的鹰眼、美团的MTrace等。(服务追踪系统的鼻祖:Google 发布的一篇的论文Dapper, a Large-Scale Distributed Systems Tracing Infrastructure,里面详细讲解了服务追踪系统的实现原理。)
要理解服务追踪的原理,首先必须搞懂一些基本概念:traceId、spanId、annonation 等。Dapper 这篇论文讲得比较清楚,但对初学者来说理解起来可能有点困难,美团的 MTrace 的原理介绍理解起来相对容易一些,下面我就以 MTrace 为例,给你详细讲述服务追踪系统的实现原理。虽然原理有些晦涩,但却是你必须掌握的,只有理解了服务追踪的基本概念,才能更好地将其实现出来。
4.配置中心地方
配置实时生效:
传统的静态配置方式要想修改某个配置只能修改之后重新发布应用,要实现动态性,可以选择使用数据库,通过定时轮询访问数据库来感知配置的变化。轮询频率低感知配置变化的延时就长,轮询频率高,感知配置变化的延时就短,但比较损耗性能,需要在实时性和性能之间做折中。配置中心专门针对这个业务场景,兼顾实时性和一致性来管理动态配置。
配置管理流程:
配置的权限管控、灰度发布、版本管理、格式检验和安全配置等一系列的配置管理相关的特性也是配置中心不可获取的一部分。
开源配置中心基本介绍
目前市面上用的比较多的配置中心有:(按开源时间排序)
Disconf
2014年7月百度开源的配置管理中心,同样具备配置的管理能力,不过目前已经不维护了,最近的一次提交是两年前了。
Spring Cloud Config
2014年9月开源,Spring Cloud 生态组件,可以和Spring Cloud体系无缝整合。
Apollo
2016年5月,携程开源的配置管理中心,具备规范的权限、流程治理等特性。
Nacos
2018年6月,阿里开源的配置中心,也可以做DNS和RPC的服务发现。
配置中心核心概念的对比
由于Disconf不再维护,下面对比一下Spring Cloud Config、Apollo和Nacos。
Spring Cloud Config、Apollo和Nacos在配置管理领域的概念基本相同,但是也存在一些不同的点,使用配置的过程中会涉及到一些比较重要的概念。
应用
应用是客户端系统的基本单位,Spring Cloud Config 将应用名称和对应Git中的文件名称关联起来了,这样可以起到多个应用配置相互隔离的作用。Apollo的配置都是在某个应用下面的(除了公共配置),也起到了多个应用配置相互隔离的作用。Nacos的应用概念比较弱,只有一个用于区分配置的额外属性,不过可以使用 Group 来做应用字段,可以起到隔离作用。
集群
不同的环境可以搭建不同的集群,这样可以起到物理隔离的作用,Spring Cloud Config、Apollo、Nacos都支持多个集群。
Label Profile & 环境 & 命名空间
Spring Cloud Config可以使用Label和Profile来做逻辑隔离,Label指远程仓库的分支,Profile类似Maven Profile可以区分环境,比如{application}-{profile}.properties。
Nacos的命名空间和Apollo的环境一样,是一个逻辑概念,可以作为环境逻辑隔离。Apollo中的命名空间指配置的名称,具体的配置项指配置文件中的一个Property。
配置管理功能的对比
作为配置中心,配置的整个管理流程应该具备流程化能力。
灰度发布
配置的灰度发布是配置中心比较重要的功能,当配置的变更影响比较大的时候,需要先在部分应用实例中验证配置的变更是否符合预期,然后再推送到所有应用实例。
Spring Cloud Config支持通过/bus/refresh端点的destination参数来指定要更新配置的机器,不过整个流程不够自动化和体系化。
Apollo可以直接在控制台上点灰度发布指定发布机器的IP,接着再全量发布,做得比较体系化。
Nacos目前发布到0.9版本,还不支持灰度发布。
权限管理
配置的变更和代码变更都是对应用运行逻辑的改变,重要的配置变更常常会带来核弹的效果,对于配置变更的权限管控和审计能力同样是配置中心重要的功能。
Spring Cloud Config依赖Git的权限管理能力,开源的GitHub权限控制可以分为Admin、Write和Read权限,权限管理比较完善。
Apollo通过项目的维度来对配置进行权限管理,一个项目的owner可以授权给其他用户配置的修改发布权限。
Nacos目前看还不具备权限管理能力。
版本管理&回滚
当配置变更不符合预期的时候,需要根据配置的发布版本进行回滚。Spring Cloud Config、Apollo和Nacos都具备配置的版本管理和回滚能力,可以在控制台上查看配置的变更情况或进行回滚操作。Spring Cloud Config通过Git来做版本管理,更方便些。
配置格式校验
应用的配置数据存储在配置中心一般都会以一种配置格式存储,比如Properties、Json、Yaml等,如果配置格式错误,会导致客户端解析配置失败引起生产故障,配置中心对配置的格式校验能够有效防止人为错误操作的发生,是配置中心核心功能中的刚需。
Spring Cloud Config使用Git,目前还不支持格式检验,格式的正确性依赖研发人员自己。
Apollo和Nacos都会对配置格式的正确性进行检验,可以有效防止人为错误。
监听查询
当排查问题或者进行统计的时候,需要知道一个配置被哪些应用实例使用到,以及一个实例使用到了哪些配置。
Spring Cloud Config使用Spring Cloud Bus推送配置变更,Spring Cloud Bus兼容 RabbitMQ、Kafka等,支持查询订阅Topic和Consumer的订阅关系。
Apollo可以通过灰度实例列表查看监听配置的实例列表,但实例监听的配置(Apollo称为命名空间)目前还没有展示出来。
Nacos可以查看监听配置的实例,也可以查看实例监听的配置情况。
基本上,这三个产品都具备监听查询能力,在我们自己的使用过程中,Nacos使用起来相对简单,易用性相对更好些。
多环境
在实际生产中,配置中心常常需要涉及多环境或者多集群,业务在开发的时候可以将开发环境和生产环境分开,或者根据不同的业务线存在多个生产环境。如果各个环境之间的相互影响比较小(开发环境影响到生产环境稳定性),配置中心可以通过逻辑隔离的方式支持多环境。
Spring Cloud Config支持Profile的方式隔离多个环境,通过在Git上配置多个Profile</
本文标签: 面试题
版权声明:本文标题:模拟面试面试题汇总 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1725921975a1030808.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论