设为首页 收藏本站
查看: 1630|回复: 0

[经验分享] ASPNET_WEBAPI快速学习02

[复制链接]

尚未签到

发表于 2017-2-19 11:57:56 | 显示全部楼层 |阅读模式
  这部分内容的学习,已经放了大半年时间了,果断补充上,尽早将过去遗留的老技术坑都补上。首先将介绍服务幂等性的概念和相关解决方案,这部分也将是本文的理解难点,由于WebAPI是一种Restful风格服务的实现方式,其遵循HTTP标准方法,因此理解好这部分概念,对于提供良好的业务服务显得非常重要。之后则将介绍SignalR这一长连接通讯的集成解决方案的概念和实践,这部分在交互式的Web场景中非常有效。最后将补充Owin、IOC、EnterpriseLibrary等相关知识,这些也都是.NET程序员比较容易忽视的知识点,这些知识在快速搭建Solution上有很大的帮助。
DSC0000.png

  最早接触这个概念还是在一次面试的过程中,当时记得自己只能是通过卖萌将这一概念一笔带过,由于当时的项目实践相对较少,且被微软便捷的服务搭建所欺骗,以为搭建一个webService只用在IDE中添加有一个.asmx就万事大吉了,其他项目通过一个服务引用就算是SOA实现了(WCF额外需要配置一下终结点),其实对于整个服务的概念完全是个门外汉。
  那么在实际中,搭建一个服务需要注意那些问题呢?接下来通过一个简单的表格来描述。



关注因素诠释
通讯协议的选取例如常见的TCP、HTTP、SOAP等,实际上任何协议都可以作为服务的载体,只要适合相应的场景即可
URL服务的地址,服务的消费者可以通过这个地址请求服务
安全性只有通过认证的请求才能获得服务,不同的服务方法需要不同权限控制
幂等性对于同一个服务方法来说,相同的请求参数无论请求几次,都将获得相同的结果(简化版的解释,不太完备)
其他与服务相关的概念非常多,比如:在架构层次流行的微服务,用于解耦应用;服务的监控、限流;分布式服务的治理、扩容等。
  接下来将详细介绍服务幂等性的概念,相关解决方案和基于HTTP协议的服务幂等性等知识。
  基础概念:从抽象代数的角度,幂等Idempotence就是f(f(x)) = f(x)。也就是说对同一个服务的1次或多次调用,返回的结果相同,且对服务系统的影响相同,接下来通过一个非常简单的图来描述该概念在服务请求场景下的意义。
DSC0001.png

  在上图中,第一次扣款请求成功,但返回丢失,这是Client重发扣款请求,之后成功。在这样的场景下,如果不控制服务的幂等性,就会出现重复扣款的情况出现。
  解决方案:上例标准的解决方案是,客户端的这个操作需要两个请求,首先需要向服务端申请一个ticket进行扣款操作,之后将该ticket作为参数的一部分发送给Server请求扣款。服务端首先检验该ticket是否已经被使用,若被使用,直接返回成功;若未被使用,则进行相应扣款操作。逻辑上很简单,不过在实践时有几点需要注意:



注意事项诠释
幂等的时效性在实际项目中,幂等是具有时效性的,不同的业务需求会有不同的时效性要求。一般来说,对于重要业务操作,通过是与Money有关的操作,要求持久的服务幂等性,这是就需要选用数据库来实现幂等控制,将ticket(流水号,GUID等)保存起来,其特点是安全、低效;对于一般的数据,可以选用缓存来控制,其特点是高效、不稳定。
数据库实现幂等比如SQL SERVER, 在Read Committed隔离级别下,,建立一张专门的幂等表,通过重复insert的异常来实现幂等,比较规范;也可以通过NoLock读的方式,更搞笑,但存在隐患,推荐前者。Tip:通过SqlException, Number = 2601
缓存实现幂等比如Redis,通过与key相关的操作,Exists Key
CRUD操作的幂等级别SELECT最高,为只读级别;UPDATE、DELETE次之,为幂等级别;INSERT为不能幂等级别。也就是说,SELECT操作不管是一次操作还是多次操作,均不改变目标的状态;UPDATE、DELETE只在第一次调用时会改变状态,之后不会;而INSERT则每次均改变状态。
CAS操作之前一直有个疑惑,就是关于UPDATE操作,比如a++的情况下,这个操作不是幂等的,但实际上,这不是一个原子操作,其涉及一次查询和一次修改,在很多语言中,都支持称为CAS(CompareAndSet)的原子操作。
Ticket的生成根据不同的场景,可以是客户端生成,也可以是服务端生成,当然,最好的方案是设置好指定规则,然后由客户端生成ticket,比如GUID组合客户端的标识的方式,因为这样可以减少服务端的压力,无论是CPU还是网络。
  基于HTTP协议的服务幂等性:在之前的表格中,已介绍过CRUD操作所对应的幂等级别,那么对应到HTTP的操作呢?很简单,GET表示查询操作,PUT和DELETE表示更新和删除操作,POST表示插入操作,因此POST操作需要添加幂等控制的。当然了,在WebAPI的实际设计中,接口的URL格式和http报文中Body的参数值会需要进一步的思考。
  此外,大家也可以查阅博主Todd Wei的博文http的幂等性http://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html
DSC0002.png

  SignalR这个名字,咋一看还挺高大上的,实际上和WCF、AJAX类似,并不是什么新技术,而是对已有技术的一种整合,集成了客户端和服务端的库。不知道大家还记不记的,大学时学习的Windows网络编程,当时通过WinSocket搭建了一个聊天室,其实这里的SignalR也一样,最常见的应用仍然是聊天室场景,不过变成浏览器和服务器之间,而不是过去的Client与服务器之间。那么它与H5的WebSocket有什么区别么?准确来说,SignalR整合了WebSocket,在浏览器支持H5的情况下就使用WebSocket,若不支持,就通过长轮训的方式,算是一种兼容性的整体解决方案。
  简单来说,记住一点就好,SignalR支持双向通信的长连接,其是对http请求-响应模式的有力补充。其提供一个简单的API用于创建服务端到客户端的远程过程调用(RPC),以便从服务器端.NET代码中调用客户端浏览器中的js代码。
  SignalR的API包含两种客户端和服务器之间进行通信的模型:永久连接和Hubs。。接下来通过来通过一段代码,走进SignalR的世界。


DSC0003.gif DSC0004.gif


1 前端页面
2 @{
3 ViewBag.Title = "Chat";
4 }
5
6 <h2>Chat</h2>
7 <div class="container">
8 <input type="text" id="message" />
9 <input type="button" id="sendmessage" value="Send" />
10 <input type="hidden" id="displayname" />
11 <ul id="discussion"></ul>
12 </div>
13 @section scripts{
14 <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
15 <script src="~/signalr/hubs"></script>
16 <script>
17 $(function () {
18 //reference the auto-generated proxy for the hub
19 var chat = $.connection.chatHub;
20 chat.client.addNewMessageToPage = function (name, message) {
21 //add the message to the page
22 $('#discussion').append('<li><strong>' + htmlEncode(name) + '</strong>: ' + htmlEncode(message) + '</li>');
23 };
24 //get the user name and store it to prepend to messages.
25 $('#displayname').val(prompt('Enter your name:', ''));
26 //set initial focus to message input box
27 $('#message').focus();
28 //start the connection
29 $.connection.hub.start().done(function () {
30 $('#sendmessage').click(function () {
31 chat.server.send($('#displayname').val(), $('#message').val());
32 $('#message').val('').focus();
33 });
34 });
35 });
36
37 //this optional function html-encodes messages for display in the page
38 function htmlEncode(value) {
39 var encodedValue = $('<div/>').text(value).html();
40 return encodedValue;
41 }
42 </script>
43 }
44
45 Startup文件
46 [assembly: OwinStartup(typeof(Sory.Framework.SignalRDemo.Startup))]
47 namespace Sory.Framework.SignalRDemo
48 {
49 public class Startup
50 {
51 public void Configuration(IAppBuilder app)
52 {
53 //Any connection or hub wire up and configuration should go here
54 app.MapSignalR();
55 }
56 }
57 }
58
59 Hub文件
60 public class ChatHub : Hub
61 {
62 public void Send(string name, string message)
63 {
64 Clients.All.addNewMessageToPage(name, message);
65 }
66 }
View Code  相关学习可以参见张善友大神的4年前的博文SingalR QuickStart, http://www.cnblogs.com/shanyou/archive/2012/07/28/2613693.html
  另外还有博主will_晓柠的博文http://www.cnblogs.com/vance/p/SignalR.html,相对版本更新一些,此外其翻译的Signal入门非常的赞,必须顶http://files.cnblogs.com/files/wanliwang01/SignalR2.0.pdf
DSC0005.png

  简单来说,类似J2EE中javaWeb的相关标准(servlet),之后各种不同的容器厂商均可以针对该接口提供自己的实现,比如Tomcat、Weblogic等。随着微软慢慢走向开发,也提出了相应的接口标准,这个标准就是Owin,我们常见的IIS其实就是该标准的一个官方实现。记得身边的一位大牛说过,JAVA就是先自己开发,其他的厂商也模仿着开发,之后为了统一就建立标准,之后的版本大家都按照这个标准来,类似于实践推导出理论,理论再来指导实践的过程。
  在Owin中,将不再使用ASP.NET管道处理请求,而是使用Owin管道来处理请求,其通过一个Dictionary来传递上下文信息,其信息如下表所示。



Key Name类型描述
Owin.RequestBodyStreamHttp请求体
Owin.RequestHeadersIDictionary<string, string[]>Http请求头
Owin.RequestMethodString请求方法, get, post等
Owin.RequestPathBaseStringURL根
Owin.RequestPathStringURL路径,根后面的部分
Owin.RequestProtocolString协议名称和版本, http/1.1
Owin.RequestQueryStringString查询字符串
Owin.RequestSchemaStringhttp或者https
  Owin接口微软的官方实现叫做Katana(武士刀)的组件包括:Application, Middleware, Server和Host。在vs2013中的MVC5模板中,添加如下DLL,和在nuget中package添加如下配置。





1 <package id="Owin" version="1.0" targetFramework="net451"/>
2 <package id="Microsoft.Owin" version="2.0.0" targetFramework="net451"/>
3 <package id="Microsoft.Owin.Host.SystemWeb" version="1.0" targetFramework="net451"/>
4 <package id="Microsoft.Owin.Security" version="1.0" targetFramework="net451"/>
5 <package id="Microsoft.Owin.Security.Cookies" version="1.0" targetFramework="net451"/>
View Code  需要提及的是,其通过一个称为claims-based认证方式进行用户的认证,与原有Form认证方式有一定区别,简单来讲,类似于windows的token认证(单登SSO)。
  详细信息,可以参考Jesse博主的博文http://www.cnblogs.com/jesse2013/p/aspnet-identity-claims-based-authentication-and-owin.html#what-is-owin
DSC0006.png

  IOC框架用于解耦系统不同层次间的依赖关系,便于系统的扩展。当然其也会在一定程度上增加系统的复杂性,影响系统的效率,那么选择一个高效可靠IOC显得非常重要。IOC控制反转的相关组件非常的多,包括微软的Unity,第三方的Autofac,CastleWindsor, Spring.NET, StructureMap, Ninject等,其中Unity表现的中规中矩,在大量迭代情况下(>1000000),Autofac和StructureMap效率最高。就我个人而言,由于公司的组件库支持Unity,那么就不用选了,哈哈。
  详情请见Leepy大神的博文:http://www.cnblogs.com/liping13599168/archive/2011/07/17/2108734.html
DSC0007.png

  微软的企业库包含的模块非常多,比如缓存、数据存取、日志、IOC、AOP、异常处理等,由于现代企业往往都提供统一的日志管理系统和DAL系统,因此微软企业库仍然有价值的部分为AOP和IOC等部分,其实都是面向切面的应用(我们常用的WCF、MVC、WebAPI项目由于拦截器的存在,已经实现了AOP),当然在一部分做的最好的应该是Spring。
  接下来通过一个示例,来对AOP的应用,有一个基本的了解(通过Unity的Interception扩展)。





1 配置:
2 <configuration>
3 <configSections>
4 <section name="unityInterception" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
5 </configSections>
6 <unityInterception>
7 <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension
8 , Microsoft.Practices.Unity.InterceptionExtension.Configuration">
9 <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension
10 , Microsoft.Practices.Unity.Interception.Configuration" />
11 <container>
12 <extension type="Interception"/>
13 <register type="LipinInvoice.BL.AOPDemo, LipinInvoice.BL">
14 <interceptor type="TransparentProxyInterceptor" />
15 <policyInjection />
16 </register>
17 </container>
18 </sectionExtension>
19 </unityInterception>
20 </configuration>
21
22 拦截类
23 public class ExceptionHandler : ICallHandler
24 {
25 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
26 {
27 IMethodReturn methodReturn = getNext()(input, getNext);
28 return null;
29 }
30 public int Order { get; set; }
31 }
32
33 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Class)]
34 public class ExceptionHandlerAttribute : HandlerAttribute
35 {
36 public override ICallHandler CreateHandler(IUnityContainer container)
37 {
38 return new ExceptionHandler() { Order = this.Order };
39 }
40 }
View Code  EL6.0官方文档:http://files.cnblogs.com/files/wanliwang01/EL5.0.pdf
  EL5.0的详细配置,可以参考博主黄聪的系列教程:http://www.cnblogs.com/huangcong/archive/2010/06/08/1753988.html
  还可以参考仓储大叔的博文:http://www.cnblogs.com/lori/p/4088889.html
  WebAPI学习系列目录如下,欢迎您的阅读!
  快速入门系列--WebAPI--01基础
  快速入门系列--WebAPI--02进阶
  快速入门系列--WebAPI--03框架你值得拥有
  快速入门系列--WebAPI--04在老版本MVC4下的调整
  参考资料:




  • 蒋金楠. ASP.NET Web API 2框架揭秘[M]. 北京:电子工业出版社, 2014.


  • (美)加洛韦. ASP.NET MVC 5高级编程(第5版)[M]. 北京:清华大学出版社, 2015.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-344218-1-1.html 上篇帖子: 给Java新手的一些建议----Java知识点归纳(J2EE and Web 部分) 下篇帖子: 分布式系统事务一致性解决方案
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表