一、对于 Web 性能优化,您有哪些了解和经验吗?
1、前端优化
(1)减少 HTTP 请求的次数。我们知道每次发送http请求,建立连接和等待相应会花去相当一部分时间,所以在发送http请求的时候,尽量减少请求的次数,一次请求能取出的数据就不要分多次发送。
(2)启用浏览器缓存,当确定请求的数据不会发生变化时,能够直接读浏览器缓存的就不要向服务端发送请求。比如我们ajax里面有一个参数能够设置请求的时候是否启用缓存,这种情况下就需要我们在发送请求的时候做好相应的缓存处理。
(3)css文件放 在里面,js文件尽量放在页面的底部。因为请求js文件是很花费时间,如果放在里面,就会导致页面的 DOM树呈现需要等待js文件加载完成。这也就是为什么很多网站的源码里面看到引用的文件放在最后的原因。
(4)使用压缩的css和js文件。这个不用多说,网络流量小。
(5)如果条件允许,尽量使用CDN的方式引用文件,这样就能减少网络流量。比如我们常用的网站http://www.bootcdn.cn/。
(6)在写js和css的语法时,尽量避免重复的css,尽量减少js里面循环的次数,诸如此类。
2、后端优化:
(1)程序的优化:这是一个很大的话题,我这里就选几个常见的。比如减少代码的层级结构、避免循环嵌套、避免循环CURD数据库、优化算法等等。
(2)数据库的优化:(由于数据库优化不是本题重点,所以可选几个主要的来说)比如启用数据库缓存、常用的字段建索引、尽量避免大事务操作、避免select * 的写法、尽量不用in和not in 这种耗性能的用法等等。
大数据的处理;数据层如何优化(索引、尽量避免是*、like 、not in等操作、使用分页、存储过程的方式)、Redis的缓存数据库的用法、读写分离数据库的 用法、使用轻量级的ORM(NPoco)等操作;
(3)服务器优化:(这个可作为可选项)负载均衡、Web服务器和数据库分离、UI和Service分离等等。
二、Asp.Net Web API VS Asp.Net MVC
1、Asp.net MVC 是用来创建返回视图(Views)与数据的Web应用,而Asp.net Web API是一种简单轻松地成熟的HTTP服务,它只返回数据,不返回视图(Views)。
2、Asp.net Web API可以通过.Net Framework来帮助我们构建REST-ful服务,而且他支持内容协商(根据客户端能接受的格式要求,返回相应的JSON,XML,ATOM),同时Asp.net Web API支持自我宿主(self-hosting),而MVC并不支持(只能宿主在IIS中)。
3、Asp.net Web API可以返回特定的数据类型,比如JSON,XML,或者其他在请求头中定义的数据格式。而MVC只能利用Json Result返回JSON数据类型。
4、Asp.net Web API 根据HTTP 谓语动词来映射Action,但MVC只是映射 Action 名称。
5、Asp.net Web API 一种全新的框架,它是Asp.net Framework 核心库的一部分。在Asp.net Web API 一些存在MVC中的特征(model binding、filters、路由)是存在System.Web.Http程序集中,而MVC是存在System.Web.Mvc中。因此,Web API 可以和Asp.net一起使用,也可以做独立的服务层。
6、如果在一个项目中融合Web API和MVC controller,用于处理复杂AJAX请求,这些请求可能返回JSON,XML或者其他数据格式。这就是Web API 自我宿主(Web API self-hosting)。
7、如果融合MVC和Web API 控制器(controller),而且需要集成认证,这时,需要创建两个过滤器(Filters),一个MVC的,另一个Web API的,因为他们两个是不相同的。
8、总之,WebApi在提供数据方面,是比MVC更加轻量的架构。
三、WebApi中Filter种类及作用
Authorization IAuthorizationFilter 最先运行的Filter,被用作请求权限校验
Action IActionFilter 在Action运行的前、后运行
Exception IExceptionFilter 当异常发生的时候运行
四、关于webapi开发接口的安全问题,推荐使用JWT的方式进行接口调用的加密
JWT即JSON web Tokens ,可以用来安全的传递信息,因为这些信息是经过数字签名的
JWT可以使用一种加密算法比如HMAC算法,也可以使用公钥/私钥的非对称算法
因为JWT签名后的信息够短,可以放在URL里,request body里、http header里,传输够快
负载信息里面包含所有你想要的信息,避免不止一次的去查询数据库
JWT的使用场景主要包括
1)认证,这是比较常见的使用场景,只要用户登陆过一次系统,之后的请求都会包含签名出来的token
,通过token也可以用来实现单点登陆
2)交换信息,通过使用密钥对来安全的传递信息,可以知道发送者是谁,放置信息被篡改
JSON web Tokens由三部分组成,用英文句点分割(.),一般看起来例如xxx.yyy.zzz
分为:
Header 头信息
PayLoad 负载信息,实际数据
Signature 由头信息+负载信息+密钥 组合之后进行加密得到
1)Header头信息通常包含两部分,type:代表token的类型,这里使用的是JWT类型。alg:使用的Hash算法
,例如HMAC SHA256或RSA
{
"alg":"HS256",
"type":"JWT"
}
//这会被经过base64URL编码形成第一部分
2)PayLoad 一个token的第二部分是负载信息,它包含一下声明Claim(实体的描述,通常是一个User信息,还包括一些
其它的元素)
声明分三类
a)Reserved Claims,这是一套预定义的声明,并不是必须的,这是一套易于使用。操作性强的声明,包括iss(issuer)
exp(expiration time)、sub(subject)、aud(audience)
b)Public Claims
c)Private Claims,交换信息的双方自定义的声明
3)signature使用header中指定的算法将编码后的headr、编码后的payload、一个secret进行加密
例如使用的是HMAC SHA256算法,大致流程类似于:HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload)+"."+secret)
这个signature字段被用来确认JWT信息的发送者是谁,并保证信息没有被修改;
由于没有使用Cookies,Cross-Origin Resource Sharing(CORS),跨域的资源访问不会成为问题;
五、MVC路由理解?
1、首先我们要理解MVC中路由的作用:url Routing的作用是将浏览器的URL请求映射到特定的MVC控制器动作。
2、当我们访问http://localhost:8080/Home/Index 这个地址的时候,请求首先被UrlRoutingModule截获,截获请求后,从Routes中得到与当前请求URL相符合的RouteData对象, 将RouteData对象和当前URL封装成一个RequestContext对象,然后从Requestcontext封装的RouteData中得到 Controller名字,根据Controller的名字,通过反射创建控制器对象,这个时候控制器才真正被激活,最后去执行控制器里面对应的 action。
六、谈谈你觉得做的不错系统,大概介绍下用到了哪些技术?
WPF、MEF、Vue、Xamarin (展开)
七、IOC和DI
其实它们是同一个概念的不同角度描述,控制反转IOC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IOC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IOC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IOC容器了,通过IOC容器来建立它们之间的关系。DI(依赖注入)其实就是IOC的另外一种说法,DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结道:控制的什么被反转了?就是获得依赖对象的方式反转了。
NETCore下DI使用总结
AddSingleton : 在整个应用生命周期里都是唯一
AddTransient:每次获取一次服务就创建一个实例
AddScoped:在我们自定义的Scope内的生命周期,在Scope内是唯一
八、设计模式的六大原则
单一职责原则:一个类只负责一个职责,不能有多个导致类变更的原因
开闭原则:一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭
里氏替换原则:避免子类重写父类中已经实现的方法
迪米特法则:一个对象应该对其他对象有最少的了解
接口隔离原则:接口尽量小,接口要高内聚
依赖倒置原则:要尽可能使用接口或抽象类
九、谈谈你对设计模式的认识?结合你用得最多的一种设计模式说说它的使用
单例模式:1)一个类只有一个实例;2)提供一个全局访问点;如何保证一个类只有 一个实例,定义私有的构造函数,这样外界就不能通过new关键字进行 创建实例了;
工厂模式
观察者模式
十、数据库优化经验(后端工程师非常常见)
1、数据库运维方面的优化:启用数据库缓存。对于一些比较常用的查询可以采用数据库缓存的机制,部署的时候需要注意设置好缓存依赖项,防止“过期”数据的产生。
2、数据库索引方面的优化:比如常用的字段建索引,联合查询考虑联合索引。(PS:如果你有基础,可以敞开谈谈聚集索引和非聚集索引的使用场景和区别)
3、数据库查询方面的优化:避免select * 的写法、尽量不用in和not in 这种耗性能的用法等等。
4、数据库算法方面的优化:尽量避免大事务操作、减少循环算法,对于大数据量的操作,避免使用游标的用法等等。
十一、关于代码优化你怎么理解?你会考虑去代码重构吗?
1、对于代码优化,之前的公司每周会做代码审核,审核的主要作用就是保证代码的正确性和执行效率,比如减少代码的层级结构、避免循环嵌套、避免循环CURD数据库、尽量避免一次取出大量数据放在内存中(容易内存溢出)、优化算法等。
2、对于陈旧代码,可能很多地方有调用,并且开发和维护人员很有可能不是同一个人,所以重构时要格外小心,如果没有十足的把握,不要轻易重构。如果必须要重构,必须做好充分的单元测试和全局测试。
十二、谈谈你的优点和缺点
优点:对于新的技术学习能力强,能很快适应新环境等等
缺点:对技术太过于执着等等
十三、关于服务器端 MVC 架构的技术实现及理解
MVC,顾名思义,Model、View、Controller。所有的 界面代码放在View里面,所有涉及和界面交互以及URL路由相关的逻辑都在Controller里面,Model提供数据模型。MVC的架构方式会让系 统的可维护性更高,使得每一部分更加专注自己的职责,并且MVC提供了强大的路由机制,方便了页面切换和界面交互。然后可以结合和WebForm的比较, 谈谈MVC如何解决复杂的控件树生成、如何避免了复杂的页面生命周期。
十四、运行慢,如何定位问题?发现问题如何解决?
后台日志查看请求耗时,然后再去查找耗时的根源并解决该问题
十五、说说你最擅长的技术?并说说你是如何使用的?
MEF、 DIP、IOC、DI、插槽、服务
十六、写过多线程组件?简要说明!
Reduce
当任务触发的频率非常高时,合并名称相同的任务处理函数,保证名称相同的任务只一个在执行,保证第一个任务能执行到
保证名称相同的任务只一个在执行,且最后一个任务能执行到,中间某些任务的返回结果会被覆盖掉,返回最后一个任务的执行结果
保证相同参数的任务只有一个在执行
保证参数相同的任务只一个在执行,且最后一个任务能执行到,中间某些任务会被忽略掉
合并指定时间段内的事件,间隔小于时间段的事件都被忽略,保证最后一个任务能被执行
TaskQueue
TaskPool
十七、Http协议
1、http协议是浏览器和服务器双方共同遵循的规范,是一种基于TCP/IP应用层协议。
2、http是一种典型的请求/响应协议。客户端发送请求,请求的内容以及参数存放到请求报文里面,服务端收到请求后,做出响应,返回响应的结果放到响应报文里面。通过F12可以查看请求报文和响应报文。
3、http协议是”无状态”的,当客户端向服务端发送一次http请求后,服务端收到请求然后返回给客户端相应的结果,服务器会立即断开连接并释放资源。在实际开发过程中,我们有时需要“保持”这种状态,所以衍生出了Session/Cookie这些技术。
4、http请求的方式主要有get/post。
5、http状态码最好记几个,博主有一次面试就被问到了。200(请求成功)、404(请求的资源不存在)、403(禁止访问)、5xx(服务端错误)
十八、http常见状态码
2开头状态码
2xx (成功)表示成功处理了请求的状态代码
200 (成功) 服务器已成功处理了请求。 通常。
3开头状态码
3xx (重定向) 表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
302重定向
304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
4开头状态码
4xx(请求错误) 这些状态代码表示请求可能出错,妨碍了服务器的处理
1:400 (错误请求) 服务器不理解请求的语法。
2:403 (禁止) 服务器拒绝请求。
3:404 (未找到) 服务器找不到请求的网页。
5开头状态码
5xx(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
十九、Ajax提交数据
$.ajax({
url: "admin/check_login", // 提交到controller的url路径
type: "post", // 提交方式
data: {"username": username, "password": password}, // data为String类型,必须为 Key/Value 格式。
dataType: "json", // 服务器端返回的数据类型
success: function (data) { // 请求成功后的回调函数,其中的参数data为controller返回的map,也就是说,@ResponseBody将返回的map转化为JSON格式的数据,然后通过data这个参数取JSON数据中的值
if (data.message == "success") {
//跳转到系统首页
......
} else {
......
}
},
});
二十、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,客户端处理响应,整个过程结束。
二十一、SQL Server数据库操作的原子性
SQL Server数据库操作的原子性,出Select之外,Update、Insert、Delete的操作都是原子性的,不可拆分,执行的最小单位;可以用于充值交费中 ,如果多个请求进行更新同一条 数据时,直接使用update Table1 set money=money+100 这种方式就可以避免多个语句,更新一条记录导致的更新失败的问题(一般想法是,先查询当前的账户余额,然后进行更新,这种想法太low);可以直接使用一条更新语句即可;