Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update)

[WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update)

作者头像
蒋金楠
发布于 2018-01-16 12:05:51
发布于 2018-01-16 12:05:51
8830
举报
文章被收录于专栏:大内老A大内老A

条件获取(Conditional Update)可以避免相同数据的重复传输,进而提高性能。条件更新(Conditional Update)用于解决资源并发操作问题。如果我们预先获取一个资源进行修改或者删除,条件更新检验帮助我们确认资源被获取出来到针对它的修改/删除操作被提交的这段时间内是否被其他人改动过。[源代码从这里下载]

一、HTTP对条件更新的支持

HTTP为条件更新提供了相应的报头,我们按照分析条件获取的方式来分析条件更新在HTTP请求/回复过程中的实现。客户端第一次向服务端发起针对某个资源的请求,服务端除了将资源数据作为回复消息主体返回之外,会将与资源关联并且能够可以用于对其进行对等性判断的某个值作为回复的ETag报头,这与条件获取时一致的。

客户端通过回复获得请求的资源和ETag报头值。对于资源修改操作,客户端直接针对获取的资源进行相应的修改,并将修改后的资源以HTTP请求的方式向服务端提交;对于资源删除操作,则可以指定被删除资源的唯一标识直接向服务端发送删除的请求。而之前获取的ETag指将会作为请求消息的If-Match报头。

服务端接收到资源修改/删除请求后先获取到现有的资源的ETag值,并将此值与请求消息的If-Match报头值进行比较。如果两者不一致,则表明试图被修改/删除的资源已经被修改了,在这种情况下会直接回复一个HTTP状态为“412 (Precondition Failed)”的空消息。条件更新同时支持针对PUT、POST和DELETE这三种方法的HTTP请求。

二、WebOperationContext与条件更新

服务端进行条件更新检测,以及客户端对If-Match请求报头的设置都可以通过当前的WebOperationContext来完成。如下面的代码片断所示,表示入栈请求上下文的IncomingWebRequestContext类型具有如下四个CheckConditionalUpdate方法重载用于进行添加更新检测。

代码语言:js
AI代码解释
复制
   1: public class IncomingWebRequestContext
   2: {
   3:     //其他成员
   4:     public void CheckConditionalUpdate(Guid entityTag);
   5:     public void CheckConditionalUpdate(int entityTag);
   6:     public void CheckConditionalUpdate(long entityTag);
   7:     public void CheckConditionalUpdate(string entityTag);
   8: }

实现在CheckConditionalUpdate方法中的条件更新检测具有这样的逻辑:对于HTTP方法为PUT的请求,如果If-Match报头值不为“*”,则直接抛出HTTP状态为PreconditionFailed的WebFaultException异常;对于HTTP方法为POST和DELETE的请求来说,如果If-Match报头值为“*”或者包含指定的entityTag则验证通过,否则同样则直接抛出HTTP状态为PreconditionFailed的WebFaultException异常。

表示出栈请求上下文的OutgoingWebRequestContext类型具有如下一个IfMatch属性,客户端可以通过该属性对请求消息的If-Match报头进行设置。

代码语言:js
AI代码解释
复制
   1: public class OutgoingWebRequestContext
   2: {
   3:     //其他成员
   4:     public string IfMatch { get; set; }
   5: }

三、实例演示:通过条件更新解决对相同资源的并发修改

我们同样通过对EmployeesService进行相应的改造来模拟如何通过添加更新实现对相同资源的并发操作问题,这次我们修改的是用于获取指定ID员工信息的Get操作和用于修改员工信息的Update操作。Get操作在返回与指定员工ID匹配的Employee对象之前我们将该对象的哈希码作为了回复消息的ETag报头(Employee类型重写了GetHashCode方法)。

代码语言:js
AI代码解释
复制
   1: public class EmployeesService : IEmployees
   2: {
   3:     //其他成员
   4:     public Employee Get(string id)
   5:     {
   6:         Employee employee = employees.FirstOrDefault(e => e.Id == id);
   7:         if (null == employee)
   8:         {
   9:             throw new WebFaultException(HttpStatusCode.NotFound);
  10:         }
  11:         WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
  12:         return employee;
  13:     }
  14:     public void Update(Employee employee)
  15:     {
  16:         var existing = employees.FirstOrDefault(e => e.Id == employee.Id);
  17:         if (null == existing)
  18:         {
  19:             throw new WebFaultException(HttpStatusCode.NotFound);
  20:         }
  21:         //模拟并发修改
  22:         existing.Name += Guid.NewGuid().ToString();
  23:  
  24:         WebOperationContext.Current.IncomingRequest.CheckConditionalUpdate(existing.GetHashCode());
  25:         employees.Remove(existing);            
  26:         employees.Add(employee);
  27:         WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
  28:  
  29:     }
  30: }

Update方法中我们通过手工修改相应员工的Name属性的方式来模拟针对相同员工信息的并发修改。在真正实施修改之前调用当前IncomingWebRequestContext的CheckConditionalUpdate方法进行条件更新检测,而作为参数传入的ETag值为代表目前员工的Employee对象的哈希码。方法的最后我们对回复消息的ETag报头作了更新。

我们通过手工创建HTTP请求的方式对上述的两个服务操作进行调用。如下面的代码片断所示,我们首先通过创建的HttpWebRequest对象调用Get操作获得ID为001的员工信息并将其打印出来。然后创建调用Update操作的HttpWebRequest,并对HTTP方法(POST)和内容类型(application/xml)进行了相应的设置。我们之前针对员工获取请求得到ETag报头和员工数据作为本次请求的If-Match报头和主体。如果调用GetResponse方法抛出WebException异常,并且其回复状态为PreconditionFailed,则表明试图修改的员工信息已被另一个用户修改过了,所以我么打印“服务端数据已发生变化”字样。

代码语言:js
AI代码解释
复制
   1: Uri address = new Uri("http://127.0.0.1:3721/employees/001");
   2: var request = (HttpWebRequest)HttpWebRequest.Create(address);
   3: request.Method = "GET";
   4: var response = (HttpWebResponse)request.GetResponse();
   5: string employee;
   6: using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
   7: {
   8:     employee = reader.ReadToEnd();
   9:     Console.WriteLine("获取员工信息:");
  10:     Console.WriteLine(employee + "\n");
  11: }
  12: try
  13: {
  14:     address = new Uri("http://127.0.0.1:3721/employees/");
  15:     request = (HttpWebRequest)HttpWebRequest.Create(address);
  16:     request.Method = "POST";
  17:     request.ContentType = "application/xml";
  18:     byte[] buffer = Encoding.UTF8.GetBytes(employee);
  19:     request.GetRequestStream().Write(Encoding.UTF8.GetBytes(employee), 0, buffer.Length);
  20:     request.Headers.Add(HttpRequestHeader.IfMatch, response.Headers[HttpResponseHeader.ETag]);
  21:     Console.WriteLine("修改员工信息:");
  22:     request.GetResponse();
  23: }
  24: catch (WebException ex)
  25: {
  26:     response = ex.Response as HttpWebResponse;
  27:     if (null == response)
  28:     {
  29:         throw;
  30:     }
  31:     if (response.StatusCode == HttpStatusCode.PreconditionFailed)
  32:     {
  33:         Console.WriteLine("服务端数据已发生变化");
  34:     }
  35:     else
  36:     {
  37:         throw;
  38:     }
  39: }

在服务成功寄宿的情况下调用这段程序会在控制台上输出如下的结果。由于并发错误的发生,员工信息其实并没有被真正修改。

代码语言:js
AI代码解释
复制
   1: 获取员工信息:
   2: <Employee xmlns="http://www.artech.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Department>开发部</Department><Grade>G7</Grade><Id>001</Id><Name>张三</Name></Employee>
   3:  
   4: 修改员工信息:
   5: 服务端数据已发生变化
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2012-02-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
超牛逼!这款轻量级 Linux 系统自动安全审计工具真强大
Lynis 是Unix/Linux等操作系统的一款安全审计工具,它可以发现基于Linux系统中的恶意软件和安全漏洞。Lynis是免费开源的服务器审计工具,一旦审计完成,我们可以审查结果、警告和建议,然后我们可以根据它实现我们的安全策略。它将显示一个报告,该报告可以被分成几个部分。
民工哥
2022/10/27
1.1K0
超牛逼!这款轻量级 Linux 系统自动安全审计工具真强大
如何在Ubuntu 16.04上使用Lynis执行安全审计
Lynis是一个基于主机的开源安全审计应用程序,可以评估Linux和其他类型UNIX操作系统的安全配置文件和状态。
黑色技术
2018/07/24
2.7K0
CentOS7下使用开源安全审计工具Lynis
Lynis是一款Linux系统的安全审计以及加固工具,能够进行深层次的安全扫描,其目的是检测潜在的时间并对未来的系统加固提供建议。
yuanfan2012
2020/11/26
1.8K0
如何有效阻止 90% 服务器攻击
很多服务器时不时地被黑掉。因此,我决定编写一个简短的教程,向您展示如何轻松地保护您的Linux服务器。
网罗开发
2021/02/26
1.7K0
Linux系统常用基础命令
touch -t 0712250000 file1 修改一个文件或目录的时间戳 - (YYMMDDhhmm)
用户8418197
2021/03/27
1.5K0
安全审计报告问题:安全审计报告生成失败,无法分析
是山河呀
2025/02/09
1860
如何在 Centos8 中安装 Lynis审计工具
Lynis 还附带一些审计配置文件,该文件确定或说明应如何执行安全审计。配置文件位于 /etc/lynis 目录中。
用户9239730
2021/11/29
3860
安全审计工具选择问题:安全审计工具选择不当,无法满足需求
是山河呀
2025/02/09
1420
20个可能你不知道Linux网路工具
如果要在你的系统上监控网络,那么使用命令行工具是非常实用的,并且对于 Linux 用户来说,有着许许多多现成的工具可以使用,如: nethogs, ntopng, nload, iftop, iptraf, bmon, slurm, tcptrack, cbm, netwatch, collectl, trafshow, cacti, etherape, ipband, jnettop, netspeed 以及 speedometer。 鉴于世上有着许多的 Linux 专家和开发者,显然还存在其他的网络
小小科
2018/05/04
1.7K0
20个可能你不知道Linux网路工具
lynis安装和扫描Linux的安全漏洞
  今天客户的服务器出了点问题需要排查具体的原因,在德国朋友的建议下用Lynis进行扫描,Lynis是Linux系统中的审计工具,能够对Linux系统的安全进行检测,在对系统进行扫描检测后,会生成安全报告。如何安装呢?随ytkah一起来看看
ytkah
2019/11/26
1.3K0
你知道吗,Artifactory还可以管理SUSELinux系统的依赖
提到SUSE系统大家应该都用过,尤其是在金融领域。大部分都是使用SUSELinux系统。当SUSE系统缺少组件时,安装也是相当的麻烦。
JFrog杰蛙科技
2020/12/04
8290
你知道吗,Artifactory还可以管理SUSELinux系统的依赖
Airgorah:一款功能强大的WiFi安全审计工具
Airgorah是一款功能强大的WiFi安全审计工具,该工具可以轻松发现和识别连接到无线接入点的客户端,并对特定的客户端执行身份验证攻击测试,捕捉WPA握手包,并尝试破解接入点的密码。在该工具的帮助下,广大研究人员可以对无线接入点和客户端的安全性进行检测和验证。
FB客服
2024/04/01
2970
Airgorah:一款功能强大的WiFi安全审计工具
Linux系统中安装及管理程序的最佳实践与教程
hide
2025/04/27
1800
Linux系统中安装及管理程序的最佳实践与教程
浅谈Linux下dpkg、apt-get、yum和rpm命令的区别
小编最近一直进行国产化输入法测试,国产化系统基本上都是基于Linux搭建来的,不同系统安装输入法的命令也是不一样;比如uos(统信)系统用dpkg或者apt-get来安装,而中标麒麟则是用yum或者rpm来安装,那么它们到底有什么区别那?
用户5521279
2020/12/11
7.9K0
浅谈Linux下dpkg、apt-get、yum和rpm命令的区别
系统漏洞:系统存在已知的安全漏洞
使用强制访问控制系统(如 SELinux 或 AppArmor)来增强系统安全性。
是山河呀
2025/02/06
1460
安全补丁管理
使用审计工具(如 auditd)记录系统活动,确保补丁管理过程的透明性和可追溯性。
是山河呀
2025/02/03
1310
安全审计问题:安全审计工具使用不当,导致审计数据不准确
示例:编辑 /etc/logrotate.d/audit 文件,设置日志轮转策略:
是山河呀
2025/02/06
3380
5 种 Linux 安装包管理工具中文手册!抓紧看,别再说不会了,丢人。。。
包管理系统除了安装软件外,它还提供了工具来更新已经安装的包。包存储库有助于确保你的系统中使用的代码是经过审查的,并且软件的安装版本已经得到了开发人员和包维护人员的认可。
民工哥
2022/10/27
1.2K0
5 种 Linux 安装包管理工具中文手册!抓紧看,别再说不会了,丢人。。。
Linux软件包管理:yum和apt比较
📌 猫头虎博主在此! 在Linux世界中,软件包管理是一项基本技能。不同的发行版使用不同的包管理工具,而yum和apt是其中最受欢迎的两个。这篇文章将为你详细解析这两个强大的工具,帮助你更好地理解它们的优势和适用场景。当然, 我在文章中融入了一些热门关键词,确保每一位Linux爱好者都能找到这篇宝藏文章。与我一同,探索Linux软件包管理的奥秘!
猫头虎
2024/04/09
7040
【Linux探索学习】第六弹——Linux的工具(一):Ubuntu系统下的软件包管理器
注意:本文是所讲解的内容是在Ubuntu系统下进行操作的,centos系统下相关操作略有不同
GG Bond1
2024/10/19
2410
【Linux探索学习】第六弹——Linux的工具(一):Ubuntu系统下的软件包管理器
推荐阅读
相关推荐
超牛逼!这款轻量级 Linux 系统自动安全审计工具真强大
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档