今天看到一篇漫画,[3 年. NET 开发应聘大厂惨遭淘汰, 如何翻身打脸面试官?], 好多问题, 一下子还真的回答不了, 这里对这些问题进行了整理, 增加下脑容量, 哈哈. 俗话说不想当将军的士兵不是好士兵, 不想当架构师的程序员, 不是一个努力要进步的程序员, 努力加油, 不断学习. 有人说架构师都是一批秃顶的人, 程序员都是一群 XX, 其实现实是, 架构师好多不是秃顶, 不用担心自己成了架构师变成秃顶, 那都是吓人的. 程序员也是懂得浪漫的, 要不然那么多浪漫的程序, 那么多酷炫的技巧都是怎么实现的.
1.C# 中的委托是什么? 事件是不是一种委托?
委托是一种引用类型, 表示对具有特定参数列表和返回类型的方法的引用. 委托用于将方法作为参数传递给其他方法. 事件就是通过委托调用的方法.
例如:
- public class DelegateTest
- {
- public delegate int AddDelegate(int a, int b); // 定义委托类型
- public AddDelegate addDelegate; // 定义委托
- public event AddDelegate AddDelegateForEvent; // 定义事件
- public int Add(int a, int b) {
- Console.WriteLine($"a:{a},b:{b}");
- return a + b;
- }
- // 委托和事件的使用
- public static void Test() {
- DelegateTest text = new DelegateTest();
- text.addDelegate = text.Add; ;
- text.addDelegate(1, 2);
- text.AddDelegateForEvent += text.addDelegate;
- text.AddDelegateForEvent += text.addDelegate;
- text.AddDelegateForEvent(10, 20);// 或者下面的使用
- //AddDelegate d = text.AddDelegateForEvent;
- //d(10, 20);
- // 结果
- //a: 1,b: 2
- //a: 10,b: 20
- //a: 10,b: 20
- }
- //Func 和 Action 的使用
- public static void Test2() {
- Func<int, int, int> add = (int a, int b) => { return a + b; };
- Action<int, int> addVoid = (int a, int b) => { int c = a + b; };
- }
- }
- C# 中委托这篇文章, 对委托有更多的介绍. Fun 和 Action 是微软封装的委托, 一个有返回值, 一个没有, C# 高级功能(三)Action,Func,Tuple 这篇文章介绍的比较详细.
2. 聊聊. NET 的管道和. NET Core 的中间件
.NET 的管道: 在管道模型运行开始前, 首先 HTTP 的请求被被传递到 HttpRuntime 类的一个实例中, 然后这个实例对象检测请求并找到被接受的那个应用程序, 接下来管道模型就使用 HttpApplicationFactory 对象来创建一个 HttpApplication 对象来处理这个请求(在此同时也将创建 HttpContext,HttpRequest 和 HttpResponse), 一个 HttpApplication 可以包含一系列 HttpModule 对象.
ASP.NET MVC 请求生命周期
URL Routing Module →→ Matching Route Entry →→ Route Handle →→ Http Handle →→ Controller Factory →→ Controller →→ Action Invoker →→ Module Binders →→ Authentication Filter →→ Authorization Filter →→ Action Filter →→ Action Execution →→ Action Filter →→ Action Result
简单就是: Url →→ Route →→ Controller →→ Action →→ View
其他的 ASP.NET 生命周期的文章, ASP.NET 生命周期 , webForm 页面运行周期 -- 页面关系
.NET Core 的中间件
中间件是一种装配到应用管道中以处理请求和响应的程序, 使用 Run,Map 和 Use 扩展方法来配置请求委托. 请求委托用于构建请求管道, 处理每个 HTTP 请求. 每个委托可以在下一个委托之前和之后执行操作. 委托还可以决定不将请求传递给下一个委托, 这称为请求管道的短路. 短路通常是可取的, 因为它避免了不必要的工作.
- public class Startup
- {
- // 此处省略部分代码, 创建一个新的 Core Web 项目, 可以自行查看
- public void Configure(IApplicationBuilder App, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- App.UseDeveloperExceptionPage();
- }
- else
- {
- App.UseExceptionHandler("/Home/Error");
- App.UseHsts();
- }
- App.UseHttpsRedirection();
- App.UseStaticFiles();
- App.UseCookiePolicy();
- App.UseMvc(routes =>
- {
- routes.MapRoute(
- name: "default",
- template: "{controller=Home}/{action=Index}/{id?}");
- });
- }
- }
Configure 方法中的就是中间件, 中间件组件的顺序定义了在请求上调用它们的顺序, 以及响应的相反顺序, 此排序对于安全性, 性能和功能至关重要.
常用的中间件顺序
1. 异常 / 错误处理
2. HTTP 严格传输安全协议, HTTP 协议介绍
3. HTTPS 重定向
4. 静态文件服务器
5. Cookie 策略实施
6. 身份验证
7. 会话
8.MVC
中间件例子:
- public class LogMiddleware
- {
- private readonly RequestDelegate _next;
- public LogMiddleware(RequestDelegate next)
- {
- _next = next;
- }
- public async Task Invoke(HttpContext context)
- {
- Debug.WriteLine("程序运行 开始.");
- await _next(context);
- Debug.WriteLine("程序运行 结束.");
- }
- }
- public static class LogMiddlewareExtensions {
- public static IApplicationBuilder UseLog(this IApplicationBuilder App) {
- return App.UseMiddleware<LogMiddleware>();
- }
- }
在 Configure 中 App.UseLog(); 就可, 程序运行, 会在 VS 调试输出的地方显示
程序运行 开始.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Index", controller = "Home"}. Executing action ---- 此处省略部分输出
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action WebCore.Controllers.HomeController.Index (WebCore) in 13.9555ms
程序运行 结束.
3. 说说数据库的隔离级别, 数据库有哪些锁
数据库事物的四大特性: 原子性, 一致性, 隔离性, 持续性(永久性). 原子性: 要么全做, 要么全不做; 一致性: 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态. 一致性与原子性是密切相关的; 隔离性: 一个事务的执行不能被其他事务干扰; 永久性: 一个事务一旦提交, 它对数据库中数据的改变就应该是永久性的.
事务的隔离性: 未提交读(Read uncommitted), 已提交读(Read committed), 可重复读(Repeatable read), 可串行化(Serializable ). 未提交读: 最低级别, 任何情况都无法保证; 已提交读: 可避免脏读的发生; 可重复读: 可避免脏读, 不可重复读的发生; 串行化: 可避免脏读, 不可重复读, 幻读的发生. 举例: 未提交读: A 更新了数据没有提交 B 可以看到; 已提交读: A 更新了数据没有提交 B 看不到, 提交之后可以看到; 可重复读: A 插入一条数据, 提交之后, B 看不到, B 事物结束之后, 在查询可以看到; 可串行化: A 执行完之后 B 才可执行.(所有的一切操作都是并行操作)
数据库中的锁: 分为独占锁(即排它锁), 共享锁和更新锁, 细分又可分为表锁, 行锁, 页锁等.
为什么需要所? 当并发事务同时访问一个资源时, 有可能导致数据不一致, 因此需要一种机制来将数据访问顺序化, 以保证数据库数据的一致性.
共享锁表示对数据进行 select 操作, 多个事务可以同时为一个对象加共享锁. 排他锁也叫写锁, 排他锁表示对数据进行 insert,update 或 delete 操作, 如果一个事务对对象加了排他锁, 其他事务就不能再给它加任何锁了. 更新锁在的初始化阶段用来锁定可能要被修改的资源, 这可以避免使用共享锁造成的死锁现象.
4. 口述下如何设计一个 SOA 框架
SOA 的全称是 Service Oriented Architecture, 即面向服务的架构. 它可以根据需求通过网络对应用组件进行分布式部署, 组合和使用, 服务层是 SOA 的基础, 可以直接被应用调用, 从而有效控制系统松耦合. 简单来说就是 A 功能布置在 A 服务器, B 功能布置在 B 服务器, 他们都开放出接口供 C.. 等访问, C 不用知道 A,B 是如何实现的, 只管用就可以了. 简单的例子 webservice,WCF,Web API 等等.
SOA 框架的文章, Web Service 和 WCF 的比较
5.SOA 和微服务架构之间的主要区别是什么?
我的理解是: SOA 和微服务是一脉相承的, 两者都是中立性, 语言无关, 协议跨平台. 微服务的目的是有效的拆分应用, 服务的细粒度, 重用组合, 甚至是每个操作 (或方法) 都是独立开发的服务, 足够小到不能再进行拆分. SOA 更适合大型企业中的业务过程编排, 应用集成.
6. 了解各个 framework 的底层不?
C# 源码文件 →→ C# 编译器 →→ 程序集 →→ 本机语言
底层的库: CLR(Common Language Runtime)公共语言运行时, CTS(Common Type System)通用类型系统, CLS(Common Language Specfication)公共语言规范, CIL(Common Intermediate Language)公共中间语言, CLI(Common Language Infrastructure)公共语言基础结构
7. 说说浏览器页面的渲染过程
DNS 查询 →→ TCP 链接 →→ HTTP 请求 → 服务器响应 →→ 客户端渲染(html,CSS,JS)
8. 说说中介模式的设计原理和应用场景
中介者模式是用来降低类类之间的耦合的, 因为如果类类之间有依赖关系的话, 不利于功能的拓展和维护, 只要修改一个对象, 其它关联的对象都得进行修改, 如果使用中介者模式, 只需关心和 Mediator 类的关系, 具体类类之间的关系及调度交给 Mediator 就行. 房产中介, QQ 游戏平台, 聊天室, QQ 群和短信平台
9. 请问如何构架一个高负载的系统?
应用服务和数据服务分离, 使用缓存改善网站性能, 使用应用服务器集群改善网站的并发处理能力, 数据库读写分离, 使用反向代理和 CDN 加速网站响应, 使用分布式文件系统和分布式数据库系统, 使用 NoSQL 和搜索引擎, 对业务拆分, 建立分布式服务.
10..NET 系统如何实现水平扩展, 如何解决高并发问题
水平扩展: 利用 Nginx 建立分布式系统, 增加服务器, 增加 CPU
解决高并发问题: 增加缓存, 禁止用户重复操作, 建立请求队列
11. 说说 IIS 的工作原理?
对比 IIS 来说, 它依赖 HTTP.SYS 的内置程序来监听外部的 HTTP 请求, 如果请求的是一个可访问的 URL,HTTP.SYS 会将这个请求交给 IIS 工作进程, 把信息保存到 HttpWorkRequest 中, 在相互隔离的应用程序域 AppDomain 中加载 HttpRuntime, 调用 HttpRuntime 的 ProcessRequest 方法, 之后就是我们的程序操作, 最后返回数据流, 并重新返回到 HTTP.SYS,HTTP.SYS 在将数据返回给客户端浏览器.
Win10 下 IIS 配置图解, MVC 项目发布图解, IIS 添加网站图解.
12. 手写一个千万并发的商品秒杀功能
Redis 缓存秒杀的商品 ID, 数量, 一个请求数量减少一个, 数量等于 0 的时候, 直接返回失败, 成功的数据保存到消息队列中, 之后保存到数据库, 秒杀的商品比较少的, 直接用一个线程安全的列表就可以了.
来源: https://www.cnblogs.com/zhao123/p/11104207.html