基于REST的Web服务基础

基于REST的Web服务基础 代表性状态传输 (Representational State Transfer,REST) 在Web领域已经得到了广泛的接受,是基于SOAP和Web服务描述语言 (Web Services Description Language,WSDL) 的Web服务的更为简单的替代方法。接口设计方面这一转变的关键证据是主流Web 2.0服务提供者 (包括Yahoo、Google和Facebook) 对REST的采用,这些提供者弃用或放弃了基于SOAP和WSDL的接口,而采用了更易于使用、面向资源的模型来公开其服务。在本文中,Alex Rodriguez将向您介绍REST的基本原理。 基础 REST定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的Web服务,包括使用不同语言编写的客户端如何通过HTTP处理和传输资源状态。如果考虑使用它的Web服务的数量,REST近年来已经成为最主要的Web服务设计模型。事实上,REST对Web的影响非常大,由于其使用相当方便,已经普遍地取代了基于SOAP和WSDL的接口设计。 REST这个概念于2000年由Roy Fielding在就读加州大学欧文分校期间在学术论文"Architectural Styles and the Design of Network-based Software Architectures"首次提出,他的论文中对使用Web服务作为分布式计算平台的一系列软件体系结构原则进行了分析,而其中提出的REST概念并没有获得现在这么多关注。多年以后的今天,REST的主要框架已经开始出现,但仍然在开发中,因为它已经被广泛接纳到各个平台中,例如通过JSR-311成为了Java? 6不可或缺的部分。 本文认为,对于今天正在吸引如此多注意力的最纯粹形式的REST Web服务,其具体实现应该遵循四个基本设计原则: ·显式地使用HTTP方法。 ·无状态。 ·公开目录结构式的URI。 ·传输XML、JavaScript Object Notation(JSON),或同时传输这两者。 下面几个部分将详述这四个原则,并提供技术原理解释,说明为什么这些原则对REST Web服务设计人员非常重要。 显式地使用HTTP方法 基于REST的Web服务的主要特征之一是以遵循RFC 2616定义的协议的方式显式使用HTTP方法。例如,HTTP GET被定义为数据产生方法,旨在由客户端应用程序用于检索资源以从Web服务器获取数据,或者执行某个查询并预期Web服务器将查找某一组匹配资源然后使用该资源进行响应。 REST要求开发人员显式地使用HTTP方法,并且使用方式与协议定义一致。这个基本REST设计原则建立了创建、读取、更新和删除 (create, read, update, and delete,CRUD) 操作与HTTP方法之间的一对一映射。根据此映射: ·若要在服务器上创建资源,应该使用POST方法。 ·若要检索某个资源,应该使用GET方法。 ·若要更改资源状态或对其进行更新,应该使用PUT方法。 ·若要删除某个资源,应该使用DELETE方法。 许多Web API中所固有的一个令人遗憾的设计缺陷在于将HTTP方法用于非预期用途。例如,HTTP GET请求中的请求URI通常标识一个特定的资源。或者,请求URI中的查询字符串包括一组参数,这些参数定义服务器用于查找一组匹配资源的搜索条件。至少,HTTP/1.1 RFC是这样描述GET方法的。但是在许多情况下,不优雅的Web API使用HTTP GET来触发服务器上的事务性操作——例如,向数据库添加记录。在这些情况下,GET请求URI属于不正确使用,或者至少不是以基于REST的方式使用。如果Web API使用GET调用远程过程,则应该类似如下: GET /adduser?name=Robert HTTP/1.1 这不是非常优雅的设计,因为上面的Web方法支持通过HTTP GET进行状态更改操作。换句话说,该HTTP GET请求具有副作用。如果处理成功,则该请求的结果是向基础数据存储区添加一个新用户——在此例中为Robert。这里的问题主要在语义上。Web服务器旨在通过检索与请求URI中的路径 (或查询条件) 匹配的资源,并在响应中返回这些资源或其表示形式,从而响应HTTP GET请求,而不是向数据库添加记录。从该协议方法的预期用途的角度看,然后再从与HTTP/1.1兼容的Web服务器的角度看,以这种方式使用GET是不一致的。 除了语义之外,GET的其他问题在于,为了触发数据库中的记录的删除、修改或添加,或者以某种方式更改服务器端状态,它请求Web缓存工具 (爬网程序) 和搜索引擎简单地通过对某个链接进行爬网处理,从而意外地做出服务器端更改。克服此常见问题的简单方法是将请求URI上的参数名称和值转移到XML标记中。这样产生的标记是要创建的实体的XML表示形式,可以在HTTP POST的正文中进行发送,此HTTP POST的请求URI是该实体的预期父实体 (请参见清单1和2) : ...

2012-11-08 · 2 min · 238 words · lcf

Web 服务编程,REST 与 SOAP的比较

Web 服务编程,REST 与 SOAP的比较 REST 简介 在开始我们的正式讨论之前,让我们简单看一下 REST 的定义。 REST (Representational State Transfer) 是 Roy Fielding 提出的一个描述互联系统架构风格的名词。为什么称为 REST?Web 本质上由各种各样的资源组成,资源由 URI 唯一标识。浏览器 (或者任何其它类似于浏览器的应用程序) 将展示出该资源的一种表现方式,或者一种表现状态。如果用户在该页面中定向到指向其它资源的链接,则将访问该资源,并表现出它的状态。这意味着客户端应用程序随着每个资源表现状态的不同而发生状态转移,也即所谓 REST。 关于 REST 本身,本文就不再这里过多地讨论,读者可以参考 developerWorks 上其它介绍 REST 的文章。本文的重点在于通过 REST 与 SOAP Web 服务的对比,帮助读者更深刻理解 REST 架构风格的特点,优势。 应用场景介绍 (在线用户管理) 本文将借助于一个应用场景,通过基于 REST 和 SOAP Web 服务的不同实现,来对两者进行对比。该应用场景的业务逻辑会尽量保持简单且易于理解,以有助于把我们的重心放在 REST 和 SOAP Web 服务技术特质对比上。 需求描述 这是一个在线的用户管理模块,负责用户信息的创建,修改,删除,查询。用户的信息主要包括: 用户名 (唯一标志在系统中的用户) 头衔 公司 EMAIL 描述 需求用例图如下: 图 1. 需求用例图 如图 1 所示,客户端 1 (Client1) 与客户端 2 (Client2) 对于信息的存取具有不同的权限,客户端 1 可以执行所有的操作,而客户端 2 只被允许执行用户查询 (Query User) 与用户列表查询 (Query User List) 。关于这一点,我们在对 REST Web 服务与 SOAP Web 服务安全控制对比时会具体谈到。下面我们将分别向您介绍如何使用 REST 和 SOAP 架构实现 Web 服务。 ...

2012-11-07 · 6 min · 1212 words · lcf

REST是什么?

REST是什么? 概述 REST是英文Representational State Transfer的缩写,中文翻译: 表述性状态转移。 他是由Roy Thomas Fielding博士在他的论文 《Architectural Styles and the Design of Network-based Software Architectures》中提出的一个术语。 REST本身只是为分布式超媒体系统设计的一种架构风格,而不是标准。 基于Web的架构,实际上就是各种规范的集合,这些规范共同组成了Web架构。比如Http协议,比如客户端服务器模式,这些都是规范。每当我们在原有规范的基础上增加新的规范, 就会形成新的架构。而REST正是这样一种架构,他结合了一系列的规范,而形成了一种新的基于Web的架构风格。 传统的Web应用大都是B/S架构,它包括了如下一些规范: 客户-服务器 这种规范的提出,改善了用户接口跨多个平台的可移植性,并且通过简化服务器组件,改善了系统的可伸缩性。最为关键的是通过分离用户接口和数据存储这两个关注点,使得不同用户终端享受相同数据成为了可能。 无状态性 无状态性是在客户-服务器约束的基础上添加的又一层规范。他要求通信必须在本质上是无状态的,即从客户到服务器的每个request都必须包含理解该 request所必须的所有信息。这个规范改善了系统的可见性 (无状态性使得客户端和服务器端不必保存对方的详细信息,服务器只需要处理当前 request,而不必了解所有的request历史) ,可靠性 (无状态性减少了服务器从局部错误中恢复的任务量) ,可伸缩性 (无状态性使得服务器端可以很容易的释放资源,因为服务器端不必在多个request中保存状态) 。同时,这种规范的缺点也是显而易见得,由于不能将状态数据保存在服务器上的共享上下文中,因此增加了在一系列request中发送重复数据的开销,严重的降低了效率。 3.缓存 为了改善无状态性带来的网络的低效性,我们填加了缓存约束。缓存约束允许隐式或显式地标记一个response中的数据,这样就赋予了客户端缓存 response数据的功能,这样就可以为以后的request共用缓存的数据,部分或全部的消除一部分交互,增加了网络的效率。但是用于客户端缓存了信息,也就同时增加了客户端与服务器数据不一致的可能,从而降低了可靠性。 B/S架构的优点是其部署非常方便,但在用户体验方面却不是很理想。为了改善这种情况, 我们引入了REST。 REST在原有的架构上增加了三个新规范: 统一接口,分层系统和按需代码。 1.统一接口 REST 架构风格的核心特征就是强调组件之间有一个统一的接口,这表现在REST世界里,网络上所有的事物都被抽象为资源,而REST就是通过通用的链接器接口对资源进行操作。这样设计的好处是保证系统提供的服务都是解耦的,极大的简化了系统,从而改善了系统的交互性和可重用性。并且REST针对Web的常见情况做了优化,使得REST接口被设计为可以高效的转移大粒度的超媒体数据,这也就导致了REST接口对其它的架构并不是最优的。 2.分层系统 分层系统规则的加入提高了各种层次之间的独立性,为整个系统的复杂性设置了边界,通过封装遗留的服务,使新的服务器免受遗留客户端的影响,这也就提高了系统的可伸缩性。 3.按需代码 REST允许对客户端功能进行扩展。比如,通过下载并执行applet或脚本形式的代码,来扩展客户端功能。但这在改善系统可扩展性的同时,也降低了可见性。所以它只是REST的一个可选的约束。 REST的设计准则 REST架构是针对Web应用而设计的,其目的是为了降低开发的复杂性,提高系统的可伸缩性。REST提出了如下设计准则: 网络上的所有事物都被抽象为资源 (resource) ; 每个资源对应一个唯一的资源标识符 (resource identifier) ; 3.通过通用的连接器接口 (generic connector interface) 对资源进行操作; 对资源的各种操作不会改变资源标识符; 所有的操作都是无状态的 (stateless) 。 REST中的资源所指的不是数据,而是数据和表现形式的组合,比如"最新访问的10位会员"和"最活跃的10为会员"在数据上可能有重叠或者完全相同,而由于他们的表现形式不同,所以被归为不同的资源,这也就是为什么REST的全名是Representational State Transfer的原因。资源标识符就是URI(Uniform Resource Identifier),不管是图片,Word还是视频文件,甚至只是一种虚拟的服务,也不管你是xml格式,txt文件格式还是其它文件格式,全部通过 URI对资源进行唯一的标识。 REST是基于Http协议的,任何对资源的操作行为都是通过Http协议来实现。以往的Web开发大多数用的都是Http协议中的GET和 POST方法,对其他方法很少使用,这实际上是因为对Http协议认识片面的理解造成的。Http不仅仅是一个简单的运载数据的协议,而是一个具有丰富内涵的网络软件的协议。他不仅仅能对互联网资源进行唯一定位,而且还能告诉我们如何对该资源进行操作。Http把对一个资源的操作限制在4个方法以内: GET, POST,PUT和DELETE,这正是对资源CRUD操作的实现。由于资源和URI是一一对应的,执行这些操作的时候URI是没有变化的,这和以往的 Web开发有很大的区别。正由于这一点,极大的简化了Web开发,也使得URI可以被设计成更为直观的反映资源的结构,这种URI的设计被称作 RESTful的URI。这位开发人员引入了一种新的思维方式: 通过URL来设计系统结构。当然了,这种设计方式对一些特定情况也是不适用的,也就是说不是所有的URI都可以RESTful的。 ...

2012-11-07 · 2 min · 425 words · lcf

REST Web Service带给我们什么

REST Web Service带给我们什么 Web Service的协议最近几年一直在发生转变。Web Servcie的最大优势是能在一个操作系统不同的各个系统之间架起沟通的桥梁,早期的 Web Service一般都是以SOAP协议传输。仔细学习和研究过SOAP协议的同学知道,SOAP协议是一个很完备的自解释协议,对Service、Interface、Method和Parameter的描述都非常详细,甚至还制定了一个WSDL的XSD来,在VS中,只要导入Web Service的WSDL,VS就可以自动生成存根代理代码,你只需调用它便可以调用这些SOAP的Web Service了。 SOAP 的Web Service看起来是很完美的解决方案,但是往往看起来完美的东西,用起来并不完美。 SOAP就是如此,随着Web Service 应用在企业级软件的运用,SOAP的缺陷迅速开始暴露出来。 首先,SOAP协议是在是太复杂,很少有人能完全看懂根据SOAP协议生成的数据 (其实这本来设计,就是给机器看的,哪能照顾你大爷,呵呵哦!) 。我本人是很厌烦看SOAP的数据,一看头就大,特别是SOAP头和尾。 其次,太复杂还不是SOAP协议最大的缺陷。大不了我用下解释SOAP的工具,现在VS也提供此类工具用来查看SOAP类型的数据。但是恰恰是这个缺陷造就了SOAP另一个很致命的缺陷。由于SOAP为了是每个调用的参数和返回值都可以独立解释,为此,需要在每次调用中加入大量的XML复杂信息,来解释这些数据。例如为了解释一个XML的节点是STRING,于是<datatype=“string”>被按在了一个XML节点上,其实这是没有必要的。因为,往往程序员在消费这个service的时候,已经知道了返回的数据类型,比如你在调用GetAge的时候,返回的XML肯定是int型。所以,一般一个SOAP的调用,一个来回少则数K,多则数M的,甚至数G的数据,而在这些数据中,真正有效的数据很少,根据统计,有效数据仅占全部数据的5%,甚至更少。对于海量数据的企业应用来说,大量的用户对海量数据的存储,如果用SOAP来进行数据传输,那简直就是灾难!!! 另外,调式SOAP的WEB SERVICE也是很费时费力的,SOAP数据的难阅读性,直接增加了调式的难度。 所以,在REST之前,很多的企业应用还是用DCOM,甚至是自定义XML来进行数据传输。 那有没有很好协议的Web Service呢!?。。。现在。。。有了,REST的Web Service就是。 REST的Web Service彻底摒弃了SOAP协议。它的数据格式简单,一般都直接采用对象XML序列化的数据作为返回结果。这样就极大的降低了数据传输量,提高了效率。而且这种XML数据可以直接用IE打开,很容易阅读理解。 随着WCF和VS 2008的发布,MS首次加入了对架构REST Web Service的支持,虽然还很不完全,但是有总比没有好!现在,你只需: 1,添加Data Contract 2,添加Interface并附给URL 3,设置CLASS 4,附加到IIS或者CONSOLE程序 你就可以创建一个REST Web Service。然后通过IE,在地址栏输入Interface的URL,就想访问网页一样调用你的Web Service,返回的数据就通过IE直接显示,这够直观了吧!? 现在,很多大型公司的Public Web Service也都已经REST化,比如GOOGLE所有的Web Service都是REST的,MS也已经采用REST来优化他的public WebService。很多"云计算"的提供商,如AMASON,他的"云服务" (呵呵,暂且如此叫吧) ,也是REST的。国内很多知名公司在看到REST的巨大优势后也纷纷开始采用REST的Web Service来提高他们的效率,如上海深睿科技的销售管理软件易卖通采用REST WebService,极大的提高了系统的速度和效率,使得传统的供销村管理软件架构在网络和"云"内成为可能。 总之,REST带给我们的是,一种更好、更简单、更有效率的Web Service,同时,可能将来成为"云计算"的基础通讯协议。

2012-11-07 · 1 min · 52 words · lcf

Hugo

Hugo Hugo 是一款开源的使用 go 语言写的静态网站生成器,很适合数据量不大的个人博客使用 为何要使用静态网站生成器 (Static Site Generators) ? 不同于 WordPress 这类博客平台 (以及其他众多流行的CMS内容管理系统) 在服务器端执行PHP等语言的动态框架、访问SQL数据库并动态产生Web页面的工作方式,静态网站生成器的原理十分简单: 将所有的页面、布局和帖子集合在一起,预先生成静态的站点。对于动态内容并非必要的站点——例如个人博客,静态网站生成器这样做有几个明显的优势 快速访问和弱服务器需求 静态HTML页面的载入速度理所当然地更快——因为它无需在服务器端执行任何代码。同时,这还大大地减轻了服务器的压力。 高安全性 基于与上述相同的理由,静态页面有着与生俱来的安全性。不像WordPress或者其他任何动态的框架,静态站点本身并不存在安全漏洞的问题。 版本控制 你无需通过WordPress来维护一整个复杂的数据库——静态站点的内容完全仅由文件系统中独立的目录和文件构成,这意味着你不但可以使用Shell、grep、sed、awk这些传统的Unix工具对它们执行操作和维护,更可以使用 Git 这样的分布式版本控制系统来管理它们,并且享受版本控制所带来的一切好处,如同维护任何软件项目的源代码库一样。你甚至可以重新生成以前任意时间点的整个网站! 简单部署 一旦静态网站生成以后,任何Web服务器都能够轻易地部署静态站点,而无须在服务器端安装配置其他任何多余的东西。你所需要做的仅仅是通过git、rsync甚至ftp简单地上传文件到你的托管服务器。相比之下,WordPress博客的维护显得复杂得多,你可能需要在你的开发服务器和托管服务器上安装、配置一整套LAMP+WordPress平台,并经常性地升级版本和维护。这是个繁重的技术活。 文本编辑器和自由格式书写 也许你不这么认为,但是作为一个hacker而言,在浏览器中一个300x300的文本区里码字写博客并非一件很酷的事情——如果你使用Hugo这样的静态网站生成器,你就可以用你喜欢的任何文本编辑器 (vi、emacs……) ,用你习惯的标记语言以书写文本文件的方式来直接写博客文章 (就好像你平常写代码一样) ,避免了使用那些简陋和功能有限的Web界面。 compile # 安装 hugo pacman -S hugo # cd 到hugo工程目录 cd /path/to/markdown/doc/home # 在本地启动一个服务,测试一下,hugo会检测文档变化自动编译 hugo server # 开个浏览器看一下页面 google-chrome-stable http://localhost:1313/ hugo, plantuml https://mogeko.me/posts/zh-cn/083/

2012-11-06 · 1 min · 55 words · -

java JVM 内存问题 调查,调优

java JVM 内存问题 调查,调优 https://my.oschina.net/u/3345762/blog/1784199 https://my.oschina.net/u/3345762/blog/1644973 http://www.infoq.com/cn/articles/Troubleshooting-Java-Memory-Issues?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global http://www.importnew.com/14933.html http://lovestblog.cn/blog/2015/08/21/rssxmx/ # set jdk path export PATH=/usr/java/default/bin/:$PATH # list java process jcmd -l # show jcmd command jcmd PID help #heap dump jcmd PID GC.heap_dump /root/dump.hprof Eclipse Memory Analyzer Eclipse Memory Analyzer NMT, pmap Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss] init: represents the initial amount of memory (in bytes) that the Java virtual machine requests from the operating system for memory management during startup. The Java virtual machine may request additional memory from the operating system and may also release memory to the system over time. The value of init may be undefined. ...

2012-11-06 · 4 min · 807 words · lcf

Smalltalk

Smalltalk Smalltalk被公认为历史上第二个面向对象的程序设计语言和第一个真正的集成开发环境 (IDE)。由Alan Kay,Dan Ingalls,Ted Kaehler,Adele Goldberg等于70年代初在Xerox PARC开发。Smalltalk对其它众多的程序设计语言的产生起到了极大的推动作用,主要有: Objective-C,Actor, Java 和Ruby等。90年代的许多软件开发思想得利于Smalltalk,例如Design Patterns, Extreme Programming(XP)和Refactoring等。 Smalltalk和许多程序设计语言不同,它不仅仅是一门语言。 一种面向对象的程序设计语言: 它是一种面向对象的语言,包含语言的语法和语义。一些编译器可以通过 Smalltalk 源程序产生可执行文件。这些编译器通常产生一种能在虚拟机上运行的二进制代码。Smalltalk语言本身非常精炼。 一种程序设计环境: 这里指的是一种提供许多 对象 的系统,而不是某种特殊的开发环境。和许多语言不同(包括C++),Smalltalk附带有一个巨大的、相当标准的类库。这些 类 使得开发Smalltalk程序的效率非常高。在其它语言 (例如 Ada , C 和 Pascal ) 中通常被作为语言的一部分的功能 (例如条件判断,循环等),在Smalltalk由特定的类提供。 **一个应用开发环境(ADE):**由于Smalltalk的历史原因,它具有一个非常优秀的高度集成、开放的应用开发环境。由于开发环境中的浏览器、监视器以及调试器都由同样的源程序衍生出来的,不同的版本之间也具有相当好的兼容性。此外,这些工具的源程序都可以在ADE直接存取。

2012-11-04 · 1 min · 35 words · -

线框图

线框图 线框图(Wireframe)是软件或者网站设计过程中非常重要的一个环节。线框图是整合在结构层的全部三种要素的方法: 通过安排和选择界面元素来整合界面设计;通过识别和定义核心导航系统来整合导航设计;通过放置和排列信息组成部分的优先级来整合信息设计。通过把这三者放到一个文档中,线框图可以确定一个建立在基本概念结构上的架构,同时指出了视觉设计应该前进的方向。 其实对于更小或更简单的网站来说,一个线框图就足够作为所有即将建立的页面的模板。对于大多数项目来说,无论如何,都需要用多个线框图来传达复杂的预期结果。不过,你不需要为网站的每一个页面都准备一个线框图。正如结构设计流程允许我们把内容要素总结成各个种类一样,一个数量相对较少的标准页面类型将在绘制线框图的过程中慢慢浮现。 线框图在正式建立网站的视觉设计的流程中,是必要的第一步,但是几乎每一个参与这个开发过程的人都会在一些任务点中使用它。负责战略层、范围层和结构层的设计者可以借助线框图来保证最终产品能满足他们的期望。真正负责建设这个网站的人,则使用线框图来回答关于网站应该如何运作的问题。 随着用户体验领域的不断成熟和发展,线框图的责任有时还成为企业内部某种口水战的主题。一些网站研发团队很鲜明地把这部分工作分成两个部分,由两个独立的角色 (有时候是整个部门) “信息架构师"和"设计师"来承担。

2012-11-03 · 1 min · 8 words · -

悲观锁和乐观锁

悲观锁和乐观锁 为什么需要锁 (并发控制) ? 在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。这就是著名的并发性问题。 典型的冲突有: 丢失更新: 一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如: 用户A把值从 6 改为 2, 用户B把值从 2 改为 6, 则用户 A 丢失了他的更新。 脏读: 当一个事务读取其它完成一半事务的记录时, 就会发生脏读取。例如: 用户 A, B 看到的值都是 6, 用户 B 把值改为 2, 用户 A 读到的值仍为 6。 为了解决这些并发带来的问题。 我们需要引入并发控制机制。 并发控制机制 最常用的处理多用户并发访问的方法是加锁。当一个用户锁住数据库中的某个对象时,其他用户就不能再访问该对象。加锁对并发访问的影响体现在锁的粒度上。比如,放在一个表上的锁限制对整个表的并发访问;放在数据页上的锁限制了对整个数据页的访问;放在行上的锁只限制对该行的并发访问。可见行锁粒度最小,并发访问最好,页锁粒度最大,表锁介于2者之间。 悲观锁 悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。 假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。悲观锁假定其他用户企图访问或者改变你正在访问、更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁。悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长,这样可能会长时间的限制其他用户的访问,也就是说悲观锁的并发访问性不好。 乐观锁 乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据: 如果别人修改了数据则放弃操作,否则执行操作。 假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读的问题。乐观锁则认为其他用户企图改变你正在更改的对象的概率是很小的,因此乐观锁直到你准备提交所作的更改时才将对象锁住,当你读取以及改变该对象时并不加锁。可见乐观锁加锁的时间要比悲观锁短,乐观锁可以用较大的锁粒度获得较好的并发访问性能。但是如果第二个用户恰好在第一个用户提交更改之前读取了该对象,那么当他完成了自己的更改进行提交时,数据库就会发现该对象已经变化了,这样,第二个用户不得不重新读取该对象并作出更改。这说明在乐观锁环境中,会增加并发用户读取对象的次数。 从数据库厂商的角度看,使用乐观的页锁是比较好的,尤其在影响很多行的批量操作中可以放比较少的锁,从而降低对资源的需求提高数据库的性能。再考虑聚集索引。在数据库中记录是按照聚集索引的物理顺序存放的。如果使用页锁,当两个用户同时访问更改位于同一数据页上的相邻两行时,其中一个用户必须等待另一个用户释放锁,这会明显地降低系统的性能。interbase和大多数关系数据库一样,采用的是乐观锁,而且读锁是共享的,写锁是排他的。可以在一个读锁上再放置读锁,但不能再放置写锁;你不能在写锁上再放置任何锁。锁是目前解决多用户并发访问的有效手段。 乐观锁应用 使用自增长的整数表示数据版本号。更新时检查版本号是否一致,比如数据库中数据版本为6,更新提交时version=6+1,使用该version值(=7)与数据库version+1(=7)作比较,如果相等,则可以更新,如果不等则有可能其他程序已更新该记录,所以返回错误。 使用时间戳来实现. 注: 对于以上两种方式,Hibernate自带实现方式: 在使用乐观锁的字段前加 annotation: @Version, Hibernate在更新时自动校验该字段。 java中的乐观锁基本都是通过CAS操作实现的 悲观锁应用 结论 在实际生产环境里边,如果并发量不大且不允许脏读,可以使用悲观锁解决并发问题;但如果系统的并发非常大的话,悲观锁定会带来非常大的性能问题,所以我们就要选择乐观锁定的方法. 参考文档 [1]Concurrent Control http://en.wikipedia.org/wiki/Concurrency_control [2] Oracle的悲观锁和乐观锁http://space.itpub.net/12158104/viewspace-374745 [3] timestamp应用——乐观锁和悲观锁【转】http://hi.baidu.com/piaokes/blog/item/9b0c6854e4909050564e00b3.html 事务隔离 https://www.cnblogs.com/kismetv/p/10787228.html http://www.cnblogs.com/Bob-FD/p/3352216.html

2012-11-01 · 1 min · 71 words · lcf

URL中#号(井号)的作用

‘URL中#号(井号)的作用’ a href="#" 这表示一个空链接 这是一个空连接 href="#" #可以改成你要连接的地址 点击就链接到你的网址 这里可以随便你放什么字 这是html超链接格式,href是说超链接的目标,#就是自身 1. 井号在URL中指定的是页面中的一个位置 井号作为页面定位符出现在URL中,比如: http://www.httpwatch.com/features.htm#print ,此URL表示在页面features.htm中print的位置。浏览器读取这个URL后,会自动将print位置滚动至可视区域。 2.井号后面的数据不会发送到HTTP请求中 当时使用类似HttpWatch工具时,你是无法在Http请求中找到井号后面的参数的,原因是井号后面的参数是针对浏览器起作用的而不是服务器端。 3. 任务位于井号后面的字符都是位置标识符 不管第一个井号后面跟的是什么参数,只要是在井号后面的参数一律看成是位置标识符。 比如这样一个链接 (http://example.com/?color=#ffff&shape=circle) ,后面跟的参数是颜色和形状,但是服务器却并不能理解URL中的含义。服务器接收到的只是: http://example.com/?color= 4. 改变井号后面的参数不会触发页面的重新加载但是会留下一个历史记录 仅改变井号后面的内容,只会使浏览器滚动到相应的位置,并不会重现加载页面。 比如从_http://www.httpwatch.com/features.htm#filter_到_http://www.httpwatch.com/features.htm#print_,浏览器并不会去重新请求页面,但是此操作会在浏览器的历史记录中添加一次记录,即你可以通过返回按钮回答上次的位置。这个特性对Ajax来说特别的有用,可以通过设置不同井号值,来表示不同的访问状态,并返回不同的内容给用户。 (注: 在IE6和IE7下井号的改变不会增加历史记录。) 5、可以通过javascript使用window.location.hash来改变井号后面的值 window.location.hash这个属性可以对URL中的井号参数进行修改,基于这个原理,我们可以在不重载页面的前提下创造一天新的访问记录。如标记框架页面当前的页面: 除此之外,HTML 5新增的onhashchange事件,当#值发生变化时,就会触发这个事件。 6. Googlebot对井号的过滤机制 默认情况下Google在索引页面的时候会忽略井号后面的参数,同时也不会去执行页面中的javascript。然而谷歌为了支持对Ajax生成内容的索引,定义了如果在URL中使用"#!",则Google会自动将其后面的内容转成查询字符串_escaped_fragment_的值。 比如最新的twitter URL: http://twitter.com/#!/username,Google会自动请求_http://twitter.com/?escaped_fragment=/username_来获取Ajax内容。 另外可以用#结合?等元素来标记流量来源,比如区分竞价和自然流量等,这个就很给力了. http://blog.163.com/seo_luofeng/blog/static/17657502420120913641444/

2012-10-31 · 1 min · 42 words · -

javascript Location

javascript Location location.href 返回整个当前url,若对其赋值: location.href=“http://www.highya.com” 则跳转其url location.host 返回域名和端口号,如: www.highya.com:80 lcation.hostname 返回域名 location.port 返回端口 location.pathname 返回域名后第一个斜框后的字符串 location.hash 跳到本页的某个锚 location.search 取url?后的部分 location对象: location提供了关于当前打开窗口或者特定框架的url信息。一个多框架的窗口对象在location属性显示的是父窗口的URL,每个框架也有一个与之相伴的location对象。 hash属性: hash标注是一个url很好的习惯用法,它指定浏览器到一个位于文档中的anchor位置,相当于一个书签儿。 host属性: 描述渔歌url的主机名和端口,只有端口号是url的一个明确部分时,值中才包括端口号。 hostname属性: 一个典型的url的主机名是网络上服务器的名字,该网络存储有你的浏览器上可以查看的文档。对大多数Web站点来说,服务器名不仅包括域名,也包括www前缀,如果端口号是在url中特有的话,主机名并不包括,而是包括在host属性中。 href属性: 该属性提供一个指定窗口对象的整个url的字符串。 pathname属性: url的路径名部分由与服务器root (根) 卷相关的目录结构组成。根不是目录的一部分,如果url的路径是通向根目录中的一个文件,那么location.pathname属性就是 (/) 。 port属性: 端口号很少用到。当指向一个没有赋给域名的的站点的url中,可以用location.port属性获取该值,如果从一个url获取值并想用那个组建创建一个url,一定要包括服务器IP地址和段口号,IP地址和段口号之间用 (:) 分界。 protocol属性: 包括协议名,且后面紧跟着 (:) 分节目。 assign方法: assign(“url”)通过这个方法可以实现把一个新的url赋给location对象。当然你也可以采用直接赋值的方法来实现,或者location.href来导航到一个新的网页。采用assign的方法会使代码易维护。 reload方法: 这个方法可以把浏览器可能保存在内存中的元素 (在一段记录中) 的文档设置全部忽略掉,重新打开该文档,和浏览器上的刷新可不一样。它的效果好像是你选择了file菜单open file一样。当然如果你不想这样,不想这么做,有一个和这个方法比较类似的方法,就是history.go () 方法。 replace方法: 当用户从当前网页,跳转到别的网页,有时候是不是想让不能用后退按钮(Back)看到前一个网页,告诉你一个方法,就是采用location.replace(“url”)就可以实现这个功能。

2012-10-31 · 1 min · 54 words · -

sk_buff

sk_buff sk_buff (internal networking structure used by linux kernel) sk_buff的意思是socket buffer,这是Linux网络子系统中的核心数据结构 https://liu-jianhao.github.io/2019/05/linux%E5%86%85%E6%A0%B8%E7%BD%91%E7%BB%9C%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%901sk_buff%E7%BB%93%E6%9E%84/ tcp连接的资源占用 size of sk_buff (internal networking structure used by linux kernel) the read and write buffer for a connection the size of buffers can be tweaked as required root@x:~# sysctl -A | grep net | grep mem check for these variables these specify the maximum default memory buffer usage for all network connections in kernel net.core.wmem_max = 131071 ...

2012-10-31 · 1 min · 197 words · -

Java中的instanceof关键字

Java中的instanceof关键字 instanceof是Java的一个二元操作符,和==,>,<是同一类东西。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。举个例子: String s = “I AM an Object!”; boolean isObject = s instanceof Object; 我们声明了一个String对象引用,指向一个String对象,然后用instancof来测试它所指向的对象是否是Object类的一个实例,显然,这是真的,所以返回true,也就是isObject的值为True。 instanceof有一些用处。比如我们写了一个处理账单的系统,其中有这样三个类: public class Bill {//省略细节} public class PhoneBill extends Bill {//省略细节} public class GasBill extends Bill {//省略细节} 在处理程序里有一个方法,接受一个Bill类型的对象,计算金额。假设两种账单计算方法不同,而传入的Bill对象可能是两种中的任何一种,所以要用instanceof来判断: public double calculate(Bill bill) { if (bill instanceof PhoneBill) { //计算电话账单 } if (bill instanceof GasBill) { //计算燃气账单 } … } 这样就可以用一个方法处理两种子类。 然而,这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现,这是面向对象变成应有的做法,避免回到结构化编程模式。只要提供两个名字和返回值都相同,接受参数类型不同的方法就可以了: public double calculate(PhoneBill bill) { //计算电话账单 } public double calculate(GasBill bill) { //计算燃气账单 } ...

2012-10-31 · 1 min · 72 words · -

getRequestDispatcher(), sendRedirect()

getRequestDispatcher(), sendRedirect() 1.getRequestDispatcher(url)是请求转发,前后页面共享一个request。 RequestDispatcher 对象从客户端获取请求request,并把它们传递给服务器上的servlet,html或jsp。 它有两个方法: forward()和include()具体如下 void forward(ServletRequest request,ServletResponse response) 用来传递request的,可以一个Servlet接收request请求,另一个Servlet用这个request请求来产生response。request传递的请求,response是客户端返回的信息。forward要在response到达客户端之前调用,也就是 before response body output has been flushed。如果不是的话,它会报出异常。 void include(ServletRequest request,ServletResponse response) 用来记录保留request和 response,以后不能再修改response里表示状态的信息。 request.getRequestDispatcher(url).forward(request,response)是直接将请求转发到指定URL,所以该请求能够直接获得上一个请求的数据,request对象始终存在,不会重新创建。 forward 发生在服务器内部, 在浏览器完全不知情的情况下发给了浏览器另外一个页面的response. 这时页面收到的request不是从浏览器直接发来了,可能己经放了数据。 请求转发时如果要传递参数可以这样用: request.setAttribute(“name”,“Michael”); request.getAttribute(“name”); 2.sendRedirect(url)重定向到指定URL,会新建request对象。 这是因为 redirect 会首先发一个response给浏览器, 然后浏览器收到这个response后再发一个requeset给服务器, 然后服务器发新的response给浏览器,这时页面收到的request是从浏览器新发来的,所以上一个request的数据会丢失。 如果要传递参数只有在url后加参数的方式,比如url?type=test才能实现。 3.ServletContext.sendRedirect(String url)中的url只能使用绝对路径; 而ServletRequest.getRequestDispatcher(String url)中的url可以使用相对路径。h这是因为ServletRequest具有相对路径的概念;而ServletContext对象无此概念。 PS:如果需要把请求转移到另外一个WebApp中的某个地址,可以按下面的步骤做法: 获得另外一个WebApp的ServletConext对象(currentServletContext.getContext(uripath)). 调用ServletContext.getRequestDispatcher(String url)方法。

2012-10-31 · 1 min · 48 words · -

CDN

CDN CDN的全称是Content Delivery Network,即内容分发网络。其目的是通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络"边缘",使用户可以就近取得所需的内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。从技术上全面解决由于网络带宽小、用户访问量大、网点分布不均等原因所造成的用户访问网站响应速度慢的问题。 (也就是一个服务器的内容,平均分部到多个服务器上,服务器智能识别,让用户获取离用户最近的服务器,提高速度 CDN 内容分发网络 (Content Delivery Network,简称CDN) 将源站内容分发至全国所有的节点,缩短用户查看对象的延迟,提高用户访问网站的响应速度与网站的可用性,解决网络带宽小、用户访问量大、网点分布不均等问题

2012-10-29 · 1 min · 12 words · -

sql command

sql command -- http://www.wiloon.com/?p=1899 insert into t1 values (1,'1',1) on duplicate key update c0=c0+1; INSERT INTO "表格名" ("栏位1", "栏位2", ...) VALUES ("值1", "值2", ...);

2012-10-29 · 1 min · 24 words · lcf

Beelink SER8 archlinux

文档说明: 本文档记录 Beelink SER8 mini PC 在 Arch Linux + KDE 桌面环境下使用过程中遇到的问题、解决方案和系统操作。 亮度自动降低问题解决方案 问题描述 系统在锁屏、关闭显示器或重启后,显示器亮度会被自动调低到 30% 左右,且不会自动恢复。 环境信息 设备: Beelink SER8 (mini PC) 系统: Arch Linux 桌面环境: KDE Plasma 亮度控制: DDC/CI (通过 ddcutil) 解决方案 方案 1: 禁用 KDE 的自动亮度调节 (推荐) 打开 KDE 系统设置: systemsettings5 导航到: 电源管理 (Power Management) → 节能 (Energy Saving) 检查以下设置: 取消勾选 “当空闲时降低屏幕亮度” (Dim screen when idle) 取消勾选 “在锁定屏幕时降低亮度” (Dim screen on lock) 在 “屏幕亮度” 部分,将所有电源模式下的亮度设置为你想要的值(如 100%) 点击 “应用” 保存设置 ...

2012-10-29 · 20 min · 4151 words · lcf

golang 读系统环境变量

golang 读系统环境变量 http://studygolang.com/articles/3387 os.Setenv("FOO", "1") fmt.Println("FOO:", os.Getenv("FOO"))

2012-10-29 · 1 min · 7 words · lcf

共识算法,一致性算法, consensus algorithm

共识算法,一致性算法, consensus algorithm PoW,PoS,DPoS,PBFT,Paxos,Raft 分布式一致性算法-Paxos、Raft、ZAB、Gossip https://zhuanlan.zhihu.com/p/130332285 ZAB算法 说明:ZAB也是对Multi Paxos算法的改进,大部分和raft相同 和raft算法的主要区别: 对于Leader的任期,raft叫做term,而ZAB叫做epoch 在状态复制的过程中,raft的心跳从Leader向Follower发送,而ZAB则相反。

2012-10-26 · 1 min · 12 words · -

Git 库空间优化/清理

Git 库空间优化/清理 git仓库过大会导致哪些问题? git仓库体积过大,占用电脑本地闪存的存储空间; clone git仓库时,耗时过长,甚至完全clone不下来导致git报错; git pull时会由于引用对象过多会报错,导致本地代码无法更新; 在切换分支的时候经常会出现cpu占满,内存占满的情况导致电脑死机; 作者:江霖丶 链接:https://juejin.cn/post/7024922528514572302 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 Git库随着使用时间的延续,空间会不断增长,但实际代码其实只占很小的空间,更多的是git库本身的归档文件,其中包括已删除的文件纪录。Git优化的本质就是清除已删除文件的归档历史,并重写commit记录。 另外可以将git中变化很少,与代码无关的文件移除,如一些资源文件,放到统一的位置,可以减小很大一部分空间占用。 克隆远程库到本地 $ git clone remote-url 用下面的脚本获取所有分支. !/bin/bash for branch in git branch -a | grep remotes | grep -v HEAD do git branch –track ${branch##*/} $branchdone done 现在你拥有了远程git库的完整克隆,可先在本地进行一些测试、验证工作。 分析git库 代码文件一般都很小,Git库的优化主要从大文件入手。 用下面的脚本可以找出git归档记录中排名前十的大文件,包括已删除的文件。 !/bin/bash set -x Shows you the largest objects in your repo’s pack file Written for osx @see http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/ @author Antony Stubbs set the internal field spereator to line break, so that we can iterate easily over the verify-pack output IFS=$’\n'; ...

2012-10-26 · 2 min · 280 words · -