.net面试题-15k左右
作者:互联网
综合
- 以前的项目中,主要解决了什么技术性 难题 ,如果出现问题,你如何迅速找到问题,你遇到问题都是怎么解决的
根据出现的问题,大概排查出问出问题的几个点,逐个排查, 错误日志- sql查询计划-定位程序错误 reshare
解决秒杀: 集群,redis缓存,rabbitmq队列,关闭评价服务等权重低的服务。
2. 关于代码优化你怎么理解?你会考虑去代码重构吗?
1、对于代码优化,之前的公司每周会做代码审核,审核的主要作用就是保证代码的正确性和执行效率,
2、 对于陈旧代码,可能很多地方有调用,并且开发和维护人员很有可能不是同一个人,所以重构时要格外小心,
如果没有十足的把握,不要轻易重构。如果必须要重构,必须做好充分的单元测试和全局测试。
3.架构设计需要满足4点要求:
1. 能进行分布式存储
2. 能实现负载均衡
3. 能根据用户访问量和图片数量增加而动态增加服务器节点
4. 服务器节点的增加对用户透明,不会中断系统的运行
4. CAP原理:
Base理论:分区容错前提下,优先保证可用性,然后最终结果一致就行
5. SignalR,是否写过聊天室?
定义:是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能(聊天室,股票交易,微信角标,站内消息):当所连接的客户端变得可用时服务器代码可以立即向其推送内容,
而不是让服务器等待客户端请求新的数据。使用websocket通信,底层是socket (本质是编程接口(API),对TCP/IP的封装,提供了网络通信的能力).
当环境条件合适时,SignalR将WebSocket作为底层传输方式的优先实现,当然,它也能很高效地回退到其他技术(长轮询, ServerSendEvent)。同时,SignalR提供了非常良好的Api以供远程调用(RPC) 浏览器中的js代码。
SignalR有两种连接,分为Persistent Connection(永久连接) 与 Hubs
Persistent Connection:表示一个发送单个,编组,广播信息的简单终结点。开发人员通过使用持久性连接Api,直接访问SignalR公开的底层通信协议。
Hubs:是基于连接Api的更高级别的通信管道,它允许客户端和服务器上彼此直接调用方法,SignalR能够很神奇地处理跨机器的调度,使得客户端和服务器端能够轻松调用在对方端上的方法。使用Hub还允许开发人员将强类型的参数传递给方法并且绑定模型
4种方式:
- 轮询(polling以前的方式)客户端以一定时间间隔中向服务器发送Ajax查询请求大,但是也因此,当服务器端内容并没有显著变化时,这种连接方式将带来很多无效的请求,造成服务器资源损耗。适合并发量小,实时性要求低的应用模型,更像是定时任务。优点:实现最为简单,配置简单,出错几率小. 缺点:每次都是一次完整的http请求,易延迟,有效请求命中率少,并发较大时,服务器资源损耗大
- long polling长轮询, 长轮询是对轮询的改进,客户端通过请求连接到服务器,并保持一段时间的连接状态,直到消息更新或超时才返回Response并中止连接,可以有效减少无效请求的次数。属于Comet实现. 优点:有效减少无效连接,实时性较高.缺点:客户端和服务器端保持连接造成资源浪费,服务器端信息更新频繁时,long polling并不比polling高效,并且当数据量很大时,会造成连续的polls不断产生,性能上反而更糟糕
- WebSocket 是HTML5提供的一种在单个 TCP 连接上进行全双工通讯的协议,目前chrome、Firefox、Opera、Safari等主流版本均支持,Internet Explorer从10开始支持。另外因为WebSocket 提供浏览器一个原生的 socket实现,所以直接解決了 Comet 架构很容易出错的问题,而在整個架构的复杂度上也比传统的实现简单得多。优点:服务器与客户端之间交换的数据包档头很小,节约带宽。全双工通信,服务器可以主动传送数据给客户端。缺点:旧版浏览器不支持。
使用条件:
1.正在使用跨域连接,并且符合以下条件(以下不满足任一条则使用长轮询)
(1).客户端支持CORS
(2).客户端支持WebSocket
(3).服务器端支持WebSocket
2.不配置使用JSONP,连接不跨域并且客户端和服务器端都支持WebSocket
(1).客户端支持CORS
(2).客户端支持WebSocket
(3).服务器端支持WebSocket
- ServerSendEvent 客户端或服务器端不支持Websocket时使用
- Forever Frame EventSource不可用(基本上除了IE外都支持)时使用
6. .netframework的运行机制: 编译器会将源代码编译成Microsoft中间语言(MSIL)有时也称为中间语言(IL)。当程序运行时,实时(JIT)编译器将MSIL转换为特定机器的本机代码,实时编译器是公共语言运行库的一部分。
7. 项目管理要素:
工作范围、时间、质量、成本:
68.1范围(Scope )。也称为工作范围,指为了实现项目目标必须完成的所有工作。(完成哪些工作就可以达到项目的目标”,或者说 “完成哪些工作项目就可以结束了)
68.2. 时间(Time )。项目时间相关的因素用进度计划描述,进度计划不仅说明了完成项目工作范围内所有工作需要的时间,也规定了每个活动的具体开始和完成日期。
68.3 成本(Cost )。指完成项目需要的所有款项,包括人力成本、原材料、设备租金、分包费用和咨询费用等。项目的总成本以预算为基础,项目结束时的最终成本应控制在预算内。
68.4 质量(Quality )。是指项目满足明确或隐含需求的程度。
8. 解决高并发
1. 缓存
2. HTML静态化
3. 数据库读写分离mssql订阅发布
4、分布式集群
5、镜像
6、负载均衡
7. 分库分表
8. 业务拆分,做微服务
9. 使用队列
9. 微服务
微服务架构是一个用分布式服务拆分业务逻辑,完成解耦的架构模式。(就是把以前的Bll改成服务,跨进程调用服务来完成功能)
微服务------进程之间通信:
共享存储: Redis,DB,Queue,硬盘文件等等,被动式通信,门槛低。
服务通信: WebSoeket, WebService,WCF,WebApi,ashx,aspx等等,主动触发,数据序列化传递,跨平台,跨语言,http穿透防火墙.
RPC: .net Remoting(.net独有,不支持跨平台);gRPC(高性能,开源,通用的RPC框架,面向服务端和移动端,基于http/2设计)
微服务------服务实例集群
Consul:服务注册与发现,健康检查
微服务------网关:Gateway:提供统一服务入口,对前台透明.聚合后台服务,节省流量,提高性能。提供安全,过滤,流量控制等管理功能,就是一个configuration.json
缓存
熔断:单位时间内异常多少次,就指定时间内,网关直接返回失败。
限流:单位时间内,流量只允许多少次。(张善友写的)
降级:特殊情况下可以降低服务器等级,甚至关闭。
微服务------鉴权&授权:JWT
微服务------瞬态故障处理:
Polly是一种.net弹性和瞬态处理库,允许我们以非常顺畅和线程安全的方式来执行诸如 重试,断路,超时,故障恢复等策略。
微服务------分布式追踪(常用软件Skyworking):
分布式追踪和APM的Server端,它将包含Collector,Stroage,独立的WebUI,并使用OpenTracing规范来设计追踪数据。
微服务------ExceptionLess:
ExceptionLess:开源的日志收集和分析框架,能为应用程序提供实时错误,特性和日志报告。
微服务------统一配置中心:
Apollo:配置管理平台,能够集中化管理应用不同环境,不同集群的配置,配置修改后能实时推送到应用端,并且具备规范的权限、流程治理等特性。
微服务------分布式事务:
CAP理论
微服务------容器化docker:
Docker:是一个开源的应用程序引擎,可以打包应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的linux或者windows机器上,也可以实现虚拟化
微服务------容器编排K8S(管理docker):
Kubernetes编排容器,是管理应用的全生命周期的工具,从创建应用/部署,应用提供服务,扩容缩容,更新,都非常方便,而且可以做到故障自愈。
微服务------CI/CD:
Jenkins是一个开源的,提供友好操作界面的持续集成(CI)工具,主要用于持续、自动的构建/测试软件项目、监控外部任务的运行。
10. redis:(Remote Dictionary Server )
即远程字典服务,是一个开源的key-value数据结构存储系统,可以用作数据库,缓存,消息中间件MQ(发布,订阅). 它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)和范围查询geospatial 地理位置,Geopos 获取坐标,Geodist 获取两个城市的距离。数据都是缓存在内存中。redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
Redis单条命令是保存原子性的,但是事务不保证原子性,没有隔离级别的概念。只有发起命令exec时才会被执行,执行完以后销毁该事务。编译时异常,不执行事务,运行时异常(1/0),其他命令可以执行,错误抛出异常.
Reids事务本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事物的执行过程中,会按照顺序执行。 一次性,顺序性,排他性。
Redis默认有16个数据库。
悲观锁:什么操作都加锁,耗性能。
Watch 乐观锁:什么时候都不会上锁,只有更新的时候,获取version,判断下是否有人更改了这个数据。 如果失败了,就使用unwatch取消锁,然后再开启乐观锁
持久化: 只做缓存的话,没必要持久化。
实现:单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。
1. Rdb就是子进程创建快照(默认,修复快,运行快,适合大规模数据修复,对数据完整性要求不高,但是需要一定时间操作,如果redis宕机,那最后一次操作就丢失了,fork进程的时候,会占用一部分的内存空间)。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件,对应产生的数据文件为dump.rdb。
2.AOF:以日志的形式来记录每个写操作,只追加文件,redis启动时会读取该文件重新构建数据,就是把所有写操作都来一遍。每次修改都同步,文件的完整性更好,效率最高,但是修复慢,运行慢。
哨兵模式:是个独立的进程,类似服务注册与发现、心跳检测,是主从复制的升级,自动检测是否可用,不过在线扩容麻烦。可以做哨兵集群。
缓存穿透(缓存查不到,直接查数据库)
布隆过滤器:是一种数据结构,对所有可能查询的参数以hash存储,在控制层校验,不符合则丢弃,避免了对底层存储系统的查询压力
缓存空对象
缓存击穿(大量查询单个热点缓存的时候,缓存过期了)
设置热点数据永不过期,
加互斥锁(分布式锁):每个key同时只能有一个线程去查询后端,其他线程等待,将高并发的压力转移到分布式锁上。
缓存雪崩:某个时间段内,缓存集体失效(redis宕机,秒杀数据缓存集体过期)
集群
限流降级:缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。
缓存预热:正式部署之前,先把可能访问的数据,都访问一遍,手动加载都缓存中,设置不通的过期时间,让缓存的失效时间尽量均匀。
单线程的redis为什么这么快
(一)纯内存操作
(二)单线程操作,避免了频繁的上下文切换
(三)采用了非阻塞I/O多路复用机制
redis采用的是定期删除+惰性删除策略。
redis默认每个100ms随机抽取检查,是否有过期的key,有过期key则删除,如果只采用定期删除策略,会导致很多key到时间没有删除。于是,惰性删除派上用场,。也就是说在你获取某个key的时候,redis会检查一下key过期就删除。如果定期删除没删除key。然后你也没即时去请求key,redis的内存会越来越高,那么就应该采用内存淘汰机制。
在redis.conf中有一行配置maxmemory-policy volatile-lru
该配置就是配内存淘汰策略的
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据,新写入操作会报错ps:如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。
为什么是单线程的
因为Redis是基于内存的操作,CPU不是Redis的瓶颈,并且单线程容易实现,所以是单线程,利用队列技术将并发访问变为串行访问。
Redis 集群方案:只用过redis cluster3.0 自带的集群,特点在于他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自身支持节点设置从节点。
Redis 常见性能问题和解决方案?
Master 最好不要做任何持久化工作,如 RDB 内存快照和 AOF 日志文件(2) 如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次(3) 为了主从复制的速度和连接的稳定性, Master 和 Slave 最好在同一个局域网内(4) 尽量避免在压力很大的主库上增加从库(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即: Master <- Slave1 <- Slave2 <-Slave3…
Redis事务
Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的Redis会将一个事务中的所有命令序列化,然后按顺序执行。
1.redis 不支持回滚,Redis 在事务失败时不进行回滚,而是继续执行余下的命令, 所以 Redis 的内部可以保持简单且快速。
2.如果在一个事务中的命令出现错误,那么所有的命令都不会执行;
3.如果在一个事务中出现运行错误,那么正确的命令会被执行。注:redis的discard只是结束本次事务,正确命令造成的影响仍然存在.
1)MULTI命令用于开启一个事务,它总是返回OK。 MULTI执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。
2)EXEC:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。 当操作被打断时,返回空值 nil 。
3)通过调用DISCARD,客户端可以清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出。
4)WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。 可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。
Redis实现分布式锁
Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系。Redis中可以使用SETNX命令实现分布式锁。将 key 的值设为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。
解锁:使用 del key 命令就能释放锁解决死锁:
1)通过Redis中expire()给锁设定最大持有时间,如果超过,则Redis来帮我们释放锁。
2) 使用 setnx key “当前系统时间+锁持有的时间”和getset key “当前系统时间+锁持有的时间”组合的命令就可以实现。
11. API跨域
1. josnp
2. 后台模拟http请求(httpclient)
3 在服务器端指定允许跨域
3.1 指定一个方法跨域,方法中添加 base.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*");
3.2 指定全部方法跨域(添加方法特性或者控制器特性)
3.3 netcore中间件跨域
12. elasticsearch:是一个开源的高扩展的RESTful 风格的分布式全文检索引擎。它可以近乎实时的存储、检索数据,本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。也可以使用lucene作为你核心来实现所有索引和搜索的工功能,但它的目的是通过简单的RESTfulAPI来隐藏Lucene的复杂性,从而让全文搜索变得简单。使用ES做一个全文索引,我们将经常查询的商品的某些字段,比如说商品名,描述、价格还有id这些字段我们放入我们索引库里,可以提高查询速度。还可以设置搜索的权重,例如搜索电脑,会首先搜索商品名称,然后再搜索分类和描述。
ELK: 是指elasticsearch、Logstash(中央数据流引擎,收集数据后通过过滤输出到不同的目的地[文件、redis\es])、Kibana。
在config中elasticsearch.yml 中,最后添加下面的代码,允许跨域访问。
在bin中双击 elasticsearch.bat启动elasticsearch,浏览器输入 http://localhost:9200/ ,显示下图,表示成功
下载kibana((将es数据友好展示,提供实时分析功能)),在config中的kibana.yml,最后一句添加 i18n.locale: "zh-CN",界面汉化,浏览器输入http://localhost:5601/app/kibana#/home,打开首页.
下载分词器ik,然后在elasticsearch\elasticsearch-7.8.0\plugins 中新建ik文件夹,把代码解压到这里.可以在elasticsearch 的bin的 cmd中,使用elasticsearch-plugin list查看是否安装成功,ik有两个分词算法:ik_smark(最少切分) ik_max_word(最细粒度划分)
倒排索引是什么
传统的我们的检索是通过文章,逐个遍历找到对应关键词的位置。而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表即为倒排索引。有了倒排索引,就能实现 o(1)时间复杂度的效率检索文章了,极大的提高了检索效率。倒排索引,相反于一篇文章包含了哪些词,它从词出发,记载了这个词在哪些文档中出现过,由两部分组成——词典和倒排表。倒排索引的底层实现是基于:FST(Finite State Transducer, 空间占用小, 查询速度快)数据结构。
13. gRpc:
所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型.
gRPC和restful API都提供了一套通信机制,用于server/client模型通信,而且它们都使用http作为底层的传输协议(严格地说, gRPC使用的http2.0,而restful api则不一定)。
- 性能监控 优化系统性能 都会从哪方面操作,用到哪些工具,怎么操作
1.硬件调优:添加内存条,带宽
2.软件调优:
2.1用空间换时间:。各种cache数据缓冲,CDN数据镜象,负载均衡
2.2用时间换空间:(网络传输缩数据的算法),简化代码, 代码调优\算法调优\内存分配\异步操作\网络调优网卡调优\数据库调优 \Web服务器\数据库分离
OneAPM 通过自动探知 Web 端用户、关键应用、数据库请求、外部调用等各层级应用组件,绘制全局拓扑,直观展示组件性能及相互调用时间,其中包括网络耗时。可以实时了解哪些环节成为了系统的性能瓶颈,做出有针对性的优化
百度应用性能监测中心(http://developer.baidu.com/apm/)和齐云测(http://ce.cloud.360.cn/)也可以
- Aop:面向切面编程,能在不破坏封装的前提下,额外扩展功能,代码复用,集中管理,类似Fillter,过滤器,场景:权限,校验,性能监控,数据压缩, 异常处理,日志,缓存,事务等等
.netcore中生命周期 1. AuthorizationFilter 2. ResourceFilter 3. ActionFilter 4.ExcptionFilter 5. ResultFilter
3种注册方式 1. action注册(就是放在action的特性 2. 控制器注册, 该控制所有的操作都从走这个方法 3全局注册,全局生效
- 说一说你最大的优势:
优点是很会处理与人的关系,性格上来说很乐观,对一件事情喜欢从一而终,选择了就要好好做下去.适应力强,能很快融入团队,尽快给公司创造价值.
缺点是遇见难题,不睡觉也要弄出来,要不睡不踏实,分配给别人的任务,老不放心.老想着亲力亲为.
- 作为架构师或者技术经理,怎么进行技术选型?
- 先测试、研究,再决定,选择的软件技术,
- 要能快速地实现应用程序的构建, 技术选型必须贴着业务来选择.
- 对于未经验证的新技术、新理念的引入一定要慎重,一定要在全方位的验证过后,再大规模的的使用。
- 适当的选择熟悉的技术, 选择拥有强大社区支撑的项目
- 整体的技术选型流程:“列出需求”-“细分需求”-“明确搜索方向”-“网络搜索”-“明确评判标准”-“分头执行”-“汇总材料”-“初步选择”-“进一步调研”-“会议评审”-“做出决定”
- 缓存如何设计?千万级并发!如何设计一个多级缓存系统?
多级缓存系统,就是指在一个系统 的不同的架构层级进行数据缓存,以提升访问效率。
整个多级缓存系统被分为三层,应用层nginx缓存,分布式redis缓存集群,tomcat堆内缓存。整个架构流程如下:
- 当接收到一个请求时,首先会分发到nginx集群中,这里可以采用nginx的负载均衡算法分发给某一台机器,使用轮询可以降低负载,或者采用一致性hash算法来提升缓存命中率。
- 当nginx层没有缓存数据时,会继续向下请求,在分布式缓存集群中查找数据,如果缓存命中,直接返回(并且写入nginx应用缓存中),如果未命中,则回源到tomcat集群中查询堆内缓存。
- 在分布式缓存中查询不到数据,将会去tomcat集群中查询堆内缓存,查询成功直接返回(并写入分redis主集群中),查询失败请求数据库;堆内缓存。
- 如果以上缓存中都没有命中,则直接请求数据库,返回结果,同步数据到分布式缓存中。
- 快速有效过滤关键字/敏感词
es创建敏感词库,如果有敏感词就替换
二叉树(这个不会)
- 获取一个数组中最大的数字,使用的方式有哪些?
快速排序:通过多次比较和交换来实现排序, ,说白了就是给基准数据找其正确索引位置的过程.示例如下
static void Main(string[] args)
{
int[] array = { 49, 38, 65, 97, 76, 13, 27 };
sort(array, 0, array.Length - 1);
Console.ReadLine();
}
/**一次排序单元,完成此方法,key左边都比key小,key右边都比key大。
**@param array排序数组
**@param low排序起始位置
**@param high排序结束位置
**@return单元排序后的数组 */
private static int sortUnit(int[] array, int low, int high)
{
int key = array[low];
while (low < high)
{
/*从后向前搜索比key小的值*/
while (array[high] >= key && high > low)
--high;
/*比key小的放左边*/
array[low] = array[high];
/*从前向后搜索比key大的值,比key大的放右边*/
while (array[low] <= key && high > low)
++low;
/*比key大的放右边*/
array[high] = array[low];
}
/*左边都比key小,右边都比key大。//将key放在游标当前位置。//此时low等于high */
array[low] = key;
foreach (int i in array)
{
Console.Write("{0}\t", i);
}
Console.WriteLine();
return high;
}
/**快速排序
*@paramarry
*@return */
public static void sort(int[] array, int low, int high)
{
if (low >= high)
return;
/*完成一次单元排序*/
int index = sortUnit(array, low, high);
/*对左边单元进行排序*/
sort(array, low, index - 1);
/*对右边单元进行排序*/
sort(array, index + 1, high);
}
.net
- 单例:可以保证系统中一个类只有一个实例,并且自行实例化向整个系统提供(例如一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务)
最简单的就是写考虑线程安全的单例模式,网站的计数器,日志, Web应用的配置对象的读取,数据库连接池,多线程的线程池
简单工厂:所有类的new都放到一个工厂类中进行
工厂模式:定义公共接口,每新增一个产品类,就需要添加一个实现该接口的工厂类
抽象工厂:跟工厂模式类似,定义公共接口,只是一个类中有多个产品。
public class Singleton
{
// 定义一个静态变量来保存类的实例
private static Singleton uniqueInstance;
// 定义一个标识确保线程同步
private static readonly object locker = new object();
// 定义私有构造函数,使外界不能创建该类实例
private Singleton() {}
// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
public static Singleton GetInstance()
{
// 双重锁定只需要一句判断就可以了
if (uniqueInstance == null)
{
lock (locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
2.IIS的工作原理?在什么情况下进程会被回收
此题主要考的是.net framework和IIS是如何结合呈现页面的;
1、当客户端发送HTTP Request时,服务端的HTTP.sys(可以理解为IIS的一个监听组件) 拦截到这个请求;
2、HTTP.sys 联系 WAS 向配置存储中心请求配置信息。
3、然后将请求传入IIS的应用程序池。
4、检查请求的后缀,启动aspnet_isapi.dll这个dll,这个dll是.net framework里面的,也就是说到这一步,请求进入了.net framework的管辖范围。
5、这个时候如果是WebForm,开始执行复杂的页面生命周期(HttpRuntime→ProcessRequest→HttpContext→HttpHandler);如果是MVC,则启动mvc的路由机制,根据路由规则为URL来指定HttpHandler
6、httpHandler处理请求后,请求结束,给出Response,客户端处理响应,整个过程结束
3. RabitMQ:场景:应用解耦、异步、流量削锋、数据分发、错峰流控、日志收集等等...
核心思想就是生产者和消费者隔离,生产者从不直接将消息发送给队列。生产者通常不知道是否一个消息会被发送到队列中,只是将消息发送到一个交换机。
先由Exchange来接收,然后Exchange按照特定的策略转发到Queue进行存储。同理,消费者也是如此。Exchange 就类似于一个交换机,转发各个消息分发到相应的队列中
RabbitMQ提供了四种Exchange模式:fanout,direct,topic,header 。 header模式在实际使用中较少。
1.Fanout Exchange(发布订阅): 所有发送到Fanout Exchange的消息都会被转发到与该Exchange 绑定(Binding)的所有Queue上。
Fanout Exchange: 不需要处理RouteKey 。只需要简单的将队列绑定到exchange 上。这样发送到exchange的消息都会被转发到与该交换机绑定的所有队列上。类似子网广播,
每台子网内的主机都获得了一份复制的消息。所以,Fanout Exchange 转发消息是最快的。
2.Direct (指定路由) 所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue。Direct模式,可以使用rabbitMQ自带的Exchange:default Exchange 。所以不需要将Exchange进行任何绑定(binding)操作 。
消息传递时,RouteKey必须完全匹配,才会被队列接收,否则该消息会被抛弃。、
3.Topic Exchange(占位符指定路由):所有发送到Topic Exchange的消息被转发到所有关心RouteKey中指定Topic的Queue上。
Exchange 将RouteKey 和某Topic 进行模糊匹配。此时队列需要绑定一个Topic。可以使用通配符进行模糊匹配,符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。因此“log.#”能够匹配到“log.info.oa”,
但是“log.*” 只会匹配到“log.error”。所以,Topic Exchange 使用非常灵活。
如何确保消息正确地发送至RabbitMQ?
使用发送方确认模式,确保消息正确地发送到RabbitMQ,信道会发送一个确认给生产者(包含消息唯一ID).当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。
如何避免消息重复投递或重复消费?
在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列;在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,如支付ID、订单ID、帖子ID等)作为去重和幂等的依据,避免同一条消息被重复消费。
4. webservice api的安全性:
1.使用TOKEN+签名认证
1.1做一个认证服务,提供一个认证的WebApi,用户先访问它获取对应的Token
1.2 用户拿着相应的Token以及请求的参数和服务器端提供的签名算法计算出签名后再去访问指定的Api
1.3服务器端每次接收到请求就获取对应用户的Token和请求参数,服务器端再次计算签名和客户端签名做对比,如果验证通过则正常访问相应的Api,验证失败则返回具体的失败信息
2. 使用签名来保证ASP.NET MVC 和 WebApi的接口安全。给每个http请求添加一个签名,服务端来验证签名的合法性,如果签名合法则执行响应的操作,如果签名非法则直接拒绝请求。
签名算法一般都使用Hash散列算法。签名参数 可以用Http请求的queryString然后加上时间戳还有随机数来作为签名的参数
3.基于Owin OAuth;使用OAuth的Client Credential Grant授权方式,在服务端通过Authorization Server的一个实现成功发放了Access Token,并在客户端成功拿到了Access Token。
在ASP.NET WebApi中启用OAuth的Access Token验证非常简单,只需在相应的Controller或Action加上[Authorize]标记。在ASP.NET中基于Owin OAuth`
5. JWT(鉴权授权):
用户提交账号密码给服务器,成功的话,jwt创建一个token返回给用户,存储在客户端cookie中,jwt的字符串是使用.(点)连接的三段字符串,
token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
第一段是 header,json转成字符串以后baseurl64加密
{
"alg": "HS256",
"typ": "JWT"
}
第二段是 PAYLOAD 有效载荷,登录成功以后的用户相关信息,id,账号,过期时间等等,,json转成字符串以后baseurl64加密
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
“exp”:” 1516239022”
}
第三段是 VERIFY SIGNATURE 签名
将第一和第二段的密文拼接起来进行HS256加密+加盐,把生成的密文再次进行baseurl64加密
加盐:用户在输入密码注册后,随机生成一个 salt,一定要是随机生成的。然后按照一定的混淆规则,将 salt 撒入到明文密码中,最后将加盐后的密码做消息摘要,将 salt 和密码的消息摘要传给服务器。服务器如何匹配用户密码是否正确呢?用户用同样的方式对原始密码加盐再生成摘要,发送给服务器,服务器匹配摘要。因为盐是随机生成的,不用每次都生成盐,盐可以存在本地或者服务器,加盐的规则只要不泄漏出去就行,这样的处理比简单的对密码摘要要安全很多。
校验方式:
由于token不存储在服务器,所以需要用户访问的时候(携带token),去校验token
1.使用点(.)分割token,成3段
2.对第二段进行baseurl64解密,获取payload信息,检测token是否过期
3.将第一和第二段的密文拼接起来进行HS256加密+加盐,把生成的密文再次进行baseurl64加密
4.将token和密文比较,一样就是没有被更改的
6. Quartz:开源的作业调度框架。所谓作业调度其实就是按照程序的设定,某一时刻或者时间间隔去执行某个代码,有调度器Scheduler,触发器Trigger,任务Job,任务详情JobDetail日历-Calendar,JobDataMap,cron表达式,quartz.properties文件组成.
Trigger是用来定义Job的执行规则,主要有四种触发器,其中SimpleTrigger和CronTrigger触发器用的最多。
SimpleTrigger:从某一个时间开始,以一定的时间间隔来执行任务。它主要有两个属性,repeatInterval 重复的时间间隔;repeatCount 重复的次数,实际上执行的次数是n+1,因为在startTime的时候会执行一次。
CronTrigger:适合于复杂的任务,使用cron表达式来定义执行规则。
CalendarIntervalTrigger:类似于SimpleTrigger,指定从某一个时间开始,以一定的时间间隔执行的任务。 但是CalendarIntervalTrigger执行任务的时间间隔比SimpleTrigger要丰富,它支持的间隔单位有秒,分钟,小时,天,月,年,星期。相较于SimpleTrigger有两个优势:1、更方便,比如每隔1小时执行,你不用自己去计算1小时等于多少毫秒。
2、支持不是固定长度的间隔,比如间隔为月和年。但劣势是精度只能到秒。它的主要两个属性,interval 执行间隔;intervalUnit 执行间隔的单位(秒,分钟,小时,天,月,年,星期)
DailyTimeIntervalTrigger:指定每天的某个时间段内,以一定的时间间隔执行任务。并且它可以支持指定星期。它适合的任务类似于:指定每天9:00 至 18:00 ,每隔70秒执行一次,并且只要周一至周五执行。它的属性有startTimeOfDay 每天开始时间;endTimeOfDay 每天结束时间;daysOfWeek 需要执行的星期;interval 执行间隔;intervalUnit 执行间隔的单位(秒,分钟,小时,天,月,年,星期);repeatCount 重复次数
7. 冒泡排序
int[] aa = { 1,5,2,3,7 };
int temp;
for (int i = 0; i < aa.Length; i++)
{
for (int j = 0; j < aa.Length-i-1;j++ )
{
if(aa[j+1]<aa[j])
{
temp = aa[j];
aa[j]=aa[j+1];
aa[j + 1] = temp;
}
}
}
for (int i = 0; i < aa.Length;i++ )
{
textBox1.Text += aa[i];
}
这是bai从小到大顺序排列du,如果zhi要从大到小排列只需将地dao7行的<改为>即可
8. 类和结构的异同
Class可以被实例化,属于引用类型,是分配在内存的堆上的。类是引用传递的。
Struct属于值类型,是分配在内存的栈上的。结构体是复制传递的。加分的回答:Int32、Boolean等都属于结构体。
堆和栈的区别
栈是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义;局部值类型变量、值类型参数等都在栈内存中。
堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小。
值类型和引用类型的区别:
1.将一个值类型变量赋给另一个值类型变量时,将复制包含的值。引用类型变量的赋值只复制对对象的引用,而不复制对象本身。
2.值类型不可能派生出新的类型:所有的值类型均隐式派生自 System.ValueType。但与引用类型相同的是,结构也可以实现接口。
3.值类型不可能包含 null 值:然而,可空类型功能允许将 null 赋给值类型。
4.每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。
接口和类
不同点:
不能直接实例化接口。
接口不包含方法的实现。
接口可以多继承,类只能单继承。
类定义可在不同的源文件之间进行拆分。
相同点:
接口、类和结构都可以从多个接口继承。
接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
接口和类都可以包含事件、索引器、方法和属性。
基础知识:接口只能定义方法(只能定义行为,不能定义实现也就是字段),因为事件、索引器、属性本质上都是方法,所以接口中也可以定义事件、索引器、属性。
abstract class和interface
相同点:
都不能被直接实例化,都可以通过继承实现其抽象方法。
不同点:
接口支持多继承;抽象类不能实现多继承。
接口只能定义行为;抽象类既可以定义行为,还可能提供实现。
接口只包含方法(Method)、属性(Property)、索引器(Index)、事件(Event)的签名,但不能定义字段和包含实现的方法;
抽象类可以定义字段、属性、包含有实现的方法。
接口可以作用于值类型(Struct)和引用类型(Class);抽象类只能作用于引用类型。例如,Struct就可以继承接口,而不能继承类。
加分的补充回答:讲设计模式的时候SettingsProvider的例子。
9. IIS经典模式和集成模式
经典模式是为了与之前的版本兼容,使用ISAPI扩展来调用ASP.NET运行库,原先运行于IIS6.0下的Web应用程序迁移到IIS7.0中只要将应用程序配置成经典模式,代码基本不用修改就可以正常运行。集成模式是一种统一的哀求处理管道,它将ASP.NET请求管道与IIS核心管道组合在一起,这种模式能够提供更好的性能,能够实现配置和治理的模块化,而且增加了使用托管代码模块扩展IIS时的灵活性。假如老的Web应用程序运行于IIS7.0的集成模式下,可能需要对应用程序的web.config文件进行修改,尤其是使用了实现IHttpHandler接口的自定义模块的情况。IIS7.0在同一个服务器上能够同时支持两种模式的应用程序。
10. 内存分配
CLR管理的内存主要有三块, 也就是我们对象实例分配在这三块内存区域:
1. 线程的栈: 用于分配值类型实例, 由操作系统管理, 不受垃圾收集器的控制, 当值类型实例所在的方法结束, 其存储单元自动释放. 栈的执行效率高, 但容量有限.
2. GC堆: 用于分配小对象实例(小于85000字节的引用类型). 但有内存分配或垃圾回收时, 垃圾收集器可能会对GC堆压缩.
3. LOH堆: 用于分配大对象实例(大于85000字节的引用类型大对象实例), LOH堆不会被压缩, 只有在GC堆全部被回收后, LOH堆才会被回收.
我们常说的托管堆就是指GC堆和LOH堆
11.sizeof:用来计算类型的大小,单位是字节,sizeof只适用于值类型,并且需要在unsafe上下文环境中使用
class Program
{
static void Main(string[] args)
{
MyUglyClass m = new MyUglyClass();
m.myChar1 = 'd';
m.myInt = 25;
m.myChar2 = 'a';
unsafe
{
Console.WriteLine(sizeof(MyUglyClass));
}
}
}
运行,继续报错:"不安全代码只会在使用 /unsafe 编译的情况下出现"。
解决方法是:右键项目→属性→生成→勾选"允许不安全代码"→保存,再次运行,结果:12。
12.Filter?Attribute?
Filter:根据用途和执行时机的不同,MVC主要分为以下5种类型的过虑器:ResourceFilter、AuthorizationFilter、ActionFilter、ExceptionFilter、ResultFilter.
IMvcFilter只有两个只读属性成员Order(排序,正序)和AllowMultiple(允许多个);
Attribute:ActionFilterAttribute, AuthorizationFilterAttribute,有2个属性,执行前,执行后。
13. IHttpModule与IHttpHandler
先IHttpModule,后IHttpHandler.
IHttpModule:无论客户端请求的是什么文件,都会调用到它;例如aspx,rar,html的请求,对请求进行预处理,如验证、修改、过滤等等,同时也可以对响应进行处理
IHttpHandler:,只有ASP.net注册过的文件类型(例如aspx,asmx等等)才会轮到调用它,按照你的请求生成响应的内容,是HTTP请求的处理中心,真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中
.netcore
1.ASP net core哪些好的功能
遵循了dot net的标准架构, 可以运行于多个操作系统上。它更快,更容易配置,更加模块化,可扩展性更强。
第一是依赖注入
第二是日志系统架构
第三是引入了一个跨平台的网络服务器,kestrel。可以没有iis, apache和nginx就可以单独运行,开源,linux安装一个runtime就行。
第四是可以使用命令行创建应用
第五是更好的支持异步编程
第六是使用start up来注册服务
2.dot net core工程里面有多少个工程文件?
global, launch setting,app settings,bundle config,bower, package。
- 描述一下依赖注入后的服务生命周期,好处?
依赖注入减少了一个类和其他类的耦合并且减少了依赖.提升了代码的可复用性
在dot net core中,我们不需要关心如何释放这些服务, 因为系统会帮我们释放掉。有三种服务的生命周期。
控制反转IOC,去掉对细节的依赖,方便扩展,减少影响范围:甚至转移到配置文件依赖,只需要改配置文件就行了, 屏蔽细节.ioc(控制反转)是一种设计模式(容器中创建实例),DI(依赖注入)是实现手段。除了构造函数注入(ServicesCollection支持,后两个不支持),还有属性注入,方法注入
services.AddTransient<ITestServiceC, TestServiceC>();//瞬时,即时构造(常用)
services.AddSingleton<ITestServiceC, TestServiceC>();//单例-全程唯一(不建议太多单例,一般只在(配置文件,线程池 等)需要的地方才单例)
services.AddScoped<ITestServiceC, TestServiceC>();//作用域单例,本质是容器实例单例(一个http请求就是一个单例,这说明一次请求会创建一个容器实例)例如 事务,数据库连接,主要适用于一次请求只需要一个对象,多个请求需要多个对象
需要安装AutoFac 等包,配置Program,把默认的Ioc容器 ServicesCollections替换成 Autofac
4. startup中的 ConfigureServices和Configure的区别
ConfigureServices:用于配置依赖注入以在运行时根据依赖关系创建对象
Configure: 用于配置中间件(middleware)以构建请求处理流水线
5. .netcore负载均衡
1. 转接头中间件
2. Nginx
前端
1.在浏览器输入网址,Enter之后发生了什么?
输入网址后DNS(域名解析协议)将网址转换成对应的IP,然后网络在路由表中查找最适合一条路由连接到对应的服务器ip,也就是刚刚转换的ip.此时,传输层tcp经过三次握手后建立连接,服务器收到http请求(get/post)等后,进行相应的处理并把结果数据返回到浏览器上,此时输入网址后对应的信息就会显示出来.
- 前端优化
减少 HTTP 请求的次数,启用浏览器缓存,css文件放 在<head>里面,js文件尽量放在页面的底部,使用压缩的css和js文件,如果条件允许,尽量使用CDN的方式引用文件
尽量避免重复的css,尽量减少js里面循环的次数
3. Http协议
1、http协议是浏览器和服务器双方共同遵循的规范,是一种基于TCP/IP应用层协议
2、http是一种典型的请求/响应协议。客户端发送请求,请求的内容以及参数存放到请求报文里面,服务端收到请求后,做出响应,
返回响应的结果放到响应报文里面。通过F12可以查看请求报文和响应报文
3、http协议是”无状态”的,当客户端向服务端发送一次http请求后,服务端收到请求然后返回给客户端相应的结果,服务器会立即断开连接并释放资源。
在实际开发过程中,我们有时需要“保持”这种状态,所以衍生出了Session/Cookie这些技术。
4、http请求的方式主要有get/post。http状态码:200(请求成功)、404(请求的资源不存在)、403(禁止访问)、5xx(服务端错误)
4. tcp、ip三次握手,udp
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,
tcp是面向链接,三次握手是为了保持连接性。
udp是非面相链接,就是发送时不需要和对方建立连接,也不需要理会对方是否接收。udp发送的数据内容,用户是可以进行验证的。
5. 4层协议和7层协议
7层协议:OSI是一个开放性的通信系统互连参考模型,它是一个定义得非常好的协议规范。上到下分别是 7 应用层(HTTP,FTP,NFS,SMTP等) 6 表示层(定义数据格式及加密) 5 会话层(定义了如何开始、控制和结束一个会话,,例如RPC) 4 传输层 (TCP,UDP)3 网络层 (对端到端的包传输进行定义,例如IP)2 数据链路层 (定义了在单个链路上如何传输数据,示例:ATM,FDDI等)1 物理层(有关传输介质的特性)
4层协议:应用层,传输层,网络层,数据链路层(光纤等)
6. Nginx
一款免费的、自由的、开源的、高性能HTTP服务器和反向代理服务器,高性能、稳定性、丰富的功能、简单的配置和低资源消耗。本身就可以托管网站(类似于Tomcat一样),进行Http服务处理,也可以作为反向代理服务器 、负载均衡器和HTTP缓存,跨平台,配置异常简单,非阻塞、高并发连接,Nginx代理和后端Web服务器间无需长连接,Nginx接收用户请求是异步的,网络依赖性低,可以实施负载均衡(轮询,权重), 内存消耗小、成本低廉节省带宽、稳定性高等.
反向代理服务器可以隐藏源服务器的存在和特征。它充当互联网云和web服务器之间的中间层。这对于安全方面来说是很好的,特别是当您使用web托管服务时
最佳用法是在网络上部署动态HTTP内容,使用SCGI、WSGI应用程序服务器、用于脚本的FastCGI处理程序。它还可以作为负载均衡器。
7. MVC如何保持session?
设置session的过期时间
8.301,302,303分别是什么意思
301 Moved Permanently(永久移动)
302临时重定向,client发送post请求,server返回URL和302。如果用户确认,client发送post请求,很多浏览器发送get请求。
303临时重定向,发送Post请求,收到303,直接重定向为get,发送get请求,不需要向用户确认
307临时重定向,客户端发送post请求返回307时,浏览器询问用户是否再次post
以前浏览器碰到302,都是按303那样处理的。
9. cookie的 path,domain?
domain表示的是cookie所在的域, 默认为请求的地址,如网址为www.test.com/test/test.aspx,那么domain默认为www.test.com.
path表示cookie所在的目录,asp.net默认为/,就是根目录.
浏览器会将domain和path都相同的cookie保存在一个文件里,cookie间用*隔开
10. http头信息
Host,Origin(请求的来源域名和端口号 (跨域请求时,浏览器会自动带上这个头信息), Referer,User-Agent,Cookie,Accept,Accept-Encoding,Accept-Language,Connection,Date,Expires,Cache-Control,Last-Modified,Content-Type
11. js中的系统对象,数据类型和函数名称
系统对象:Object、Function、Array、String、Boolean、Number、Date,ERROR,Global,Math
数据类型: null , undefined, boolean,number,string, 引用类型(object、array、function), Symbol(这种类型的对象永不相等即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。)
函数名称: alert, confirm, eval, isNaN, parseFloat, parseInt, join, reverse
,sort, getDate, abs,ceil,floor,max,min,random,round,charAt,indexOf,length,
数据库
1.sql语句慢,你怎么调试出来?怎么解决?
Sql执行计划,mysql是explain
索引,首先考虑在 where及order by涉及的列上建索引
使用“临时表”暂存中间结果,将临时结果暂存在临时表,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能
不要把SQL语句写得太复杂,一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划
使用like进行模糊查询时,除非必要,否则不要在关键词前加%
尽量避免在where中对null判断、!=或<>、or 来连接条件(适用union all)、in (exists 代替 in)和 not in 也要慎用(使用between)、避免在 where 子句中对字段进行表达式操作,函数操作,否则就是全表扫描
2.数据库移植,就是sql,换成mysql,底层怎么做
使用dapper,调用的接口不改变,将数据映射成 xml,就可以了。
3.数据库锁有几种
共享(S)锁:多个事务可封锁一个共享页;任何事务都不能修改该页; 通常是该页被读取完毕,S锁立即被释放。
排它(X)锁:仅允许一个事务封锁此页;其他任何事务必须等到X锁被释放才能对该页进行访问;X锁一直到事务结束才能被释放。
更新(U)锁:用来预定要对此页施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的页将要被更新时,则升级为X锁;U锁一直到事务结束时才能被释放。
4.聚集索引和非聚集索引:
聚集索引确定表中数据的物理顺序,类似于电话簿,分配一块连续的空间,由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引
非聚集索引 随机分配一块空间,数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。
5.事务的特性,隔离级别 ?大多数数据库默认的事务隔离级别是Read committed
1. 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚
2. 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
3. 隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
4. 持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的
隔离级别
1. Read uncommitted读未提交,就是一个事务可以读取另一个未提交事务的数据。
2. Read committed 读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据
3. Repeatable read 重复读,就是在开始读取数据(事务开启)时,不再允许修改操作
4. Serializable 序列化Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
6. MongoDB:定义:开源,高性能,无模式的文档数据库,应用场景:解决 高并发,海量数据的访问和存储,对数据库的高扩展性和高可用性,具体场景: 社交,游戏,物流,物联网,直播等等。缺点:对事务性的支持不大友好,没有复杂的join。
7. show engines ; 查询mysql数据库支持的引擎是MyISAM(性能优先,表锁) 还是InnoDB(默认,事务优先,行锁)
8. 数据库三大范式:1 列不可再分 2 必须有主键 3表的非主属性不能依赖其他表的非主属性外键约束
9.索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
mysql 使用Explain 模拟优化器执行SQL语句,分析查询语句或是结构的性能瓶颈, id越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行 查询索引信息。可以设置慢查询日志,来查看具体慢的sql.
Explain select * from user
主键索引,唯一索引,普通索引,全文索引 4种索引
10. 设计投票系统需要的主要几张表
11. 多表连接查询中有几种连接方式
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
inner join(等值连接) 只返回两个表中联结字段相等的行
cross join(交叉连接) 没有where条件的交叉连接将产生连接表所涉及的笛卡尔积。即TableA的行数*TableB的行数的结果集
full join(全连接) 只要多表中某个表存在匹配的行,就返回行数据
union(结果集合) 将多张表的select语句获得的结果集合并在一起,数据不能重复。
union all(结果集合) 将多张表的select语句获得的结果集合并在一起,数据可以重复。
12. 数据库读写分离的链接怎么写
写只有一个链接,往主库写入。
读有多个链接,配置的时候,轮询/权重/随机 三种算法获取其中一个链接字符串,读取从库数据。
13. mysql和mssql有什么区别,关键字有什么不同?
MySQL是一个免费的、bai开放源du代码的SQL数据库,安装特别简单,
mysql不支持nchar,nvarchar,ntext类型,mysql的递增语句是AUTO_INCREMENT,mysql需要为表指定存储类型,关键字是`包裹,日期是cur_date(),当前完整时间是 now(),只支持一种存储引擎,关键字 EXPLAIN,Now(),Limit
docker
1.Docker是一个容器化平台,它以容器的形式将您的应用程序及其所有依赖项打包在一起,以确保您的应用程序在任何环境中无缝运行。没有环境不一致的情况,我这能用,你那用不了。类似于发布一个app.
2.Docker镜像是Docker容器的源代码,Docker镜像用于创建容器。使用build命令创建镜像。
3.Docker容器包括应用程序及其所有依赖项,作为操作系统的独立进程运行。
4.Docker容器:四种状态:运行、已暂停、重新启动、已退出。
5.Dockerfile中最常见的指令
FROM:指定基础镜像
LABEL:功能是为镜像指定标签
RUN:运行指定的命令
CMD:容器启动时要运行的命令
6.docker常用命令
docker pull 拉取或者更新指定镜像
docker push 将镜像推送至远程仓库
docker rm 删除容器
docker rmi 删除镜像
docker images 列出所有镜像
docker ps 列出所有容器
7. 容器与主机之间的数据拷贝命令: 主机到容器:docker cp /www 96f7f14e99ab:/www/
8. 启动nginx容器(随机端口映射),并挂载本地文件目录到容器html的命令
docker run -d -P --name nginx2 -v /home/nginx:/usr/share/nginx/html nginx
9. 解释一下dockerfile的ONBUILD指令
dockerfile是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
当镜像用作另一个镜像构建的基础时,ONBUILD指令向镜像添加将在稍后执行的触发指令。如果要构建将用作构建其他镜像的基础的镜像(例如,可以使用特定于用户的配置自定义的应用程序构建环境或守护程序),这将非常有用
10. Docker Swarm是Docker的本机群集。它将Docker主机池转变为单个虚拟Docker主机。Docker Swarm提供标准的Docker API,任何已经与Docker守护进程通信的工具都可以使用Swarm透明地扩展到多个主机。
11. 如何在生产中监控Docker
Docker提供docker stats和docker事件等工具来监控生产中的Docker。我们可以使用这些命令获取重要统计数据的报告。
Docker统计数据:当我们使用容器ID调用docker stats时,我们获得容器的CPU,内存使用情况等。它类似于Linux中的top命令。
Docker事件:Docker事件是一个命令,用于查看Docker守护程序中正在进行的活动流。
一些常见的Docker事件是:attach,commit,die,detach,rename,destroy等。我们还可以使用各种选项来限制或过滤我们感兴趣的事件
Linux
基本上都是一些面试常问到的题目
1、说一些你比较常用linux指令
1.1、ls/ll、cd、mkdir、rm-rf、cp、mv、ps -ef | grep xxx、kill、free-m、tar -xvf file.tar、(说那么十几二十来个估计差不多了)
2、查看进程(例:如何查看所有xx进程)
2.1、ps -ef | grep xxx
2.2、ps -aux | grep xxx(-aux显示所有状态)
3、杀掉进程
3.1、kill -9[PID] ---(PID用查看进程的方式查找)
4、启动/停止服务
4.1、cd到bin目录cd/
4.2、./startup.sh --打开(先确保有足够的权限)
4.3、./shutdown.sh ---关闭
5、查看日志
5.1、cd到服务器的logs目录(里面有xx.out文件)
5.2、tail -f xx.out --此时屏幕上实时更新日志。ctr+c停止
5.3、查看最后100行日志 tail -100 xx.out
5.4、查看关键字附件的日志。如:cat filename | grep -C 5 '关键字'(关键字前后五行。B表示前,A表示后,C表示前后) ----使用不多
5.5、还有vi查询啥的。用的也不多。
6、查看端口:(如查看某个端口是否被占用)
6.1、netstat -anp | grep 端口号(状态为LISTEN表示被占用)
7、查找文件
7.1、查找大小超过xx的文件: find . -type f -size +xxk -----(find . -type f -mtime -1 -size +100k -size-400k)--查区间大小的文件
7.2、通过文件名:find / -name xxxx ---整个硬盘查找
其余的基本上不常用
8、vim(vi)编辑器
有命令模式、输入模式、末行模式三种模式。
命令模式:查找内容(/abc、跳转到指定行(20gg)、跳转到尾行(G)、跳转到首行(gg)、删除行(dd)、插入行(o)、复制粘贴(yy,p)
输入模式:编辑文件内容
末行模式:保存退出(wq)、强制退出(q!)、显示文件行号(set number)
在命令模式下,输入a或i即可切换到输入模式,输入冒号(:)即可切换到末行模式;在输入模式和末行模式下,按esc键切换到命令模式
公众号
1优点
微信用户量大,开发成本低 ,是一个开放性平台,形成闭环:一站式服务,效益转化率高
2 OAuth2.0认证流程?与微信OAuth2.0认证流程有什么不同?
1)OAuth2.0处理流程
a.获得用户许可,得到授权码code
b.根据code 获得access
token
c.通过access
token获得openid
d.通过access
token 和openid调用API,获得用户授权信息
2)微信认证流程(将bc合并了)
微信认证只需要获得用户许可后,获得授权码code,
就可以通过code,同时获得access
token以及用户的openid,
然后根据access token 和openid调用API,获得用户授权信息
3 access_token有效时间只有2个小时,并且每天只能请求微信服务器获取access_token 2000次,该问题是如何处理的?
将acess_token存在数据库或文件或缓存每隔一定时间(小于7200s即可),再去获取.
4微信有哪九大高级接口
语音识别,客服接口,OAuth2.0网页授权,生成带参数二维码,获取用户地理位置,获取用户基本信息,获取关注者列表,用户分组接口,上传下载多媒体
5 微信支付流程(需要配置微信支付异步通知回调地址)
1.用户在商户APP中选择商品,提交订单,选择微信支付
2. 商户后台收到用户支付单,调用微信支付统一下单接口
3. 统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP
4. 商户APP调起微信支付
5. 商户后台接收支付通知(小程序没有支付异步通知回调地址)
小程序
1你使用过哪些方法,来提高微信小程序的应用速度
提高页面加载速度
减少默认data的大小
组件化方案
2优势
无需下载,通过搜索和扫一扫就可以打开。
良好的用户体验:打开速度快。
安卓上可以添加到桌面。
为用户提供良好的安全保障。小程序的发布,微信拥有一套严格的审查流程,不能通过审查的小程序是无法发布到线上的。
劣势:
限制较多。页面大小不能超过2M
样式单一。小程序的部分组件已经是成型的了,样式不可以修改
推广面窄,不能分享朋友圈,只能通过分享给朋友,附近小程序推广。其中附近小程序也受到微信的限制。
3原理
微信小程序采用JavaScript、WXML、WXSS三种技术进行开发,JavaScript的代码是运行在微信App中的,WXML只能使用微信提供的现有标签,
微信的架构,是数据驱动的架构模式,它的UI和数据是分离的,所有的页面更新,都需要通过对数据的更改来实现。
小程序分为两个部分webview和appService。其中webview主要用来展现UI,appService用来处理业务逻辑、数据及接口调用。它们在两个进程中运行,通过系统层JSBridge实现通信,实现UI的渲染、事件的处理
4简述下 wx.navigateTo()
, wx.redirectTo()
, wx.switchTab()
, wx.navigateBack()
, wx.reLaunch()
的区别
wx.navigateTo():保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar
页面
wx.redirectTo():关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar
页面
wx.switchTab():跳转到 TabBar
页面,并关闭其他所有非 tabBar
页面
wx.navigateBack()关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages()
获取当前的页面栈,决定需要返回几层
wx.reLaunch():关闭所有页面,打开到应用内的某个页面
转载请标注来源-已哥们经有把我的面试总结,弄到自己网站里,换取打赏了,无语。。。。。。
名师大将莫自牢,千军万马避蓝猫!!!
标签:面试题,缓存,请求,事务,key,服务器,15k,net,客户端 来源: https://www.cnblogs.com/randy619/p/13930739.html