第1集:锦绣华南 http://t.cn/zWZF3Er第2集:云翔天边 http://t.cn/zWZF13x第3集:神奇高原 http://t.cn/zWZFB3A第4集:风雪塞外 http://t.cn/zWZFrmJ第5集:沃土中原 http://t.cn/zWZFdYW第6集:潮涌海岸[去旅行]
from: http://www.html-js.com/article/2134Underscore 简介Underscore 是一个JavaScript实用库,提供了类似Prototype.js的一些功能,但是没有继承任何JavaScript内置对象。它弥补了部分jQuery没有实现的功能,同时又是Backbone.js必不可少的部分。Underscore提供了80多个函数,包括常用的: map, select, invoke — 当然还有更多专业的辅助函数,如:函数绑定, JavaScript模板功能, 强类型相等测试, 等等. 在新的浏览器中, 有许多函数如果浏览器本身直接支持,将会采用原生的,如 forEach, map, reduce, filter, every, some 和 indexOf.个人感受Underscore 是一个我坚持看完的js源代码,他简单、易懂、实用,细心观察就会发现,每个函数都很简短,作为开源阅读源码,我相信Underscore是不错的选择笔记1:大量的这种方法,应该是 防止原始方法被篡改,同时加快运行速度,而且在严格模式,也不让通过arguments.callee 调用相关方法的原因吧var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;// Create quick reference variables for speed access to core prototypes.varpush = ArrayProto.push, slice = ArrayProto.slice, concat = ArrayProto.concat, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty;2:void 0,开始还好奇为啥用void 0,是undefined 的缩写?后来一打听才知道,原来undefined在旧版本的浏览器中是不可以被赋值的,而新版本的浏览器是可以被赋值的,为了准确的判断,所以就有了void 0_.first = _.head = _.take = function(array, n, guard) { if (array == null) return void 0; if ((n == null) || guard) return array[0]; if (n < 0) return []; return slice.call(array, 0, n);};3:代码短小精干Underscore 代码短小精干没的说,真是精品除了 eq 这个方法长点外 其他方法都很短4:遗憾 这次走读 没记录笔记没调试本菜鸟第一次走读源码 同时欢迎大家把源码走读 放到这个专栏下 O(∩_∩)O~
Haroopad 最好用的markdown编辑器跨平台,代码高亮,Vim 键绑定,多列模式,行号,折叠, Github Flaverd Markdown 等功能.
Notification js提醒插件,有很有炫的效果.demo: http://tympanus.net/Development/NotificationStyles [repo owner=”codrops” name=”NotificationStyles”]
TmodJS 前端模板,又一款腾讯的前端模板框架,使用 artTemplate3.0 作为模板引擎.TmodJS(原名 atc)是一个简单易用的前端模板预编译工具。它通过预编译技术让前端模板突破浏览器限制,实现后端模板一样的同步“文件”加载能力。它采用目录来组织维护前端模板,从而让前端模板实现工程化管理,最终保证前端模板在复杂单页 web 应用下的可维护性。同时预编译输出的代码经过多层优化,能够在最大程度节省客户端资源消耗。
from: http://witmax.cn/cache-writing-policies.htmlCache写机制参考[http://en.wikipedia.org/wiki/Cache#Writing_Policies](http://en.wikipedia.org/wiki/Cache#Writing_Policies)上的说明,Cache写机制分为write through和write back两种。Write-through- Write is done synchronously both to the cache and to the backing store.Write-back (or Write-behind) – Writing is done only to the cache. A modified cache block is written back to the store, just before it is replaced.Write-through(直写模式)在数据更新时,同时写入缓存Cache和后端存储。此模式的优点是操作简单;缺点是因为数据修改需要同时写入存储,数据写入速度较慢。 Write-back(回写模式)在数据更新时只写入缓存Cache。只在数据被替换出缓存时,被修改的缓存数据才会被写到后端存储。此模式的优点是数据写入速度快,因为不需要写存储;缺点是一旦更新后的数据未被写入存储时出现系统掉电的情况,数据将无法找回。Write-misses写缺失的处理方式对于写操作,存在写入缓存缺失数据的情况,这时有两种处理方式:Write allocate (aka Fetch on write) – Datum at the missed-write location is loaded to cache, followed by a write-hit operation. In this approach, write misses are similar to read-misses.No-write allocate (aka Write-no-allocate, Write around) – Datum at the missed-write location is not loaded to cache, and is written directly to the backing store. In this approach, actually only system reads are being cached.Write allocate方式将写入位置读入缓存,然后采用write-hit(缓存命中写入)操作。写缺失操作与读缺失操作类似。No-write allocate方式并不将写入位置读入缓存,而是直接将数据写入存储。这种方式下,只有读操作会被缓存。无论是Write-through还是Write-back都可以使用写缺失的两种方式之一。只是通常Write-back采用Write allocate方式,而Write-through采用No-write allocate方式;因为多次写入同一缓存时,Write allocate配合Write-back可以提升性能;而对于Write-through则没有帮助。处理流程图Write-through模式处理流程: [![A Write-Through cache with No-Write Allocation](http://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Write_through_with_no-write_allocation.png/445px-Write_through_with_no-write_allocation.png "A Write-Through cache with No-Write Allocation")](http://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Write_through_with_no-write_allocation.png/445px-Write_through_with_no-write_allocation.png "A Write-Through cache with No-Write Allocation")A Write-Through cache with No-Write AllocationWrite-back模式处理流程: [![A Write-Back cache with Write Allocation](http://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Write_back_with_write_allocation.png/468px-Write_back_with_write_allocation.png "A Write-Back cache with Write Allocation")](http://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Write_back_with_write_allocation.png/468px-Write_back_with_write_allocation.png "A Write-Back cache with Write Allocation")A Write-Back cache with Write Allocation
from: http://www.lanceyan.com/tech/arch/consistenthashing_and_solr.html互联网创业中大部分人都是草根创业,这个时候没有强劲的服务器,也没有钱去买很昂贵的海量数据库。在这样严峻的条件下,一批又一批的创业者从创业中获得成功,这个和当前的开源技术、海量数据架构有着必不可分的关系。比如我们使用mysql、nginx等开源软件,通过架构和低成本服务器也可以搭建千万级用户访问量的系统。新浪微博、淘宝网、腾讯等大型互联网公司都使用了很多开源免费系统搭建了他们的平台。所以,用什么没关系,只要能够在合理的情况下采用合理的解决方案。那怎么搭建一个好的系统架构呢?这个话题太大,这里主要说一下数据分流的方式。比如我们的数据库服务器只能存储200个数据,突然要搞一个活动预估达到600个数据。可以采用两种方式:横向扩展或者纵向扩展。纵向扩展是升级服务器的硬件资源。但是随着机器的性能配置越高,价格越高,这个代价对于一般的小公司是承担不起的。横向扩展是采用多个廉价的机器提供服务。这样一个机器只能处理200个数据、3个机器就可以处理600个数据了,如果以后业务量增加还可以快速配置增加。在大多数情况都选择横向扩展的方式。如下图:现在有个问题了,这600个数据如何路由到对应的机器。需要考虑如果均衡分配,假设我们600个数据都是统一的自增id数据,从1~600,分成3堆可以采用 id mod 3的方式。其实在真实环境可能不是这种id是字符串。需要把字符串转变为hashcode再进行取模。目前看起来是不是解决我们的问题了,所有数据都很好的分发并且没有达到系统的负载。但如果我们的数据需要存储、需要读取就没有这么容易了。业务增多怎么办,大家按照上面的横向扩展知道需要增加一台服务器。但是就是因为增加这一台服务器带来了一些问题。看下面这个例子,一共9个数,需要放到2台机器(1、2)上。各个机器存放为:1号机器存放1、3、5、7、9 ,2号机器存放 2、4、6、8。如果扩展一台机器3如何,数据就要发生大迁移,1号机器存放1、4、7, 2号机器存放2、5、8, 3号机器存放3、6、9。如图:从图中可以看出 1号机器的3、5、9迁移出去了、2好机器的4、6迁移出去了,按照新的秩序再重新分配了一遍。数据量小的话重新分配一遍代价并不大,但如果我们拥有上亿、上T级的数据这个操作成本是相当的高,少则几个小时多则数天。并且迁移的时候原数据库机器负载比较高,那大家就有疑问了,是不是这种水平扩展的架构方式不太合理?—————————–华丽分割线—————————————一致性hash就是在这种应用背景提出来的,现在被广泛应用于分布式缓存,比如memcached。下面简单介绍下一致性hash的基本原理。最早的版本 http://dl.acm.org/citation.cfm?id=258660。国内网上有很多文章都写的比较好。如: http://blog.csdn.net/x15594/article/details/6270242下面简单举个例子来说明一致性hash。准备:1、2、3 三台机器还有待分配的9个数 1、2、3、4、5、6、7、8、9一致性hash算法架构步骤一、构造出来 2的32次方 个虚拟节点出来,因为计算机里面是01的世界,进行划分时采用2的次方数据容易分配均衡。另 2的32次方是42亿,我们就算有超大量的服务器也不可能超过42亿台吧,扩展和均衡性都保证了。二、将三台机器分别取IP进行hashcode计算(这里也可以取hostname,只要能够唯一区别各个机器就可以了),然后映射到2的32次方上去。比如1号机器算出来的hashcode并且mod (2^32)为 123(这个是虚构的),2号机器算出来的值为 2300420,3号机器算出来为 90203920。这样三台机器就映射到了这个虚拟的42亿环形结构的节点上了。三、将数据(1-9)也用同样的方法算出hashcode并对42亿取模将其配置到环形节点上。假设这几个节点算出来的值为 1:10,2:23564,3:57,4:6984,5:5689632,6:86546845,7:122,8:3300689,9:135468。可以看出 1、3、7小于123, 2、4、9 小于 2300420 大于 123, 5、6、8 大于 2300420 小于90203920。从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个Cache节点上。如果超过2^32仍然找不到Cache节点,就会保存到第一个Cache节点上。也就是1、3、7将分配到1号机器,2、4、9将分配到2号机器,5、6、8将分配到3号机器。这个时候大家可能会问,我到现在没有看见一致性hash带来任何好处,比传统的取模还增加了复杂度。现在马上来做一些关键性的处理,比如我们增加一台机器。按照原来我们需要把所有的数据重新分配到四台机器。一致性hash怎么做呢?现在4号机器加进来,他的hash值算出来取模后是12302012。 5、8 大于2300420 小于12302012 ,6 大于 12302012 小于90203920 。这样调整的只是把5、8从3号机器删除,4号机器中加入 5、8。同理,删除机器怎么做呢,假设2号机器挂掉,受影响的也只是2号机器上的数据被迁移到离它节点,上图为4号机器。大家应该明白一致性hash的基本原理了吧。不过这种算法还是有缺陷,比如在机器节点比较少、数据量大的时候,数据的分布可能不是很均衡,就会导致其中一台服务器的数据比其他机器多很多。为了解决这个问题,需要引入虚拟服务器节点的机制。如我们一共有只有三台机器,1、2、3。但是实际又不可能有这么多机器怎么解决呢?把 这些机器各自虚拟化出来3台机器,也就是 1a 1b 1c 2a 2b 2c 3a 3b 3c,这样就变成了9台机器。实际 1a 1b 1c 还是对应1。但是实际分布到环形节点就变成了9台机器。数据分布也就能够更分散一点。如图:写了这么多一致性hash,这个和分布式搜索有什么半点关系?我们现在使用solr4搭建了分布式搜索,测试了基于solrcloud的分布式平台提交20条数据居然需要几十秒,所以就废弃了solrcloud。采用自己hack solr平台,不用zookeeper做分布式一致性管理平台,自己管理数据的分发机制。既然需要自己管理数据的分发,就需要考虑到索引的创建,索引的更新。这样我们的一致性hash也就用上了。整体架构如下图:建立和更新需要维持机器的位置,能够根据数据的key找到对应的数据分发并更新。这里需要考虑的是如何高效、可靠的把数据建立、更新到索引里。备份服务器防止建立服务器挂掉,可以根据备份服务器快速恢复。读服务器主要做读写分离使用,防止写索引影响查询数据。集群管理服务器管理整个集群内的服务器状态、告警。整个集群随着业务增多还可以按照数据的类型划分,比如用户、微博等。每个类型按照上图架构搭建,就可以满足一般性能的分布式搜索。对于solr和分布式搜索的话题后续再聊。扩展阅读:java的hashmap随着数据量的增加也会出现map调整的问题,必要的时候就初始化足够大的size以防止容量不足对已有数据进行重新hash计算。疫苗:Java HashMap的死循环 http://coolshell.cn/articles/9606.html一致性哈希算法的优化—-关于如何保正在环中增加新节点时,命中率不受影响 (原拍拍同事scott)http://scottina.iteye.com/blog/650380语言实现:http://weblogs.java.net/blog/2007/11/27/consistent-hashing java 版本的例子http://blog.csdn.net/mayongzhan/archive/2009/06/25/4298834.aspx PHP 版的例子http://www.codeproject.com/KB/recipes/lib-conhash.aspx C语言版本例子
由于最近两个月工作比较清闲,个人也比较“上进”,利用工作空余时间,也继续学习了一下,某天突然想起struts2和struts1的区别的时候,发现为什么struts1要用servlet,而struts2要用filter呢?一时又发现,servlet和filter有什么区别呢?于是看了看web.xml,一时又发现,咦,servlet、filter、listener?还有个interceptor?对于这几个概念,本应是初学者就掌握的东东了,可惜本人基础学的不好,只能是现在补课。于是就有了这篇博客。慢慢来吧,需要补课的地方还有很多很多呀。初学的时候都不知道他们存在呢。呵呵。下面从几个方面阐述一下题目中四个概念的区别与联系:1、概念2、生命周期3、职责4、执行过程一、概念:1、servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层。2、filter:filter是一个可以复用的代码片段,可以用来转换HTTP请求、响应和头信息。Filter不像Servlet,它不能产生一个请求或者响应,它只是修改对某一资源的请求,或者修改从某一的响应。3、listener:监听器,从字面上可以看出listener主要用来监听只用。通过listener可以监听web服务器中某一个执行动作,并根据其要求作出相应的响应。通俗的语言说就是在application,session,request三个对象创建消亡或者往其中添加修改删除属性时自动执行代码的功能组件。4、interceptor:是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。5、servlet、filter、listener是配置到web.xml中,interceptor不配置到web.xml中,struts的拦截器配置到struts.xml中。spring的拦截器配置到spring.xml中。二、生命周期:1、servlet:servlet的生命周期始于它被装入web服务器的内存时,并在web服务器终止或重新装入servlet时结束。servlet一旦被装入web服务器,一般不会从web服务器内存中删除,直至web服务器关闭或重新结束。(1)、装入:启动服务器时加载Servlet的实例;(2)、初始化:web服务器启动时或web服务器接收到请求时,或者两者之间的某个时刻启动。初始化工作有init()方法负责执行完成;(3)、调用:从第一次到以后的多次访问,都是只调用doGet()或doPost()方法;(4)、销毁:停止服务器时调用destroy()方法,销毁实例。2、filter:(一定要实现javax.servlet包的Filter接口的三个方法init()、doFilter()、destroy(),空实现也行)(1)、启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;(2)、每一次请求时都只调用方法doFilter()进行处理;(3)、停止服务器时调用destroy()方法,销毁实例。3、listener:类似于servlet和filterweb.xml 的加载顺序是:context- param -> listener -> filter -> servlet4、interceptor:以struts的拦截器为例,加载了struts.xml以后,初始化相应拦截器。当action请求来时调用intercept方法,服务器停止销毁interceptor。三、职责1、servlet:创建并返回一个包含基于客户请求性质的动态内容的完整的html页面;创建可嵌入到现有的html页面中的一部分html页面(html片段);读取客户端发来的隐藏数据;读取客户端发来的显示数据;与其他服务器资源(包括数据库和java的应用程序)进行通信;通过状态代码和响应头向客户端发送隐藏数据。2、filter:filter能够在一个请求到达servlet之前预处理用户请求,也可以在离开servlet时处理http响应:在执行servlet之前,首先执行filter程序,并为之做一些预处理工作;根据程序需要修改请求和响应;在servlet被调用之后截获servlet的执行3、listener:职责如概念。servlet2.4规范中提供了8个listener接口,可以将其分为三类,分别如下:第一类:与servletContext有关的listner接口。包括:ServletContextListener、ServletContextAttributeListener第二类:与HttpSession有关的Listner接口。包括:HttpSessionListner、HttpSessionAttributeListener、HttpSessionBindingListener、 HttpSessionActivationListener;第三类:与ServletRequest有关的Listener接口,包括:ServletRequestListner、ServletRequestAttributeListener4、interceptor:与过滤器十分相似,通过层层拦截,处理用户的请求和响应。 备注:web.xml 的加载顺序是:context-param -> listener -> filter -> servlet 。了解了这几个概念的区别以后,不难理论这个加载顺序了。 四、几个区别:1,servlet 流程是短的,url传来之后,就对其进行处理,之后返回或转向到某一自己指定的页面。它主要用来在 业务处理之前进行控制.2,filter 流程是线性的, url传来之后,检查之后,可保持原来的流程继续向下执行,被下一个filter, servlet接收等,而servlet 处理之后,不会继续向下传递。filter功能可用来保持流程继续按照原来的方式进行下去,或者主导流程,而servlet的功能主要用来主导流程。filter可用来进行字符编码的过滤,检测用户是否登陆的过滤,禁止页面缓存等3, servlet,filter都是针对url之类的,而listener是针对对象的操作的,如session的创建,session.setAttribute的发生,在这样的事件发生时做一些事情。可用来进行:Spring整合Struts,为Struts的action注入属性,web应用定时任务的实现,在线人数的统计等4,interceptor 拦截器,类似于filter,不过在struts.xml中配置,不是在web.xml,并且不是针对URL的,而是针对action,当页面提交action时,进行过滤操作,相当于struts1.x提供的plug-in机制,可以看作,前者是struts1.x自带的filter,而interceptor 是struts2 提供的filter.与filter不同点:(1)不在web.xml中配置,而是在struts.xml中完成配置,与action在一起( 2 ) 可由action自己指定用哪个interceptor 来在接收之前做事5,struts2中的过滤器和拦截器的区别与联系:(1)、拦截器是基于java反射机制的,而过滤器是基于函数回调的。(2)、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器。(3)、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。(4)、拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。(5)、在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次。五、执行流程图:1、servlet:2、filter:3、listener:4、interceptor: