很多场景下,用户的访问网站的会话信息都需要保存,实现会话保存的方式有三种:
1、session绑定 2、session复制,在多个集群的节点间复制会话信息到各个节点 3、session服务器,使用单独的服务器专门用于保存会话信息。实验过程要实现的是第三种方式,使用session服务器的方式来保存用户的会话信息。
实验用机:
两台前端tomcat集群,使用httpd做反向代理,请用户请求转发至后端的tomcat集群,同时有两台memcached服务器用于保存用户的会话信息,其中有一个节点作为备用会话服务器,另一个节点作为主节点使用。具体使用的主机信息如下:
node1:172.16.103.1,安装httpd,tomcat
node2:172.16.103.2,安装tomcat,memcached,该主机安装的memcached作为备用节点
node3:172.16.103.3,安装memcached,作为memcached的主节点使用
实验过程:安装的jdk版本jdk-7u9-linux-x64,tomcat为apache-tomcat-7.0.42
一、配置node1
1、安装httpd
# yum -y install httpd
2、tomcat依赖于jdk运行,需要提前安装jdk
# rpm -ivh jdk-7u9-linux-x64.rpm
配置jdk
# vim /etc/profile.d/java.sh AVA_HOME=/usr/java/latest PATH=$JAVA_HOME/bin:$PATH export JAVA_HOME PATH # source /etc/profile.d/java.sh
3、安装tomcat
# tar xf apache-tomcat-7.0.42.tar.gz -C /usr/local/ # cd /usr/local # ln -sv apache-tomcat-7.0.42/ tomcat
配置tomcat
# vim /etc/profile.d/tomcat.sh export CATALINA_HOME=/usr/local/tomcat export PATH=$CATALINA_HOME/bin:$PATH
4、为tomcat提供sysv脚本:
# vim /etc/rc.d/init.d/tomcat #!/bin/sh # Tomcat init script for Linux. # # chkconfig: 2345 96 14 # description: The Apache Tomcat servlet/JSP container. # JAVA_OPTS='-Xms64m -Xmx128m' JAVA_HOME=/usr/java/latest CATALINA_HOME=/usr/local/tomcat export JAVA_HOME CATALINA_HOME case $1 in start) exec $CATALINA_HOME/bin/catalina.sh start ;; stop) exec $CATALINA_HOME/bin/catalina.sh stop;; restart) $CATALINA_HOME/bin/catalina.sh stop sleep 2 exec $CATALINA_HOME/bin/catalina.sh start ;; configtest) exec $CATALINA_HOME/bin/catalina.sh configtest ;; *) exec $CATALINA_HOME/bin/catalina.sh * ;; esac
启动tomcat,查看tomcat运行的实例监听的端口结果
# service tomcat start
其中8080为默认的tomcat使用的http协议的连接器监听的端口,8005为管理tomcat实例的进程监听的端口,8009为tomcat使用的ajp协议的连接器监听的端口。在单独部署的tomcat服务器中,连接器也可以理解为web服务器,用于接收和响应用户请求。
在tomcat实例启动之后,可以通过浏览器测试tomcat实例运行是否正常,比如,在浏览器内输入该实例监听的地址和端口,显示的结果如下:
二、配置node2
node2上需要安装的与node1相近,有jdk,tomcat,不同的是这个节点要安装memcached,用于保存用户的会话信息,该节点的memcached作为备用节点,安装配置jdk和tomcat的过程参考node1的配置。
1、安装memcached
# yum -y install memcached # service memcached start
在node2上安装好tomcat之后一定要测试一下其默认的tomcat页面是否可以正常的访问到,以便进行下一步操作。
三、配置node3
node3上只安装memcached,作为保存用户会话的主节点
# yum -y install memcached # service memcached start
四、配置node1上的httpd服务,工作于反向代理模式,用于接收用户请求,将请求转发至后端的tomcat服务器
安装httpd确保安装有以下模块,可以使用httpd -M或httpd -D DUMP_MODULES命令查看下面的模块是否已经安装:
proxy_module (shared) proxy_balancer_module (shared) proxy_http_module (shared) proxy_ajp_module (shared)
五、在node1和node2上创建一个web app用于测试访问使用,在tomcat程序安装的路径下对应的webapps目录下创建新的web应用程序:
# cd /usr/local/tomcat/webapps/
# mkdir test/WEB-INF/{classes,lib}
提供该web应用程序的测试页面,该测试页面中提供的内容用于测试用户的会话信息,是一个java脚本:
# cd test/ # vim index.jsp <%@ page language="java" %> <html> <head><title>TomcatA</title></head> <body> <h1><font color="red">TomcatA.magedu.com</font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("magedu.com","magedu.com"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>
在node2上创建web app过程相同,提供的测试页面内容为:
<%@ page language="java" %> <html> <head><title>TomcatA</title></head> <body> <h1><font color="red">TomcatB.magedu.com</font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("magedu.com","magedu.com"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>
两个页面的内容不同,测试时可以查看到不同的主机名称的变化,但是用户的session信息不变,以达到用户会话保存的效果。这两个页面提供完成后,可以重启tomcat实例,使用主机名:端口的方式查看这两个页面是否可以访问到,其效果应该如下图:
两个节点的tomcat配置完成之后,配置httpd反向代理,实现后端的两个tomcat实例组成集群,两个节点使用balancer负载均衡器定义为lbcluster的集群,每个节点的权重为1,同时定义了该集群的状态输出信息等。
<Proxy balancer://lbcluster> BalancerMember ajp://172.16.103.1:8009 loadfactor=1 route=TomcatA BalancerMember ajp://172.16.103.2:8009 loadfactor=1 route=TomcatB ProxySet lbmethod=byrequests </Proxy> <Location /status> SetHandler balancer-Linux利用sendmail和fetion发送报警通知 阅读原文» Linux利用sendmail和fetion发送报警通知
一、sendmail报警通知
| 1、停止系统自带的sendmail服务 #/etc/init.d/postfixstop 2、安装sendmail和mailx #yum-yinstallsendmailmailx 3、修改sendmail配置文件 #cp/etc/mail.rc/etc/mail.rc.bak #cat>>/etc/mail.rc<<EOF set from=13260071987@139.comsmtp=smtp.139.com set smtp-auth-user=13260071987@139.comsmtp-auth-password=yi15093547036smtp-auth=login 4、重新启动sendmail服务 #servicesendmailrestart #echo"IloveNagios"|mail-s'邮件主题01:TodaylearnNagios'13260071987@139.com #cat/etc/passwd|mail-s'邮件主题02:TodaylearnNagios'13260071987@139.com #mail-s'邮件主题03:TodaylearnNagios'13260071987@139.com</etc/issue |
邮件通知如下图所示
手机短信通知如下图所示
二、fetion报警通知
1、安装解压rar格式的解压软件
| [root@fetion~] #wgethttp://www.rarsoft.com/rar/rarlinux-4.0.1.tar.gz [root@fetion~] #tarxfrarlinux-4.0.1.tar.gz [root@fetion~] #cdrar [root@fetionrar] #make mkdir -p /usr/local/bin mkdir -p /usr/local/lib cp rarunrar /usr/local/bin cp rarfiles.lst /etc cp default.sfx /usr/local/lib [root@fetionrar] #cd.. |
2、下载并安装飞信的支持库
| [root@fetion~] #wgethttp://www.it-adv.net/fetion/linuxso_20101113.rar [root@fetion~] #unrarxlinuxso_20101113.rar - bash : /usr/local/bin/unrar : /lib/ld-linux .so.2:badELFinterpreter:没有那个文件或目录 [root@fetion~] #yum-yinstallglibc.i686 [root@fetion~] #unrarxlinuxso_20101113.rar unrar:error while loadingsharedlibraries:libstdc++.so.6:cannot open sharedobject file :Nosuch file ordirectory [root@fetion~] #yum-yinstalllibstdc++.so.6 [root@fetion~] #yum-yinstalllibstdc++ [root@fetion~] #yum-yinstalllibstdc++.so.6 [root@fetion~] #unrarxlinuxso_20101113.rar UNRAR4.01freewareCopyright(c)1993-2011AlexanderRoshal Extractingfromlinuxso_20101113.rar Extractinglibcrypto.so.4OK Extractinglibssl.so.4OK ExtractinglibACE_SSL-5.7.2.soOK ExtractinglibACE-5.7.2.soOK [root@fetion~] #mkdir-p/usr/local/fetion/lib [root@fetion~] #mvlib*so*/usr/local/fetion/lib/ 阅读更多内容
本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 基于.NET的3D开发框架/工具比较 - 波多尔斯基 阅读原文»- 好久木有写博客了,这么日子以来忙忙碌碌的,也没大有时间潜心学习和梳理。最近刚好接手一个3D显示的活,虽然还没怎么弄明白,但是也看过一些方案,走了一些弯路,经过一些浅显的了解(3D Display这里面水太深),说说我个人的看法吧。
1.目标项目的主要工作是能够接受从核心模块得来的数据(已经对原始的工程数据进行处理,包括进行坐标转化、归一化等)并将点云数据进行展示,核心是通过C++写的,然后我负责的外围,没有硬性的语言要求。 2.方案我觉得应该想办法使用C#来实现这个显示展示问题。经过简单的寻找,大体比较靠谱的有这么些: - XNA/MONOGAME
- Silverlight
- SharpGL/SharpDX/OpenTK
- WPF
首先从本质上来说,3D显示到底层都是调用DirectX或者OpenGL(不考虑软件加速),上面的这些只是对他们包装的层次不同而已。接下来看看应用场景: XNA/MONOGAME: 提供了一个较完整的渲染管线,操作3D模型很容易,比较适合于3D的游戏的开发,然后还有一点就是我做这个开发的时候,没看见鼠标在哪,难道不支持?值得关注的是,据我所知,XNA不支持WINFORM/WPF控件!(学了一点而已,不深入) Silverlight:作为一个客户端的程序运行,适用于构建RIA程序(P.S. 虽然小光酱已经不是微软的开发方向了…),核心3D显示功能是基于XNA的,就是继承结构不一样而已,值得一说的是,这个可以实现运用普通的WPF控件实现对3D图形的控制。 SharpGL/SharpDX/OpenTK:这些都是对底层DirectX或者OpenGL的.NET封装,肯定是可以实现所需要的功能的,不过由于是对底层的封装,使用起来较XNA还是有些难度。 WPF:显示是基于DirectX的,内建支持3D功能的展示,操作方式和xna有一些不同,不过支持原生的WPF控件。 3.小结从上面的简单对比,可以发现,如果有时间的话,通过SharpGL这一类方法会比较适合于从底层开始开发,通过WPF会比较适合于我的应用场景;由于XNA与Silverlight不再受微软力推,最好也暂停一下,观望观望(当然从学习的角度来说,学了就是自己的,融会贯通,不会白学)。 由于最初没有做一个横向的对比,我直接用的XNA进行的开发。结果,手下人折腾了半天,告诉我搞不出来,回头还要重做,耽误了很多时间,以后动手之前还是需要先动脑,应引以为戒。 P.S. 微软的开发者中心http://msdn.microsoft.com/library/windows/desktop/dn614993.aspx上对开发技术做了对比,做graphics-rich程序,微软还是推荐用C++ 本文链接:基于.NET的3D开发框架/工具比较,转载请注明。 [程序人生]前途无"亮''的大学 - badwell 阅读原文»转眼之间就到大四了,今天晚上很迷茫,很纠结,想了好多,好多,真的,长大之后,自从第一次失恋之后,第一次会想到这么的多。 嗯,先自我介绍哈吧,我是从云南的大山里走出来的孩子,什么样的大山,就是到现在到村里的路都还是泥巴路,村子里也只有20多家,说实话,爸妈把我抚到大学真心不容易,妈妈身体不好,腿上有风湿,爸爸腰杆也不好,由于有那个骨刺,所以身体也不是很好,经常的要吃药,我想要是家里要是有钱的话,估计爸爸就可以去做手术的了,总比吃那些什么药酒要好的多,生病了,也不和我们说,经常一个人闷在心里面。我也很想和父亲多说一些话,但是发现,说起来,还是困难的。 在村里,我的那一大家里,我的爸爸人也是比较好,喜欢帮助别人,但也就是人太好了,所以就经常吃亏,好多的东西都会做出让步。让别人觉得他好欺,然后妈妈就经常拿这个说事,说他软,怎么怎么的,而爸爸,也经常只会沉默着,也不管妈妈怎么说呢,实在听不下去呢时候,就顶几句,当然,现在很大的一部分时间都在外面读书,也只有周末,和放假才会回家了, 回家呢时候,爸爸,由于要挣钱,给我和姐姐读书用,所以,即使回家的时候,也跟爸爸交流不上几句,回家呢时候,也只是晚上回来,因为他们在离家20多里远的地方,给人家干活,而为了回家见我们一面,只好在那边干完活之后,连夜的回家,到家的时候,都已经快10点了,但是在农村,这个时候,村子里的人大多也都睡觉了,我们也的是快差不多睡了。 本来也不会有那么多的感慨的,可是今天晚上爸爸打电话给我,说让我回家一次,我,因为要放国庆节的嘛。回家么,看看的嘛,还有就是聊聊呗。因为之前我打电话给他说:我现在在纠结我到底是要在云南工作呢,还是要到外省去闯闯?也或者是从事我学的专业,还是去当程序员!??嗯,说起这个,你们可能也会觉得怪怪的吧,我也这么认为,嘿嘿。我是2011级的学生,报告大学的时候,我哥帮我选了昆明理工大学的材料科学与工程专业,听他说的,好就业的嘛,而且还是昆工的强悍专业的说,因为云南这边矿产多,所以,也造就了昆工。于是乎,就这样进了昆工,进来之后,因为一些意外的原因,结识了计算机编程,然后就喜欢上了,这个东西,熟入指令,居然可以让它做你想做呢事,就这样我也的就进去了计算机的世界(至于这其中的具体经历,我在另外一篇日志里,写了大家如果感兴趣,的话可以上我的博客里,里面有我写的日志,当然如果有后来者看到我的博客想要与我交流的话,当然欢迎我的QQ是1005526886) 。 然后我就从此喜欢上了计算机,平时闲着的时候,我就逛论坛,学习电脑黑客技术,学习汇编,逆向,破解等等。然后就是,在假期的时候,我又通过我认识的朋友,或者在网上去给外面的企业当实习生,然后就是周末的时候,又去找一个兼职做做,不停的锻炼着自己。 经过大二结束,进去大三呢时候,进入了云南的Actiontec分公司实习,这个进去这个公司实习,说起来,还是挺有传奇呢。(具体怎么进去的,等等在我的另外一个帖子里里有写到,感兴趣的,可以去看看,不说其他的,只是希望你们也能通过我这些经历的分享能找到你们要走的路。。。) 在大三的时候,我知道我的技术不成熟,还需要在沉淀,于是我经常去的地方就是图书馆了,每天差不多大多的时间,我都是呆在图书馆学习java相关联的技术的。但是,很感慨,学的和用的,总是不是一会事的。我选择java是因为,它开源的多,而且技术更新换代,没有微软的那么频繁。 在我们有次去做实验的时候,突然的结识了傅老师,他也是学材料的,但是,他动手能力也很强,于是,他在年轻的时候,也在弄计算机网络安全(就是这个,还去给师云南师范大学的学生上过计算机网络安全的课,但是由于后来,他对师大的考试制度不满意,太假了,于是就退了),然后他就说,他想招一个对单片机感兴趣的学生,进入实验室,来改进他们之前做的那个SD膨胀分析软件,这个设备,是他们自己开发的,虽然大体模型做出来了,硬件相关的,也弄的差不多了,但是软件还没弄好,叫我弄一个软件出来。 去实验室的时候,他把师兄做的一个软件拷给我,那个是用VB做的,好吧,于是我就又去学了VB,然后把它的界面改了哈,然后就是,宝石切割机的改造,因为,它的声音实在太大了,一启动,噪声很大,旁边领导的办公室,还有上课都会影响到,然后就是,测尺寸,画图纸,写方案,估计那段时间,是我最忙的时候了吧,一天白天的时候,还要正常的上我们的专业课,我还要,努力的去看讲关于单片机的书,还要帮忙设计宝石切割机的图纸。呜呼哀哉,一天吃了饭,不是往实验室跑,就是从图书馆跑的,一回到宿舍,都很晚了,躺在床上,直接就睡着了。 顺便写个小插曲,在大二的时候,我喜欢了,我们班上一个姓段的女孩,自从我看到第一眼以后,就喜欢上了,参加我们学校的大学生网球比赛的时候,那个时候估计是我最幸福的日子吧,每天都可以和她打电话,也可以越出来玩,于是乎,我在那个暑假的时候,我表白了,我发短信和他说的,我说我喜欢她!她说,为什么?我说,我喜欢你,没有为什么?然后就是,也得无条件的对她好,但是到了大三下学期的时候,见了她,不知道说什么好了,见了面,也只是打了一声招呼,话也跟少说,只有有一次,我约她出来玩,她说很忙!我去,她一天看到晚的小说,在上课也还在看的?会很忙的吗?于是有了一些分歧,让后,我看她在空间发了一条说说,说,她欠债了。我看见之后,我就给她打了一条消息,说:对不起了,然后她也没回 。之间也把她的QQ删了好多次,但是删了之后,最后还是又加上了,明早道是犯贱,可是还去犯。哎,人啊。! 不说女朋友了,说了,太伤心了,从那那之后,我觉得我跟她彻底没戏了,所以,我之后,几乎没有打过电话给她,而她几几乎没有打过电话给我,即使打给我的,也是因为有事的,所以我想她估计也不喜欢我,所以,就没怎么联系了,我只是想说:你不喜欢我,你可以直说的嘛,我又不会像苍蝇一样围着你,浪费你的表情,也是在浪费我的表情,但是估计也是我,水平太菜了,当初和女孩说话都会脸红的,这种么,估计也是没戏的了。 女朋友,说完了,然后就是进入了大三下学期,下学期,我们要做热膨胀分析的实验,么么,之前只是打开软件看过一眼,还有就是,根本没做过热膨胀分析的实验,还涉及到串口通信的,要我一个月就要弄好,么么,那个时候,我居然还选折了用最难的C++来做,然后就要用MFC的框架,天啊,我不是计算机专业的,之前虽有接触么,但是还是菜鸟的啊,然后就是硬着头皮去弄了。也就是在那个时候学会了串口通信,单片机编程。因为是用C++做的,涉及到了COM技术,通信技术,解码编码问题,这些解决之后,遇到了最大的问题,就是波形显示的问题,之前,一直在网上找波形显示的插件,找来找去,不仅没有满意的,而且还浪费了,我不少的时间,没的办法,我只能按照我的理解,自己写。这个做好后,又遇到一个问题,就是传数据的时候,居然数据波动很大,还要滤波,这可把我还产了,经过几个不暝之夜,最终还是做出来了,能正常的为教学使用了。这个也算告一个段落了。 隔一段时间之后,由于实验室建设需要,要做一个虚拟实验室,这个困难的任务,又归到我身上了,要求用一周的时间做好,么么,还真当我是神了噶!没办法,只好加班加点的,赶出来了,当然,本来我之前是做成动态的,但是,老师,突然间说,这里要改,那里要改的,直接就是要我的命啊,你怎么不去改改看,当然,这个只能在心里嘀咕,还是不敢和他说的。最终,最终,还是弄出来了。弄出来之后,还要去百参加评比,哎,命苦啊,又是我去了,期间不得不说一个人,姓孔的,不得不说,他还是有点吹牛的本事的,我们一个一天忙到晚的,他不仅不忙,而且还多悠闲的,老师请客吃饭的时候,也是把他叫上的。而我活干的最多的,除了请我吃了几顿饭以外,钱都木有给我一些。哎,真是苦命的娃。 到后面,快放假了,说给我找个兼职做呢,找着找着的,就没有下文了,还要让我帮忙维护那个服务器。我真心累了!!!不想去弄了。特别要去呈贡照相么时候,尼玛,我就是要忙着帮你弄网站,所以,也才木有时间去写衣服鞋子,然后,他上下看了我一眼,居然就不要我去了!!!好吧,居然闲我丢脸了!!!白白的帮你干苦力活,钱都木有,还这样。 到大四了,我们要去洛阳实习,我还特意的从洛阳买了一些特产来给我们的老师,么么,这个我可是左省右省,才省出来的啊! 然后就是,才正事上课一个星期,就是各种招聘会了!于是我就有拿着我做过的这些东西去投简历了!哎,真心伤不起啊,人家别的,去做人力资源管理的,一个月工资都是3000以上,还有提成!而我这个,还是正打实的一本,还有过实践经验的,还耐吃苦的,工资最高的,也才给我开到3000啊,,这个还是我到外面的这些公司去不断的面试,不断的总结面试经验的,工资才难那么低啊,我的心啊,顿时凉飕飕的,么么,这个钱拿的心酸啊!虽然之前有看网友说IT这个行业工资高的嘛,这就高了吗?我也只是想挣点钱,帮爸妈们减轻点负担,给他们想点福?怎么就这么难么? 看网友们写到,干IT的,老了都要转行的,好吧,高强度,还是脑力劳动,还有时年龄限制,工资也是那么点,真的让人心寒,昆明的物价也是老高,老高的,如果要是这么干么话,多少年可以在昆明买个房子啊!哎,之前,老师还说,毕业之后,帮我们介绍工作啥的?到现在了,还没有听他说过啥呢?还让我们帮他做一个实验室安全管理系统,还是要用嵌入式的,还又设计到wifi通信,c/s架构的!么么,让人心寒啊!,话说,我现在还在很纠结很纠结啊,我也就是很想找个有发展前途的公司一直一直的做下去,怎么就不行呢!,话说,各位看官,前辈们,遇到这种问题,该咋办啊?出出主意嘛!!!! 本文链接:[程序人生]前途无"亮''的大学,转载请注明。 阅读更多内容
本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 上传VHD到Azure并创建虚拟机 阅读原文» 上传VHD到Azure并创建虚拟机 返回顶部 cache 的设计与实现 阅读原文» cache 的设计与实现 本文整理自一下两篇博客:http://my.oschina.net/ScottYang/blog/298727 http://my.oschina.net/u/866190/blog/188712 Cache简介: Cache(高速缓存), 一个在计算机中几乎随时接触的概念。CPU中Cache能极大提高存取数据和指令的时间,让整个存储器(Cache+内存)既有Cache的高速度,又能有内存的大容量;操作系统中的内存page中使用的Cache能使得频繁读取的内存磁盘文件较少的被置换出内存,从而提高访问速度。Cache的算法设计常见的有FIFO(first in first out,先进先出)、LRU(least recently used,最近最少使用)和LFU(Least Frequently userd,最不经常使用)。 - LRU(Least Recently Used ,最近最少使用) ―― 删除最久没有被使用过的数据
算法根据数据的最近访问记录来淘汰数据,其原理是如果数据最近被访问过,将来被访问的几概率相对比较高,最常见的实现是使用一个链表保存缓存数据,详细具体算法如下: 1. 新数据插入到链表头部; 2. 每当缓存数据命中,则将数据移到链表头部; 3. 当链表满的时候,将链表尾部的数据丢弃; - LFU(Least Frequently Used,最不经常使用) ―― 删除使用次数最少的的数据
算法根据数据的历史访问频率来淘汰数据,其原理是如果数据过去被访问次数越多,将来被访问的几概率相对比较高。LFU的每个数据块都有一个引用计数,所有数据块按照引用计数排序,具有相同引用计数的数据块则按照时间排序。具体算法如下: 1. 新加入数据插入到队列尾部(因为引用计数为1); 2. 队列中的数据被访问后,引用计数增加,队列重新排序; 3. 当需要淘汰数据时,将已经排序的列表最后的数据块删除; - FIFO(First In First Out ,先进先出)
算法是根据先进先出原理来淘汰数据的,实现上是最简单的一种,具体算法如下: 1. 新访问的数据插入FIFO队列尾部,数据在FIFO队列中顺序移动; 2. 淘汰FIFO队列头部的数据; 评价一个缓存算法好坏的标准主要有两个,一是命中率要高,二是算法要容易实现。当存在热点数据时,LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中率急剧下降,缓存污染情况比较严重。LFU效率要优于LRU,且能够避免周期性或者偶发性的操作导致缓存命中率下降的问题。但LFU需要记录数据的历史访问记录,一旦数据访问模式改变,LFU需要更长时间来适用新的访问模式,即:LFU存在历史数据影响将来数据的"缓存污染"效用。FIFO虽然实现很简单,但是命中率很低,实际上也很少使用这种算法。 面试题:Google和百度的面试题都出现了设计一个Cache的题目,什么是Cache,如何设计简单的Cache Cache中的存储空间往往是有限的,当Cache中的存储块被用完,而需要把新的数据Load进Cache的时候,我们就需要设计一种良好的算法来完成数据块的替换。LRU的思想是基于"最近用到的数据被重用的概率比较早用到的大的多"这个设计规则来实现的。 为了能够快速删除最久没有访问的数据项和插入最新的数据项,我们双向链表连接Cache中的数据项,并且保证链表维持数据项从最近访问到最旧访问的顺序。每次数据项被查询到时,都将此数据项移动到链表头部(O(1)的时间复杂度)。这样,在进行过多次查找操作后,最近被使用过的内容就向链表的头移动,而没有被使用的内容就向链表的后面移动。当需要替换时,链表最后的位置就是最近最少被使用的数据项,我们只需要将最新的数据项放在链表头部,当Cache满时,淘汰链表最后的位置就是了。 注: 对于双向链表的使用,基于两个考虑。首先是Cache中块的命中可能是随机的,和Load进来的顺序无关。其次,双向链表插入、删除很快,可以灵活的调整相互间的次序,时间复杂度为O(1)。 查找一个链表中元素的时间复杂度是O(n),每次命中的时候,我们就需要花费O(n)的时间来进行查找,如果不添加其他的数据结构,这个就是我们能实现的最高效率了。目前看来,整个算法的瓶颈就是在查找这里了,怎么样才能提高查找的效率呢?Hash表,对,就是它,数据结构中之所以有它,就是因为它的查找时间复杂度是O(1)。 梳理一下思路:对于Cache的每个数据块,我们设计一个数据结构来储存Cache块的内容,并实现一个双向链表,其中属性next和prev时双向链表的两个指针,key用于存储对象的键值,value用户存储要cache块对象本身。 查询: - 根据键值查询hashmap,若命中,则返回节点,否则返回null。
- 从双向链表中删除命中的节点,将其重新插入到表头。
- 所有操作的复杂度均为O(1)。
插入: - 将新的节点关联到Hashmap
- 如果Cache满了,删除双向链表的尾节点,同时删除Hashmap对应的记录
- 将新的节点插入到双向链表中头部
更新: 删除: 参考实现:Apache jcs 1)首先我们需要一个双向链表,自然地,我们需要定义双向链表的节点:DoubleLinkListNode,DoubleLinkList // 双向链表节点 public class DoubleLinkListNode implements Serializable{ private Object value; public DoubleLinkListNode next; public DoubleLinkListNode prev; DoubleLinkListNode(Object value){ this.value = value; } public Object getValue() { return value; } } 对于 DoubleLinkList ,我们需要同步对节点的各种读写操作: public class DoubleLinkList { private int size = 0; private DoubleLinkListNode first; private DoubleLinkListNode last; public DoubleLinkList(){ super(); } // 在链表的尾部的插入一个节点 public synchronized void addLast(DoubleLinkListNode me){ if (first == null) { first = me; }else{ last.next = me; me.prev = last; } last = me; size++; } // 在链表的头部插入一个节点 public synchronized void addFirtst(DoubleLinkListNode me){ if (last == null) { last = me; }else{ first.next = me; me.prev = first; } first = me; size++; } // 获取尾节点 public synchronized DoubleLinkListNode getLast(){ return last; } // 获取头结点 public synchronized DoubleLinkListNode getFirst(){ return first; } // 删除链表指定节点(这个节点一定在链表中) public synchronized boolean remove(DoubleLinkListNode me){ if(me.next == null){ //删除尾节点 if (me.prev == null) { // Make sure it really is the only node before setting head and // tail to null. It is possible that we will be passed a node // which has already been removed from the list, in which case // we should ignore it if ( me == first阅读更多内容
本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 如何向Openstack社区提交一个新项目 - 牛皮糖NewPtone 阅读原文» 前几天有个朋友问我:自己有一个idea不错的项目,也把基本的框架写好了,想贡献到Openstack社区,却不知道应该怎么做。正好之前我有过类似的经历,那么来分享一下我是如何向Openstack社区提交一个新项目。 Openstack的整套系统就是一个开源项目的“大杂烩”,社区把所有项目划分为两类:核心和孵化。除非出身特别牛逼或者从其他核心项目独立出来的项目会在设计之初就被列为核心项目(例如Nuetron,Ironic等);其他项目一般划分到孵化类,在通过一个或多个大版本的发展后,如果变得成熟满足预期并被社区接受,就会转正成为核心项目(例如Savana,Designate等)。如果你想查看当前有哪些核心和孵化项目,可以前去github上查看,它们分别托管在github的openstack和stackforge两大项目下:每个核心项目几乎都是来自工业界IT巨头们的贡献,例如Swift项目来自于Rackspace,Nova项目来自于NASA,Horizon项目来自于HP… 简单介绍一下我提交的新项目的来历:由于我们的IaaS服务跨越多个Region,并且有较为复杂的DNS解析需求,因此我们很早就使用了当时仍在孵化中的designate项目(DNSaaS),用于管理UnitedStack内部的DNS服务。我发现社区并没有提供用于管理Designate服务的puppet module,于是就写了一个puppet-designate,随着代码的日益完善,已经可以满足内部designate服务的管理,然而社区却一直没有开发puppet-designate module的计划。公司文化一直支持开源,我也一直活跃在社区中,但以往都是提交某个项目的bugfix或者blueprint,我心想何不尝试提交一个新项目到社区? 前期准备工作 那么在试图说服社区接受自己的项目前,第一步得先规范自己的代码。 不同于个人项目,社区对于代码的规范要求很高。我列出以下几个注意点: - 完善的代码文档:例如README,参数说明,每个自定义资源类型或者类的使用举例,复杂逻辑的解释,未来需要重构的加上todo标注等等;
- 规范的代码格式:首先不能有语法错误,其次是代码风格要和社区一致,这些都有工具来检查,主要问题是在代码风格上,空2格还是空4格,双引还是单引,不是随心所欲的;
- 合理的代码结构:主类中该放哪些部署逻辑,各服务的组件的部署逻辑该怎么划分,数据库初始化逻辑又该放在哪,都是有要求的;
- 完善的测试代码:社区项目都是以测试驱动的,有的项目甚至先有的是测试代码,如果你妄图向社区提交一段没有附带测试的代码,其后果就是:红色粗体不解释的-1。
沟通和反馈 大约花了一个周末的时间,终于把上述工作做完了,那接下来要做的就是说服社区:接受puppet-designate项目。 我分析了一下Openstack社区的一个新项目大致可以分为两类:全新和已有项目。例如,Heat,Ceilometer就属于全新项目,先在ML上开个头,开始讨论架构,API的设计等等诸多细节,然后众人分领开发工作,接着开始编码最终实现。而Swfit,Nova就属于旧有项目,从其他公司贡献出来的时候,已经比较成熟或者已经有比较完整的架构了。puppet-designate就属于后者,Openstack社区所有相关的puppet项目归属于puppet-manager-core 组管理,当时的PTL是Puppetlabs的Dan Bode。 第一步,我需要发送一封邮件到社区的邮件列表中来告知参与这个项目的所有成员:我准备提交一个puppet-designate项目来管理designate服务。 这里有一点很重要,就是了解在这个邮件列表中,谁说了算:)。 简单解释一下,每个项目都有一个PTL以及相关的core members,他们是项目的主要贡献者。那么如何查询到具体有哪些人呢?可以在https://review.openstack.org的Groups分类中找到。 于是,我把邮件发送到社区的ML同时抄送给了PTL和其他几位非常活跃的core members。邮件里我说清楚地说明了puppet-designate的目的和完成度,以及附带一个github代码地址,以便review。 鉴于国内和国外的时差,邮件第二天得到了回复,得到了PTL和几位core member的肯定,不出所料的是,我的代码被指出了一堆问题,接下来需要进一步地改进。 由于时差的关系,我与社区的协作效率是不高的,在经过大约一周时间的邮件沟通和多次修改后,代码终于通过了这帮有强迫症的工程师的review。 提交到openstack-intra/config 虽然代码通过了社区的批准,但这并不意味着puppet-designate项目就能立马出现在stackforge中了。接着,我开始阅读社区的CI文档,了解到社区CI系统的管理工作是通过config项目来完成的,Openstack的整套CI系统以及我们所看到的Openstack主站以及其他相关站点都是通过puppet来管理的,该项目就包含了用于管理和配置的modules和manifests,属于openstack-intra组负责。Openstack-intra组的主要工作是负责Openstack站点和CI系统的开发和维护。 因此,我需要向config项目提交一个新patch来添加puppet-designate项目,这个PatchSet看起来是这样的:
首先,修改modules/gerritbot/files/gerritbot_channel_config.yaml文件,这个配置文件用于管理各项目的gerritbot,当发生指定的事件后,IRC上的gerritbot会发送通知:
接着需要修改modules/openstack_project/files/jenkins_job_builder/config/projects.yaml,告知Jenkins在处理来自gerrit的puppet-designate patchset时,需要执行哪些job:
然后还需要修改modules/openstack_project/files/zuul/layout.yaml,告知zuul在做check和gate工作的时候要执行哪些job。:
最后修改modules/openstack_project/templates/review.projects.yaml.erb文件,告知gerrit 新建一个stackforge/puppet-designate的项目,并且去github上拉去初始的puppet-designate代码。
等待Approve 在提交了这个patchset后,我在IRC上去通知PTL和其他成员帮我+1,最后还要得到openstack-intra组core member的approve才行,于是我又去#openstack-intra频道里找人,终于找到一位哥们来帮我Approve。好事多磨,结果最后Gerrit在做merge操作时,Zuul所运行得gate测试报了一些莫名的错误,始终不让这个patchset merge。那哥们说:没事,明天前我会解决的。终于,在HK的Havana Summit前,puppet-designate项目出现在了Openstack社区的孵化项目里:https://github.com/stackforge/puppet-designate。 小结 虽然参与Openstack的社区开发已经近三年,但这是我第一次向社区提交一个新项目,通过这次经历,我有以下几点感触: 1. 对于社区的CI系统有了更进一步的了解,因为过去当我输入git review时,整套CI是对我来说是透明的,我根本不知道底层的CI系统各服务之间是如何交互的; 2. 其次是学会和社区沟通,如何清晰地表明自己的观点,如何说服他人,如何找到能拍板的人,若能做好这三点有事半功倍的作用; 3. 最后一点,对于代码的质量要求和规范上有了更深刻的理解,有时候我的同事会不理解我在做code review时为什么会对格式要求那么苛刻,其实我是水瓶座,只是这些习惯是在做社区开发的时候被逼出来的 :) 本文链接:如何向Openstack社区提交一个新项目,转载请注明。 VS2013中Python学习笔记[Django Web的第一个网页] - aehyok 阅读原文»前言 前面我简单介绍了Python的Hello World。看到有人问我搞搞Python的Web,一时兴起,就来试试看。 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环境的搭建过程,以及Hello World的实现。 第二篇 VS2013中Python学习笔记[基础入门] 我简单学习使用了Python的几个基础的知识点。 第一个Web页面 第一步:首先打开VS2013开发工具 ,新建项目,选择Django Project模版。 修改项目名称,可以查看到项目的文件结构 第二步:右键点击Python Environments 第三步:点击Add Virtual Environment 第四步:点击Create,可以看到项目结构发生的变化 1、__init__.py :让 Python 把该目录当成一个开发包 (即一组模块)所需的文件。 这是一个空文件,一般不需要修改它。 2、settings.py :该 Django 项目的设置或配置。 查看并理解这个文件中可用的设置类型及其默认值。 3、urls.py:Django项目的URL设置。 可视其为django网站的目录。 目前,它是空的。 4、wsgi.py :一个WSGI兼容的web服务器的入口。 第五步:点击env(Python 64-bit 3.3) 第六步:点击 Install Python Package 第七步:继续在上面输入django,点击OK。 第八步:点击确定进行安装,等待安装即可,这个时间可能稍微长了一点,看到如下图所示的界面说明安装成功了。 第九步:安装成功之后F5运行即可。 网页竟然运行成功了。 总结 简简单单的九部我就实现了网站运行的成功。那么现在我需要来实现我的Hello World叻。 找到urls.py进行修改文件 接下来在DjangoDemo文件夹下添加views.py文件,并添加如下代码 OK了,来F5运行看效果吧。 一切都那么的顺利。 本文链接:VS2013中Python学习笔记[Django Web的第一个网页],转载请注明。 阅读更多内容
本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 [自制简单操作系统] 7、多任务(二)――任务管理自动化&任务休眠 - beautifulzzzz 阅读原文» 前言 >_<" 这里仿照窗口管理的方式将任务管理也修改成相应的管理模式,这样可以灵活的添加多个任务,而不必每次都要修改任务切换函数;此外还在任务休眠做了尝试,通过将任务挂起和唤醒从而加快运行速度~ 一、任务管理自动化 >_<" 为了仿照窗口管理模式对任务进行管理,于是在bootpack.h里做如下定义: 1 /* mtask.c 任务切换相关*/ 2 #define MAX_TASKS 1000 /* 最大任务数量 */ 3 #define TASK_GDT0 3 /* 定义从GDT的几号开始分配给TSS */ 4 5 struct TSS32 {//task status segment 任务状态段 6 int backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;//保存的不是寄存器的数据,而是与任务设置相关的信息,在执行任务切换的时候这些成员不会被写入(backlink除外,某些情况下会被写入) 7 int eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;//32位寄存器 8 int es, cs, ss, ds, fs, gs;//16位寄存器 9 int ldtr, iomap;//有关任务设置部分 10 }; 11 struct TASK { 12 int sel, flags; /* sel用来存放GDT的编号 */ 13 struct TSS32 tss; 14 }; 15 struct TASKCTL { 16 int running; /* 正在运行的任务量数 */ 17 int now; /* 这个变量用来记录当前正在运行的任务是哪一个 */ 18 struct TASK *tasks[MAX_TASKS]; 19 struct TASK tasks0[MAX_TASKS]; 20 }; 21 extern struct TIMER *task_timer; 22 struct TASK *task_init(struct MEMMAN *memman);//初始化任务控制 23 struct TASK *task_alloc(void);//分配一个任务 24 void task_run(struct TASK *task);//将task添加到tasks的末尾,然后running加1 25 void task_switch(void);//running为1的时候不用进行任务切换,函数直接结束,当running大于2的时候,先把now加1 26 //再把now代表的任务切换成当前的任务,最后再将末尾的任务移到开头 PS:可以看出和窗口管理很相似,TASK是一个任务,TASKCTL是任务管理结构体 >_<" 下面是对应的任务管理.c文件,其中task_init函数是初始化任务控制,task_alloc是分配一个任务函数,task_run其实就相当于唤醒,task_switch任务切换 1 /* 任务管理相关程序 */ 2 3 #include "bootpack.h" 4 5 struct TASKCTL * taskctl; 6 struct TIMER * task_timer; 7 8 ///////////////////////////////////////////////////////////////////////////////////// 9 //功能:初始化任务控制 10 //参数: 11 //返回:返回一个内存地址,意思是现在正在运行这个程序,已经变成一个任务12 struct TASK *task_init( struct MEMMAN * memman) 13 { 14 int i; 15 struct TASK * task; 16 struct SEGMENT_DESCRIPTOR *gdt = ( struct SEGMENT_DESCRIPTOR * ) ADR_GDT; 17 taskctl = ( struct TASKCTL *) memman_alloc_4k(memman, sizeof ( struct TASKCTL)); //TASKCTL是个很大的结构体,所以要申请一个内存空间18 for (i = 0; i < MAX_TASKS; i++ ) { 19 taskctl->tasks0.flags = 0; 20 taskctl->tasks0.sel = (TASK_GDT0 + i) * 8; 21 set_segmdesc(gdt + TASK_GDT0 + i, 103, ( int) &taskctl->tasks0.tss, AR_TSS32); //定义在gdt的号,段长限制为103字节22 } 23 task = task_alloc(); 24 task->flags = 2; /* 活动中标志 */25 taskctl->running = 1; 26 taskctl->now = winform中ComboBox利用AutoComplete属性实现模糊查询(有缺陷) - 枫上善若水 阅读原文» 上一篇文章是用ComboBox里面的原生事件实现模糊查询,操作比较灵活一些,但是收到评论说,利用AutoComplete属性就可以实现模糊查询,但是据本人所了解,AutoComplete虽然能够方便的实现模糊查询,但是有一定的缺陷,就是,模糊查询只能从左往右。 上一篇连接地址:http://www.cnblogs.com/xilipu31/p/3993049.html 下面是简单的实现方式: 前台:一个简单的form窗体+ComboBox控件 后台:申明List<string> listOnit用于初始化ComboBox的备选数据,然后设置ComboBox属性:AutoCompleteSource(自动完成数据源),AutoCompleteMode(提示类型)以及AutoCompleteCustomSource(绑定数据源)。 具体代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;
namespace TimerDemo { public partial class Form3 : Form { //初始化绑定默认关键词(此数据源可以从数据库取) List<string> listOnit = new List<string>();
public Form3() { InitializeComponent(); }
private void Form3_Load(object sender, EventArgs e) { BindComboBox(); }
/// <summary> /// 绑定ComboBox /// </summary> private void BindComboBox() { listOnit.Add("张三"); listOnit.Add("张思"); listOnit.Add("张五"); listOnit.Add("王五"); listOnit.Add("刘宇"); listOnit.Add("马六"); listOnit.Add("孙楠"); listOnit.Add("那英"); listOnit.Add("刘欢");
//自动完成数据源 this.comboBox1.AutoCompleteSource = AutoCompleteSource.CustomSource; //提示类型 建议列表+自动补全 this.comboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend; //绑定数据源 this.comboBox1.AutoCompleteCustomSource.AddRange(listOnit.ToArray()); } } }
以下是实现效果截图: 从左到右输入关键词模糊查询(例如输入:张) 可以得出正确的提示和结果。 如果不是从左到右的模糊查询呢?(例如输入:三) 可以看出,并不能将模糊数据查询出来。 总结: ComboBox控件的AutoComplete事件可以用在模糊查询程度不高,从左到右的关键词搜索,如果想实现高级的模糊查询,还是自己定义的方式比较灵活一些。
本文链接:winform中ComboBox利用AutoComplete属性实现模糊查询(有缺陷),转载请注明。 阅读更多内容
本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 Python自动化运维Django入门 阅读原文» Python自动化运维Django入门 随着IT运维技术日益更新,近几年运维自动化越来越火,而且学习python的人非常的火爆,尤其是python自动化运维开发,得到了很多前辈的推崇,尤其是老男孩培训中心、老男孩老师、Alex老师等,在这里非常感谢你们。 这里我也记录一下以前学习Django的一点点心得和方法,方便以后自己查阅,如果能帮助初学者是最好的了!好的,其他不多说了,博文滴走起。 一、系统实战环境 | 系统版本:CnetOS6.5x86_64 Django版本:Django-1.5.8 MySQL版本:MySQL-5.1.73 Python版本:python-2.6.6 |
二、Django安装部署 首先去官网下载django主程序包,Django官方下载地址为:https://www.djangoproject.com/ 文件下载地址: https://www.djangoproject.com/download/1.5.8/tarball/ 1、Django-1.5.8.tar.gz安装方法: tar -xzf Django-1.5.8.tar.gz&&cd Django-1.5.8 ;python setup.py install 2、MySQL安装方法:yuminstall mysql mysql-server y 安装即可。 注* 如果有提示setuptools模块无法找到,需要先安装这个模块,安装的方法也是下载源码包,然后执行pythonsetup.py install 即可。 Django安装成功如下图: 那接下来我们要做的第一件事就是如何创建一个默认的django程序,怎么操作呢? 3、首先执行命令:django-admin.py |tail -15 可以看到django-admin.py后面接的所有的参数,其中有一个startproject参数含义为:启动一个新的工程。 4、然后执行命令:django-admin.py startproject firstweb ,会在当前目录创建一个名为firstweb这样一个工程名,进入firstweb目录,该目录下文件如下图,有一个manage.py这样一个脚本文件,同样执行它有很多参数,如何启动django呢,使用参数runserver,后面接监听地址和端口。 5、执行命令:python manage.py runserver 0.0.0.0:8080 如下图: 6、最后在浏览器访问我们的django程序如下图所示,则代表django搭建成功。 三、创建WebSite: 通过上面的搭建和部署,我们发现这是一个默认的django页面,那如何拥有我们自己的网站呢,我们能用django来做什么呢? 接下来创建一个自己的程序,程序的功能是打印Hello World,显示在web界面。 1、首先进入与manage.py同级的firstweb目录,firstweb目录里面有如下文件: | __init__.py__init__.pycsettings.pysettings.pycurls.pyurls.pycwsgi.pywsgi.pyc |
主要配置文件注解: settings.py主要功能:django设置使用。 Urls.py文件主要功能:配置URL访问控制。 2、新建views.py文件,写入以下内容: | from django.http import HttpResponse def hello(request): return HttpResponse( "Helloworld" ) |
内容注解:调用django.http模块里面的HttpResponse模块返回数据,然后定义一个hello函数,return返回函数内容。 3、配置urls.py 默认urls.py配置文件内容如下图: 在该配置文件里面添加两行记录,导入我们定义的hello模块,然后配置url访问即可。如下图: 需要添加的两行记录为: | fromfirstweb.views iAD域和SIP域不一致的情况下Lync边缘客户端登录问题解决 阅读原文» 每日博报 精彩不止一点 AD域和SIP域不一致的情况下Lync边缘客户端登录问题解决 返回顶部 阅读更多内容
|
|