.net+.net core常见面试题总结
1、10万+大数据处理方式、应用场景。
缓存、索引、避免全局搜索、表分区
2、redis在项目中如何使用、支持的数据类型?
字符串(String)、列表(List)、集合(set)、哈希结构(hash)、有序集合(zset)和基数(HyperLogLog)
3、消息队列使用的四种场景介绍。
异步处理
场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种 1.串行的方式;2.并行方式
应用解耦
场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口
流量削锋
流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛
秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。
日志处理
日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题。架构简化如下
4、redis缓存穿透、缓存击穿、缓存雪崩原因+解决方案。
5、单列模式使用场景。
需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)
6、什么是死锁?死锁产生的原因?如何避免死锁?
指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象;
四个必要条件
1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
7、ElasticSearch使用场景。
8、TiDB使用场景。
9、Redis的优点:
支持多种数据结构,如 string(字符串)、 list(双向链表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基数估算)
每个类型使用的场景
10、各个索引应用场景
MySQL索引原理 - 二十三岁的有德 - 博客园
11、B+树为什么快
12、二叉树查找法。
13、消息队列Kafka、RocketMQ、RabbitMQ的优劣势比较和使用场景
消息队列Kafka、RocketMQ、RabbitMQ的优劣势比较 - 知乎
14、redis集群的方式
redis有三种集群方式:主从复制,哨兵模式和集群。
1.主从复制
主从复制原理:
从服务器连接主服务器,发送SYNC命令;
主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;(从服务器初始化完成)
主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令(从服务器初始化完成后的操作)
主从复制优缺点:
优点:
支持主从复制,主机会自动将数据同步到从机,可以进行读写分离
为了分载Master的读操作压力,Slave服务器可以为客户端提供只读操作的服务,写服务仍然必须由Master来完成
Slave同样可以接受其它Slaves的连接和同步请求,这样可以有效的分载Master的同步压力。
Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。
Slave Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据
缺点:
Redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
2.哨兵模式
当主服务器中断服务后,可以将一个从服务器升级为主服务器,以便继续提供服务,但是这个过程需要人工手动来操作。 为此,Redis 2.8中提供了哨兵工具来实现自动化的系统监控和故障恢复功能。
哨兵的作用就是监控Redis系统的运行状况。它的功能包括以下两个。
(1)监控主服务器和从服务器是否正常运行。
(2)主服务器出现故障时自动将从服务器转换为主服务器。
哨兵的工作方式:
每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)
如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态
当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)
在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。
当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。
哨兵模式的优缺点
优点:
哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
主从可以自动切换,系统更健壮,可用性更高。
缺点:
Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
3.Redis-Cluster集群
redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容。
Redis-Cluster采用无中心结构,它的特点如下:
所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
节点的fail是通过集群中超过半数的节点检测失效时才生效。
客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
工作方式:
在redis的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383。还有一个就是cluster,可以理解为是一个集群管理的插件。当我们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
为了保证高可用,redis-cluster集群引入了主从模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点A1都宕机了,那么该集群就无法再提供服务了。
15、如何在ASP.NET Core中激活Session功能?
首先要添加session包. 其次要在configservice方法里面添加session。然后又在configure方法里面调usesession。。
16、ASP.NET Core Filter如何支持依赖注入?依赖注入的类?
可以通过全局注册,支持依赖注入
通过TypeFilter(typeof(Filter)) 标记在方法,标记在控制器
通过ServiceType(typeof(Filter))标记在方法,标记在控制器,必须要注册Filter这类;
TypeFilter和ServiceType的本质是实现了一个IFilterFactory接口
17、ASP.NET Core 如何和读取配置文件中的内容?
可以有两种方式,可以通过IConfiguration接口来读取;
有可以定义根据配置文件结构一致的实体对象,来绑定到对象中去;或者通过1写入,2注入读取
必须保证:DBConnectionOption和配置文件的内容结构一致;
1. services.Configure<DBConnectionOption>
(Configuration.GetSection("ConnectionStrings"));//注入多个链接
2.private DBConnectionOption dBConnections = null;
private DbContext _Context = null;
public DbContextFactory(DbContext context, IOptions<DBConnectionOption>
options)
{
_Context = context;
dBConnections = options.Value;
}
18、ASP.NET Core有哪些好的功能?
第一是依赖注入。
第二是日志系统架构。
第三是引入了一个跨平台的网络服务器,kestrel。可以没有iis, apache和nginx就可以单独运行。
第四是可以使用命令行创建应用。
第五是使用appsettings来配置工程。
第六是使用startup来注册服务。
第七是更好的支持异步编程。
第八是支持web socket和signal IR。
第九是对于跨网站的请求的预防和保护机制
19、描述一下.Net Core依赖注入后的服务生命周期?
在ASP.NET Core中,我们不需要关心如何释放这些服务, 因为系统会帮我们释放掉。有三种服务的生命周期。
单实例服务, 通过add singleton方法来添加。在注册时即创建服务, 在随后的请求中都使用这一个服务。
短暂服务, 通过add transient方法来添加。是一种轻量级的服务,用于无状态服务的操作。
作用域服务,一个新的请求会创建一个服务实例。使用add scoped方法来添加。
20、说说RESTful是什么
REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”。
在传统的服务中,比方说WebService,WCF,Remouting,都是通过调用方法来做到一个进程去调用另外一个进程的服务,在Core WebApi中是把要调用的服务资源化,比方说有图书资源,Books,学生资源Studentlist,每一个资源对应一个控制器,然后对外提供增删改查等操作;对外提供统一的Uri, 可以对资源Books,资源Studentlist做增删改查的操作;访问的是资源,可以根据不同的额访问方式,做不同的事儿;
method请求方式
GET :从服务器取出资源(一项或多项)
POST :在服务器新建一个资源
PUT :在服务器更新资源(客户端提供改变后的完整资源)
PATCH :在服务器更新资源(客户端提供改变的属性)
DELETE :从服务器删除资源
21、.net core如何解决跨域问题?
三种方式:
1.后台模拟Http请求,既然是浏览器的行为,就避开浏览器,先来一个同源的服务器去请求,然后由服务器模拟http请求去请求到Core WebApi的资源,然后响应给前端;
2.JSONP,思路:通过html部分标签发起请求,比方说 等等,发起请求是可以避开同源策略的,使用这些标签发起请求,然后带有一个回调函数,然后得到请求后,把回调函数执行一次,把数据解析后使用;
3.服务端允许跨域CORS,多种方式,可以自己定义中间件支持跨域,只要把响应的Response的头信息Header中写入“Access-Control-Allow-Origin” 即可支持跨域;如果需要让所有的Api都支持跨域,就可以写一个中间件从管道处理模型中去支持跨域,如果要选择性的支持跨域,可以使用ActionFilter来完成,也可以通过Cors(ASP.NET Core中提供的中间件,可以支持配置不同的跨域规则)来配置支持跨域;
22、说说你了解到的鉴权授权技术
1.传统的授权技术:通过Session、Cookie完成授权;实现特点: 让无状态的http请求,变的有状态,让第一次请求和第二次请求之间产生联系,第一次请求进入服务器,在服务器写入一组session,然后返回sessionId给客户端存在Cookie,第二次请求,从cookie中渠道SessionId,传递给服务器,服务器鉴别SessionId,如果是上一次来的SessionId,就认为之前来请求过;就认为有权限;
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
"WebApplication1 v1"));
}
2.流行鉴权授权方式:Token授权,在Core WebApi中主要就是JWT和IdentityServer4;都是独立的授权中心,授权后办法token,然后客户端带着token去请求Api,Api方验证Token,验证通过就有权限,验证不通过就没有权限;
23、gRPC有几种模式?
四种模式:
1,简单模式:简单模式只是使用参数和返回值作为服务器与客户端传递数据的方式,最简单。
2,客户端流模式:即从客户端往服务器端发送数据使用的是流,即服务器端的参数为流类型,然而在服务器相应后返还数据给客户端,使用的也是流的send方法。一般在服务器端的代码,需要先recv再send,而客户端与此相反。但是在后面的双向模式中可以使用go的协程协作。
3,服务器端流模式:即服务器端返回结果的时候使用的是流模式,即传入的数据是通过参数形式传入的。但是在往客户端发送数据时使用send方法,与客户端返回数据的方式大同小异。
4,双向模式:客户端如果不适用协程,那么发送必须在接收之前。如果使用协程,发送与接收并没有先后顺序。为了保证协程的同步,可以使用互斥量进行约束。
24、什么AOP、POP、DDD?
(1)AOP:面向切面编程,在执行一个oop(应对复杂的设计)方法之前或之后,动态的新增功能,不影响oop原先的方法
#OOP造房子: 类>类库>架构>系统 房子》一层楼》梁柱》大厦 大厦的稳定需要房子不能随便去拆,但是现实中的需求是不断变更的,这就矛盾了
#AOP就是来解决上面不稳定的问题,AOP可以动态的改变OO的模型,相当于你要在装修房子的时候,动态的提前给你装修前做好工作,让你不再装修房子,保持稳定
(2)POP:面向过程编码,一路执行下去,不好扩展。
(3)DDD领域驱动设计-为了应对更加复杂开发而设计
以前开发模式;需求-数据怎么入库-逻辑开发-ui界面-完成(这个流程中间很容易因为需求变动导致后面从数据入库开始就大变)
领域模式:只分析业务(前期只了解业务需求,不考虑任何开发技术)-再考虑实现-避免改动,这样下来,做的东西完成以业务为主 业务给什么样,最后做出的就是什么样子
DDD和原本的三层架构区别
三层架构模式:ui:负责界面展示 >bll:业务逻辑>DLL,基础数据层
DDD设计模式:User Interface-用户层: 用户>应用(复杂逻辑,) 用户>领域 (简单业务逻辑) 用户>基础通常层(发邮件)
Applition-应用层:应用>领域(当业务复杂,ui需要调用多个Domain用这个来解耦)协调组装让用户调用领域
Domain-领域层:核心业务逻辑,其实就是业务
Infrastructure基础通用层:日志,邮件共用的
25、.net core中间件和管道
(1)中间件 是处理请求和响应的组件(代码段,一段处理逻辑),这个处理逻辑是以“前一个请求处理逻辑”为输入,并经过中间件自己的处理后,返回一个“新的请求处理逻辑”,所以从代码上可将“中间件”表式为以一个“请求处理逻辑”为输入并返回另一个“请求处理逻辑”的委托,即Func<RequestDelegate,RequestDelegate> ;每一个中间件都可以决定是否继续进入下一个管道、并且可以在进入下一个管道前后执行逻辑;他们彼此链接,形成管道;
中间件的实现原理是通过委托
使用中间件有四种方法:Use、Run、Map和使用Middleware class,但前三种方法最终调用的都是Use方法
(2)管道就是请求抵达服务器到响应结果返回的中间的一系列的处理过程
26、常用的设计模式
单例模式:
单利模式和全局静态变量/类的区别:
单例模式:保证某类只存在唯一的实例,类本身完成自身的初始化,通过本身定义的静态方法getIntance()获取唯一实例
静态变量类:可以在任何类中定义该类的实例引用的静态变量,任何位置都可以对该静态变量重新赋值
工厂模式:
作用:实现了创建者和调用者的分离(工厂模式为了让消费者和生产者分开)
核心本质:
实例化对象不使用new,用工厂方法代替
将选择实现类,创建对象统一管理和控制,从而将调用者跟我们的实现类解耦
抽象工厂模式:
抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类
建造者模式:
建造者模式也属于创建型模式,它提供了一种创建对象的最佳方式
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象
原型模式:
原型的意思就是按照对象A,复制/拷贝一份,形成一个单独独立的新的对象B,我们对对象B进行操作,而原来被复制/拷贝的对象A就称为对象B的原型
原型模式的使用场景就是当一个对象的创建比较复杂的时候,我们耗费了一些资源好不容易创建出了一个对象A,如果此时我们需要再创建一个对象B,那么我们不需要再去经过前面繁琐的步骤创建对象B,而是直接复制粘贴对象A,得到一个完整对立的对象B
27、谈谈对通信加密解密的理解
加密解密分为:对称可逆加密,非对称可逆加密两大类;
可逆加密:加密后得到密文,可以通过加密后的密文得到原文;
对称可逆加密特点:有一个公开的加密算法,任何人都知道;有一组Key,分为加密Key和解密Key,且两个Key是相同的;使用当前这个Key加密,可以得到一段密文;同时如果这段密文想要得到原文,也必须得使用这个Key才能解密; 此类被称为对称可逆加密,性能很高,但是安全性较差;只要是key被泄密了,密文就可以被攻破得到原文;因为加密算法是公开的;
非对称可逆加密特点::有一个公开的加密算法,任何人都知道;同时有一对Key,这一组Key是成套的,两个Key不相同,二者且不能相互推导;一个Key作为加密Key,一个Key作为解密Key,且加密Key加密后,只能由这个解密Key才能解开;此类被称为非对称可逆加密;在非对称可逆加密的应用中,有一个公钥和私钥的概念;公钥:把其中的一个Key公开,私钥:把其中的一个Key私有化;那这样就有一下场景:
1.公开加密Key,私有解密Key:那么任何一个拥有公开加密Key的人给我这个拥有私有解密Key的人发密文,我都能解开,且只有我能解开;这样就可以保证在通信传输的时候,保证信息的安全;在传输的时候不会被泄密,因为就算在传输的过程中,密文被拦截了,也无法得到原文;因为没有这个解密Key,有密文是无法得到原文的;
2.公开解密Key,私有化加密Key: 那么任何一个拥有解密Key的人都能够接收到来自于我这个拥有加密Key的人发送的消息,只要是我这个私有的加密Key加密后的密文,任何一个拥有解密Key的人都能够解开密文得到原文;那这样就可以实现一个功能:防止抵赖,也就是说,如果我是有解密Key的人,我得到的密文只要能够解开,那就说明这段密文一定是拥有加密Key的人发出来的;不然我是解不开这段密文的;