java学习一个月了,没有什么进展,期间又是复习Linux,又是看Android,瞻前顾后,感觉自己真的是贪得无厌,
学习的东西广而不精,所以写出的文章也就只能泛泛而谈。五一小长假,哪里都没有去,也不想去,刚刚无聊刷新了下
朋友圈,朋友们不是在玩,就是在吃,突然一下子感觉自己老了许多。岁月真是把杀猪刀,夺走了我们的青春,但却无
法夺走我们的激情。
好好复习了!
在老师引领下,算是把人生中的第一个Java项目敲完了,感觉对于学习OOP的朋友,应该有所帮助,先做个笔记吧
等后期有时间再添些自己的Feature。
import javax.swing.JFrame;
/**
* 游戏窗口
* @author Manue1
* @version 1.0
*
*/
public class GameFrame extends JFrame{
private static final long serialVersionUID = 1L;
private Tetris tetris;
public GameFrame(){
tetris =new Tetris();
add(tetris);
setSize(530,580);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args){
GameFrame frame =new GameFrame();
frame.setVisible(true);
frame.tetris.action(); //创建4个格子
}
}
2
3 import java.awt.image.BufferedImage;
4
5 /**
6 * 定义格子
7 * @author Manue1
8 */
9 public class Cell extends Object{
10 private int row; int col;
11 private BufferedImage image;
12
13 public Cell(int row, int col, BufferedImage image) {
14 super();
15 this.row = row;
16 this.col = col;
17 this.image = image;
18 }
19
20 public int getRow() {
21 return row;
22 }
23
24 public void setRow(int row) {
25 this.row = row;
26 }
27
28 public int getCol() {
29 return col;
30 }
31
32 public void setCol(int col) {
33 this.col = col;
34 }
35
36 public BufferedImage getImage() {
37 return image;
38 }
39
40 public void setImage(BufferedImage image) {
41 this.image = image;
42 }
43
44 @Override
45 public String toString() {
46 return "Cell [col=" + col + ", image=" + image + ", row=" + row + "]";
47 }
48
49
50 public void moveLeft(){
51 col--;
52 }
53 public void moveRight(){
54 col++;
55 }
56 public QQ5.0左侧滑动显示效果 - 小破孩123 阅读原文»
前三篇为大家介绍了如何实现简单的类QQ5.0左侧的侧滑效果,本篇我将带领大家一起探讨一下如何真正实现QQ5.0左侧的侧滑效果,对于本篇的内容与之前的三篇关联性很强,如果前三篇你已经完全掌握,对于这一篇相信也没有什么难处,本篇的重点在于通过Android3.0以后提供的属性动画实现上述显示特效。
开始之前首先给大家说句抱歉,前三篇由于我自己的编码问题,导致如果你还是以之前的代码设计时,会出现Menu的背景图没有填充整个屏幕,这个怎么解决呢?
在left_menu.xml中,将background修改为android:background="#0000";
activity_main.xml代码:
xmlns:tools="http://schemas.android.com/tools"
xmlns:hyman="http://schemas.android.com/apk/res/com.example.android_qq_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<com.example.menu.SlidingMenu
android:id="@+id/slidingMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/img_frame_background"
hyman:rightPadding="100dp" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<include layout="@layout/left_menu"/>"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/qq"
>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切换按钮"
/>
</LinearLayout>
</LinearLayout>
</com.example.menu.SlidingMenu>
</RelativeLayout>
将背景图片添加蓝色标注处。
其他部分无需改变,下面我们开始分析如何通过属性动画来实现上述效果:
* 实现抽屉式侧滑效果
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {//l相当于getScrollX()表示Menu左侧的偏移量
super.onScrollChanged(l, t, oldl, oldt);
/**
* 区别1:内容区域1.0~0.7 缩放的效果 scale : 1.0~0.0 0.7 + 0.3 * scale
*
* 区别2:菜单的偏移量需要修改
*
* 区别3:菜单的显示时有缩放以及透明度变化 缩放:0.7 ~1.0 1.0 - scale * 0.3 透明度 0.6 ~ 1.0
* 0.6+ 0.4 * (1- scale) ;
*
*/
//设置Menu的显示OR隐藏动画
float scroll = l * 1.0f /mMenuWidth;//1~0
ViewHelper.setTranslationX(mMenu, mMenuWidth*scroll*0.7f);
//设置Menu的透明度变化
float leftScale = 0.6f+ 0.4f * (1- scroll);
ViewHelper.setScaleX(mMenu, leftScale);
ViewHelper.setScaleY(mMenu, leftScale);
//设置Menu的缩放比例
float leftAlpha = 1.0f - scroll * 0.3f;
ViewHelper.setAlpha(mMenu, leftAlpha);
//设置Content的缩放中心
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight()/2);
//设置Content的透明度变化
float rightScale = 0.7f + 0.3f * scroll;
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);
}
需要提示的就是对于Android3.0以下的系统,不支持属性动画效果,在这里我导入了一个包,大家如果需要可以留言。好了,到这里我们的侧滑效果就完全为大家实现了,请欣赏效果图:
本文链接:QQ5.0左侧滑动显示效果,转载请注明。
关于企业邮箱服务器经常被spamhaus反垃圾邮件组织拦截的排错方法分享
其实在企业邮件平台管理过程中,企业邮箱管理员经常会被各种各样的邮箱问题所困扰,而困扰最大的除了服务器规划不当带来的后期服务器维护的困难外,还有最致命也是最让邮件管理员着急的事情,那就是企业邮箱经常被一些国际反垃圾邮件组织列为黑名单,也许,很多人会在想,如果是列为了黑名单,那么直接进行申诉,释放就可以了,这个回答其实也勉强可以算是对的,但是从申诉到释放,其实也是需要等待一个时间的,那么这时出现大批量的用户反映,我个人认为这其实也是邮件平台不稳定的一个体现,做为管理员,则必须要了解被列为黑名单的根本原因,当然最核心的还是需要在规划邮件平台架构时,就能够合理规划系统结构及网络结构才能有一个更为稳定的邮件平台结构,在下面呢,我就分享一个较为不常见的典型案例。
在之前一段时间,在处理一些邮件技术支持工作时,遇到了企业邮箱服务器频繁被国际反垃圾联盟列为黑名单的问题,而且频率极高,基本一天至少3次,这其实从3次的意义来看,这已经不是单纯的服务器故障,很有可能我们对外部提供的公网邮件地址已经被反垃圾联盟盯上啦,那么我们是每天3次,甚至是凌晨也在向反垃圾联盟申诉呢?还是自己想想哪里出现了问题?当然,我相信,偶尔出一次被列黑名单,申诉后问题解决,那还是正常的,毕竟有时反垃圾联盟也会有误判嘛。而这次出现的问题,则很明显不是误判哦,所以还是需要找到根本原因的。
在这次故障中,我用了一个最为简单的方式,也是之前处理这类问题时的一个经验性方法,反查telnet其它公司的邮件服务器时,返回值是多少?这个返回值当然指你去telnet对端邮件服务器IP时,对端回显你的发起连接的IP是多少?
其实在当时有人就提出了质疑,你去telnet对端邮件平台有意义吗?当然是有意义的,从排查思路来看,Exchange服务器各项服务正常,网络链路通,那么还有哪里会有问题,如果有实施Exchange经验的话,会知道,最后一步那是进行端口映射。所以我们不妨来看看端口映射情况,在向网络工程师查询映射前,你不妨像我一样做下面这样一件事情。
1.在办公网平台下,telnet其它支持telnet 回显的邮件组织,查看回显回来什么地址。
2.在邮件网关或Exchange 器服务器上telnet支持telnet回显的,邮件组织,查看回显回来是什么地址。
为什么要做这2步呢?如果两者回显是不同地址还好,但是如果两者回显均为邮件网关地址呢?这就是有问题的,毕竟我们发布25端口一般也只是对邮件平台,而如果办公网随意一台机器telnet其它邮件组织邮件服务器,都是邮件网关地址,那么意味着什么,相信我们邮件管理员都很清楚的。
最终也通过网络映射看到并验证了我的分析结果,当时网络层面为了简单,直接把整个办公网地址25端口映射为了邮件网关公网地址,为此,我要求重新做了映射,保证邮件公网IP仅用于邮件网关,不得做于其它映射使用,调整映射服务器范围后,观察了1个月,没有再出现被反垃圾联盟拦截的问题。
以上也只是我在分析这类被国际反垃圾邮件联盟列为黑名单时的个列处理方法,希望对有类似问题的博友看完能有一些帮助。
本文出自 "笨鸟先飞" 博客,请务必保留此出处http://tingdongwang.blog.51cto.com/1056852/1640227
最近公司来了一个陕北的实习妹子,据说家里是开矿的,人长得一般,但很有气质。开矿的,当然钱很多了。以前在大学有个同学,家里是开油田的,有节毛概课,老师说西安的房价都是陕北人轰起来的,西安人都怨陕北人。我这个同学听了不开心了,周末直接在东西南北各买一套。牛逼啊,让你老师多嘴。这几天周围的同事心思都在这个姑娘身上,装作喝咖啡过去瞄一眼,或者站起来瞅瞅背影。IT爷们真的是空虚,IT界无美女啊,还是吉日嘎啦说的好,公司有美女,可以提升爷们的战斗力。
OK,今天我们来看一下新闻审核界面,本来这节是要说ueditor上传图片到mongoDB,但是最近实在精力有限,先放放,稍后再上博客。我们先看一下界面,提提神。
这个界面上面部分是查询,采用响应式布局方式。当在手机或者pad的浏览器上的时候,依然能够正常显示并使用。
OK,我们今天主要看的不是界面,还是看功能的实现。
首先先看一下查询功能,查询有个新闻类别的下拉列表,后台Action代码如下
[HttpGet] public JsonResult GetNewsTypeList() { List<NewsTypesEntity> newsTypeEntityList = NewsMngBiz.GetInstance().GetNewsTypes(); newsTypeEntityList.Insert(0, new NewsTypesEntity() { TransactionNumber = null, NewsTypeName = CommonResouce.DefaultSelectText }); return Json(newsTypeEntityList, JsonRequestBehavior.AllowGet); }
OK,接下来我们就要看界面了
@{ Layout = null; } <div ng-app="newsAuditModule" ng-controller="newsAuditController" id="div_newsAudit" class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title"> <img class="img-panel-title" src="~/Images/Base/audit.png" /> <b>新闻审核</b> </h3> </div> <div class="panel-body"> <div class="row" style="line-height:30px"> <label for="newsTitle" class="col-sm-2 control-label">新闻标题</label> <div class="col-sm-10"> <input type="text" maxlength="100" class="form-control" id="newsTitle" ng-model="newsTitle" placeholder="请输入新闻标题查询"> </div> </div> <div class="row" style="margin-top: 5px; margin-bottom: 5px; line-height: 30px"> <label for="newsTitle" class="col-sm-2 control-label">新闻类别</label> <div class="col-sm-10"> <select id="newsTitle" class="form-control" ng-model="newsType"> @*<option value="">---请选择---</option>*@ <option ng-repeat="type in NewsTypeList" value="{{type.TransactionNumber}}">{{type.NewsTypeName}}</option> </select> </div> </div> <div class="row" style="line-height:30px"> <label for="newsTitle" class="col-sm-2 control-label">审核状态</label> <div class="col-sm-10"> <select id="newsTitle" class="form-control" ng-model="newsState"> <option value="">---请选择---</option> <option value="-1">未审核</option> <option value="0">未通过</option> <option value="1">通过</option> </select> </div> </div> <div class="row" style="margin-top:10px"> <div class="col-sm-3"> <button type="button" class="btn btn-primary btn-form-width" ng-click="getDataList()">查询</button> </div> </div> <div class="pre-scroll" style="margin-top:10px"> <table class="table table-bordered table-striped table-hover" ng-init="load()"> <tr style="background-color: #428bca; color: white"> <th><input type="checkbox" ng-model="isCheckAll" ng-change="setCheckState()"></th> <th>新闻标题</th> <th>新闻类别</th> <th>创建日期</th> <th>审核状态</th> <th>审核人</th> <th>审核日期</th> <th>操作</th> </tr> <tr ng-repeat="newsEntity in NewsList"> <td><input id="chk_{{newsEntity.TransactionNumber}}" type="checkbox" ng-model="newsEntity.IsChecked" /></td> <td title="{{newsEntity.Title}}">{{newsEntity.SubTitle}}</td> <td>{{newsEntity.InforType}}</td> <td>{{newsEntity.InDate.slice(6,-2)|date:'yyyy-MM-dd'}}</td> <td style="color:{{ newsEntity.Color }}">{{newsEntity.AuditStatus}}</td> <td>{{newsEntity.AuditUserName}}</td> <td>{{newsEntity.AuditDate.slice(6,-2)|date:'yyyy-MM-dd'}}</td> <td> <span style="cursor:pointer;"> <a href="#"><img title="浏览" alt="" src="~/Images/Base/preview.png" class="img-table-column" /></a> <a href="#"><img title="审核" ng-click="auditModalShow(newsEntity)" alt="" src="~/Images/Base/key.png" class="img-table-column" /></a> </span> </td> </tr> </table> </div> <div class="btn-group dropup"> <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> 批量操作<span class="caret"></span> </button> <ul class="dropdown-menu" role="menu"> <li><a href="#" ng-click="batchOperation('A')">批量通过</a></li> <li class="divider"></li> <li><a href="#" ng-click="batchOperation('D')">批量删除</a></li> </ul> </div> </div> <div class="modal fade" id="newAuditModal" tabindex="-1" role="dialog" aria-labelledby="auditModalTitle" aria-hidden="true" data-backdrop="static"> <div class="modal-dialog"> <div class="modal-content" style="width:550px"> <div class="modal-header" style="background-color: #009966;height:45px;line-height:45px"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button> <h5 class="modal-title" id="auditModalTitle" style="color:white"> 新闻审核 </h5> </div> <div class="modal-body"> <div class="form-horizontal"> <div class="form-group"> <label class="col-md-3" for="labTitle">新闻标题:</label> <div class="col-md-9"> <label id="labTitle"></label> </div> </div> <div class="form-group"> <label class="col-md-3">审核结果:</label> <div class="col-md-9"> <input type="radio" name="radAuditResult" ng-change="setAuditResaonEditable()" value="1" checked ng-model="AuditResult"> 通过 <input type="radio" name="radAuditResult" ng-change="setAuditResaonEditable()" value="0" ng-model="AuditResult" style="margin-left:10px"> 不通过 </div> </div> <div class="form-group"> <label class="col-md-3" for="div_reason">未通过原因:</label> <div class="col-md-9"> <div id="div_reason" style="border: 1px solid #003366; height: 90px; word-break: break-all;max-height:90px;overflow-y:scroll" contenteditable="true"></div> </div> </div> </div>
2015年4月28日星期二
高性能集群软件Keepalived之基础知识篇
一、Keepalived介绍
Keepalived是Linux下一个轻量级的高可用解决方案,它与HeartBeat、RoseHA实现的功能类似,都可以实现服务或者网络的高可用,但是又有差别:HeartBeat是一个专业的、功能完善的高可用软件,它提供了HA软件所需的基本功能,比如心跳检测和资源接管,监测集群中的系统服务,在群集节点间转移共享IP地址的所有者等,HeartBeat功能强大,但是部署和使用相对比较麻烦;与HeartBeat相比,Keepalived主要是通过虚拟路由冗余来实现高可用功能,虽然它没有HeartBeat功能强大,但Keepalived部署和使用非常简单,所有配置只需一个配置文件即可完成。这也是本章重点介绍Keepalived的原因。
二、Keepalived是什么
Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态。它根据layer3, 4 & 5交换机制检测每个服务节点的状态,如果某个服务节点出现异常,或工作出现故障,Keepalived将检测到,并将出现故障的服务节点从集群系统中剔除,而在故障节点恢复正常后,Keepalived又可以自动将此服务节点重新加入到服务器集群中,这些工作全部自动完成,不需要人工干涉,需要人工完成的只是修复出现故障的服务节点。
Keepalived后来又加入了VRRP的功能,VRRP是Virtual Router Redundancy Protocol(虚拟路由器冗余协议)的缩写,它出现的目的是为了解决静态路由出现的单点故障问题,通过VRRP可以实现网络不间断地、稳定地运行。因此,Keepalived一方面具有服务器状态检测和故障隔离功能,另一方面也具有HA cluster功能.下面详细介绍下VRRP协议的实现过程。
三、 VRRP协议与工作原理
在现实的网络环境中,主机之间的通信都是通过配置静态路由(默认网关)完成的,而主机之间的路由器一旦出现故障,通信就会失败,因此,在这种通信模式中,路由器就成了一个单点瓶颈,为了解决这个问题,就引入了VRRP协议。
熟悉网络的读者对VRRP协议应该并不陌生。它是一种主备模式的协议,通过VRRP可以在网络发生故障时透明地进行设备切换而不影响主机间的数据通信,这其中涉及两个概念:物理路由器和虚拟路由器。
VRRP可以将两台或多台物理路由器设备虚拟成一个虚拟路由器,这个虚拟路由器通过虚拟IP(一个或多个)对外提供服务,而在虚拟路由器内部,是多个物理路由器协同工作,同一时间只有一台物理路由器对外提供服务,这台物理路由器被称为主路由器(处于MASTER角色)。一般情况下MASTER由选举算法产生,它拥有对外服务的虚拟IP,提供各种网络功能,如ARP请求、ICMP、数据转发等。而其他物理路由器不拥有对外的虚拟IP,也不提供对外网络功能,仅仅接收MASTER的VRRP状态通告信息,这些路由器被统称为备份路由器(处于BACKUP角色)。当主路由器失效时,处于BACKUP角色的备份路由器将重新进行选举,产生一个新的主路由器进入MASTER角色继续提供对外服务,整个切换过程对用户来说完全透明。
每个虚拟路由器都有一个唯一标识,称为VRID,一个VRID与一组IP地址构成了一个虚拟路由器。在VRRP协议中,所有的报文都是通过IP多播形式发送的,而在一个虚拟路由器中,只有处于MASTER角色的路由器会一直发送VRRP数据包,处于BACKUP角色的路由器只接收MASTER发过来的报文信息,用来监控MASTER运行状态,因此,不会发生BACKUP抢占的现象,除非它的优先级更高。而当MASTER不可用时,BACKUP也就无法收到MASTER发过来的报文信息,于是就认定MASTER出现故障,接着多台BACKUP就会进行选举,优先级最高的BACKUP将成为新的MASTER,这种选举并进行角色切换的过程非常快,因而也就保证了服务的持续可用性。
四、Keepalived工作原理
上节简单介绍了Keepalived通过VRRP实现高可用功能的工作原理,而Keepalived作为一个高性能集群软件,它还能实现对集群中服务器运行状态的监控及故障隔离。下面继续介绍下Keepalived对服务器运行状态监控和检测的工作原理。
Keepalived工作在TCP/IP参考模型的第三、第四和第五层,也就是网络层、传输层和应用层。根据TCP/IP参考模型各层所能实现的功能,Keepalived运行机制如下。
在网络层,运行着四个重要的协议:互连网协议IP、互连网控制报文协议ICMP、地址转换协议ARP以及反向地址转换协议RARP。Keepalived在网络层采用的最常见的工作方式是通过ICMP协议向服务器集群中的每个节点发送一个ICMP的数据包(类似于ping实现的功能),如果某个节点没有返回响应数据包,那么就认为此节点发生了故障,Keepalived将报告此节点失效,并从服务器集群中剔除故障节点。
在传输层,提供了两个主要的协议:传输控制协议TCP和用户数据协议UDP。传输控制协议TCP可以提供可靠的数据传输服务,IP地址和端口,代表一个TCP连接的一个连接端。要获得TCP服务,须在发送机的一个端口上和接收机的一个端口上建立连接,而Keepalived在传输层就是利用TCP协议的端口连接和扫描技术来判断集群节点是否正常的。比如,对于常见的Web服务默认的80端口、SSH服务默认的22端口等,Keepalived一旦在传输层探测到这些端口没有响应数据返回,就认为这些端口发生异常,然后强制将此端口对应的节点从服务器集群组中移除。
在应用层,可以运行FTP、TELNET、SMTP、DNS等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived的工作方式,例如用户可以通过编写程序来运行Keepalived,而Keepalived将根据用户的设定检测各种程序或服务是否允许正常,如果Keepalived的检测结果与用户设定不一致时,Keepalived将把对应的服务从服务器中移除。
五、Keepalived的体系结构
Keepalived是一个高度模块化的软件,结构简单,但扩展性很强,如有兴趣的读者,可以阅读下Keepalived的源码。下图是官方给出的Keepalived体系结构拓扑图。
从图中可以看出,Keepalived的体系结构从整体上分为两层,分别是用户空间层(User Space)和内核空间层(Kernel Space).下面介绍Keepalived两层结构的详细组成及实现的功能。
内核空间层处于最底层,它包括IPVS和NETLINK两个模块。IPVS模块是Keepalived引入的一个第三方模块,通过IPVS可以实现基于IP的负载均衡集群。IPVS默认包含在LVS集群软件中。而对于LVS集群软件,相信做运维的朋友并不陌生:在LVS集群中,IPVS安装在一个叫做Director Server的服务器上,同时在Director Server上虚拟出一个IP地址来对外提供服务,而用户必须通过这个虚拟IP地址才能访问服务。这个虚拟IP一般称为LVS的VIP,即Virtual IP。访问的请求首先经过VIP到达Director Server,然后由Director Server从服务器集群节点中选取一个服务节点响应用户的请求。
Keepalived最初就是为LVS提供服务的,由于Keepalived可以实现对集群节点的状态检测,而IPVS可以实现负载均衡功能,因此,Keepalived借助于第三方模块IPVS就可以很方便地搭建一套负载均衡系统。在这里有个误区,由于Keepalived可以和IPVS一起很好地工作,因此很多初学者都以为Keepalived就是一个负载均衡软件,这种理解是错误的。
在Keepalived中,IPVS模块是可配置的,如果需要负载均衡功能,可以在编译Keepalived时打开负载均衡功能,反正,也可以通过配置编译参数关闭。
NETLINK模块主要用于实现一些高级路由框架和一些相关的网络功能,完成用户空间层Netlink Reflector模块发来的各种网络请求。
用户空间层位于内核空间层之上,Keepalived的所有具体功能都在这里实现,下面介绍、几个重要部分所实现的功能。
在用户空间层,Keepalived又分为四个部分,分别是Scheduler I/O Multiplexer、Memory Management、Control Plane和Core components。其中,Scheduler I/O Multiplexer是一个I/O复用分发调度器,它负责安排Keepalived所有内部的任务请求。Memory Management是一个内存管理机制,这个框架提供了访问内存的一些通用方法。Control Plane是Keepalived的控制面板,可以实现对配置文件进行编译和解析,Keepalived的配置文件解析比较特殊,它并不是一次解析所有模块的配置,而是只有在用到某模块时才解析相应的配置。最后详细说一下Core components,这个部分是Keepalived的核心组件,包含了一些列功能模块,主要有WatchDog、Checkers、VRRP Stack、IPVS wrapper和Netlink Reflector,下面介绍每个模块所实现的功能如下。
(1)WatchDog
WatchDog是计算机可靠性领域中一个极为简单又非常有效的检测工具,它的工作原理是针对被监视的目标设置一个计数器和一个阈值,WatchDog会自己增加此计数值,然后等待被监视的目标周期性地重置该计数值。一旦被监控目标发生错误,就无法重置此计数值,WatchDog就会检测到,于是就采取对应的恢复措施,例如重启或关闭。
在Linux中很早就引入了WatchDog功能,而Keepalived正是通过WatchDog的运行机制来监控Checkers和VRRP进程的。
(2)Checkers
这是Keepalived最基础的功能,也是最主要的功能,可实现对服务器运行状态检测和故障隔离。
(3)VRRP Stack
这是Keepalived后来引入的VRRP功能,可以实现HA集群中失败切换(Failover)功能。Keepalived通过VRRP功能再结合LVS负载均衡软件即可部署一套高性能的负载均衡集群系统。
(4)IPVS wrapper
本文不打算解释AOP的相关专业名词和概念,仅通过几个代码示例来展示Aspectj(对AOP实现的)的基本使用,并且使用的Aspectj是目前最新版本。
1.搭建环境
本文使用Maven来构建工程,通过aspectj-maven-plugin插件来编译*.aj文件至.class。
Maven的具体配置:
< groupId >org.codehaus.mojo</ groupId > < artifactId >aspectj-maven-plugin</ artifactId > < version >1.7</ version > < complianceLevel >1.6</ complianceLevel > |
在上面的configuration节点下可以配置
< aspectDirectory ></ aspectDirectory > |
默认是src/main/aspect , 可以根据需要进行设置。
配置aspectj运行时环境依赖jar
< groupId >org.aspectj</ groupId > < artifactId >aspectjrt</ artifactId > < version >1.8.2</ version > |
2.创建一个普通的Java类(Simple.java),为接下来使用Aspectj来植入相应功能做准备
package com.rft.fdsi.server.aop; public class Simple{ System.out.println( "[src]staticinit" ); public Simple(){ System.out.println( "[src]construct" ); public Stringwelcome(Stringname){ System.out.println( "[src]===========start===========" ); System.out.println( "[src]welcomemethodexecute" ); System.out.println( "[src]welcomemethodexecute" ); System.out.println( "[src]===========end===========" ); //thrownewRuntimeException("runtimeexception"); return "welcome" +name; public static void main(String[]args){ Simplesimple= new Simple(); Stringgreeting=simple.welcome( "Jack" ); System.out.println(greeting); |
3.创建一个针对Simple类的静态代码块初始化,构造方法执行,方法调用进行植入功能的方面类(SimpleAspect.aj)。
package com.rft.fdsi.server.aop; public aspectSimpleAspect{ public pointcutstaticInit():staticinitialization(com.rft.fdsi.server.aop.Simple); before():staticInit(){ System.out.println( "" +thisJoinPointStaticPart.getSignature().getName()); after()returning():staticInit(){ System.out.println( "[afterreturning]" +thisJoinPointStaticPart.getSignature().getName()); before():call( public com.rft.fdsi.server.aop.*. new ()){ System.out.println( "" +thisJoinPoint.getSignature().getName()); after():call( public com.rft.fdsi.server.aop.*. new ()){ System.out.println( "[after]" +thisJoinPoint.getSignature().getName()); public pointcutwelcomeMethod(Stringname):call( public Stringcom.rft.fdsi.server..*.welcome(String))&&args(name); before(Stringname):welcomeMethod(name){ .println( "" +thisJoinPoint.getTarget().getClass()阅读更多内容 javascript 数组简明总结 - 段隆贤 本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 javascript 数组简明总结 - 段隆贤 阅读原文»
定义 var empty=[];
何时使用 当属性名是小而连续的整数时,使用数据组,否则使用对象。
识别 typeof运算符对数据没有意义,因为返回的是'object' Array.isArray=function(obj) { return Object.prototype.toString.apply(obj)==='[object Array]' }
长度 array=[]; 设置更大length不会给数组分配更多的空间(undefined),而把length设小将导致所有下标等于新的length的属性被删除。
添加 添加一个元素:
删除 delete numbers[2]; //留下一个空洞
查找 //IE9+ 支持
输出 alert(array.toString()); alert(array.valueOf()); alert(array); alert(array.join(','));
方法
array.concat() //连接字符串,相当于‘+’
array.push()
array.shift()
array.reverse() //反排序
array.slice()
排序 数据原型中有sort的方法(Array.prototype.sort ),但只对字符排序 function sortNumber(a, b) { return a - b } var arr = new Array(6) arr[0] = "10" arr[1] = "5" arr[2] = "40" arr[3] = "25" arr[4] = "1000" arr[5] = "1" document.write(arr + "<br />") //字符排序 document.write(arr.sort() + "<br />") //1,10,1000,25,40,5 //数据排序 document.write(arr.sort(sortNumber)) //1,5,10,25,40,1000
迭代 在此只介绍简单用法.//以下只支持ECMA5 every() //每一个都满足条件返回true filter() //返回满足条件的子数组 forEach() //对每一个元素进行操作,不返回 map() //对每一个元素进行操作,返回结果数组 some()//有一个满足条件返回true
归并 当前后项有关系时实现的操作,方便实现双向链表的功能. //以下只支持ECMA5 reduce() reduceRight()
编码规范 以下来自GitHub,有很多关于javascript优秀的编程风格,推荐大家看看:https://github.com/airbnb/javascript
本文链接:javascript 数组简明总结,转载请注明。 【大前端之前后分离】JS前端渲染VS服务器端渲染 - 叶小钗 阅读原文»
前言 之前看了一篇文章:@Charlie.Zheng Web系统开发构架再思考-前后端的完全分离,文中论述了为何要前后分离,站在前端的角度来看,是很有必要的;但是如何说服团队使用前端渲染方案却是一个现实问题,因为如果我是一个服务器端,我便会觉得不是很有必要,为什么要前后分离,前后分离后遗留了什么问题,如何解决,都得说清楚,这样才能说服团队使用前端渲染的方案,而最近我刚好遇到了框架选型的抉择。 来到新公司开始新项目了,需要做前端框架选型,因为之前内部同事采用的fis框架,而这边又是使用的php,这次也就直接采用fis基于php的解决方案: 说句实话,fis这套框架做的不错,但是如果使用php方案的话,我就需要蛋疼的在其中写smarty模板,然后完全按照规范走,虽然fis规范比较合理,也可以接受,但是稍微深入解后发现fis基于php的方案可以概括为(我们的框架用成这样,不特指fis): 服务器端渲染html全部图给浏览器,再加载前端js处理逻辑 显然,这个不是我要的,梦想中的工作方式是做到静态html化,静态html装载js,使用json进行业务数据通信,这就是一些朋友所谓的前端渲染了 JS渲染的鄙利 前端渲染会带来很多好处: ① 完全释放前端,运行不需要服务器; ② 服务器端只提供接口数据服务,业务逻辑全部在前端,前后分离; ③ 一些地方性能有所提升,比如服务器不需要解析index.html,直接返回即可; ④ ...... 事实上以上的说法和优势皆没有十足的说服力,根据上述因素,我们知道了为什么我们要采用js+json的方案,但这不代表应该采用。 比如很多朋友认为前后分离可以让前端代码更加清晰,这一说法我就十分不认同,如果前端代码功力不够,绝对可以写成天书,分离是必要条件,却不是分离后前端就一定清晰,否则也不会有那么多人呼吁模块化、组件化;而且服务器端完全可以质疑这样做的种种问题,比如: ① 前端模板解析对手机端的负担,对手机电池产生更快的消耗; ② 前端渲染页面内容不能被爬虫识别,SEO等于没有了; ③ 前端渲染现阶段没有完善的ABTesting方案; ④ 不能保证一个URL每次展示的内容一致,比如js分页导致路由不一致; ⑤ ...... 以上的问题,一些是难点,一些是痛点,选取前端渲染方案至少得有SEO解决方案,不然一切都是空谈 所以有如此多的问题,前端凭什么说服团队使用前端渲染的方案,难道仅仅是我们爽了,我们觉得这样好就可以了吗? 况且现状是团队中服务器端的同事资深的多,前端话语权不够,这个时候需要用数据说话,但未做调研也拿不出数据,没有数据你凭什么说服领导采用前端渲染方案? 为什么要采用前端渲染 最近两年我却找到了可以说服自己采用前端渲染的原因: ① 体验更好 ② Hybrid内嵌只能用静态文件 事实上我们不能用数据说明webapp(前端渲染)的体验就一定比服务器端渲染好,所以Hybrid内嵌就变成了主要的因素,现有的Hybrid有两种方案: ① webview直连线上站点,响应速度慢,没有升级负担,离线应用不易; ② 将静态html+js+css打包进native中,直接走file模式访问,交互走json,非常简单就可以实现离线应用(某些页面的离线应用) 现在一个产品一般三套应用:PC、H5站点、APP,PC站点早就形成,H5站点一般与APP同步开发,Hybrid中的逻辑与H5的逻辑大同小异,所以 H5站点与Hybrid中的静态文件使用一套代码,这个是使用前端渲染的主要原因,意思是H5程序结束,APP就完成80%了。 因为服务器端渲染需要使用动态语言,而webview只能解析html等静态文件,所以使用前端渲染就变成了必须,而这一套说辞基本可以说服多数人,自少我是信了。 拦路虎-SEO 上面说了很多前端渲染的问题,什么手机性能、手机耗电、ABTesting都不是痛点,唯一难受的是H5站点的SEO,以原来公司酒店订单来说,有20%以上的流量来源于H5站点,浏览器是一个流量的重要来源,SEO不可丢弃。 PS:这次我在公司和同事说前端渲染SEO有问题,结果同事说,百度的产品SEO肯定靠前不用考虑,真不要考虑吗...... 所以前端渲染必须有解决SEO的方案,并且方法不能太烂,否则框架出来了也没人愿意用,好在这次做的项目不是webapp,SEO方案相对要简单一点,移动端展示的信息少SEO不会太难,这个进一步降低了我们的实现难度,经过几轮摸索,我这两天想了一个简单的方案,正在验证可行性。 JS渲染应该如何做 前端渲染应该如何做?阿里的大神们事实上一直也在思考方案,并且似乎已经有成功的产出:前后端分离的思考与实践(二) 可惜,读过文章后,依旧没有获得对自己有用的信息,并且对应的代码也看不到,自己之前的方案:探讨webapp的SEO难题(上),连自己都觉得非常戳而没有继续。 编译的过程 而最近在公司内部使用fis时候,一段代码引起了我的兴趣: {%block name="body"%} {%widget name="webapp:widget/index/route/route.tpl"%} {%widget name="webapp:widget/index/searchCity/searchCity.tpl"%} {%widget name="webapp:widget/index/selectDate/selectDate.tpl"%} {%/block%} 这段代码基于smarty模板,运行会经过一次release过程,将真正的route模板字符串与服务器data形成最终的html,这段代码引起了我的思考,却说不出来什么问题。 我偶然又看到了之前的react解决方案,似乎也有一个编译的过程: React.render( // 这是什么不是字符串,不是数字,又不是变量的参数……WTF <h1>Hello, world!</h1>, document.getElementById('example') ); //JSX编译转换为javascript==> React.render( React.DOM.h1(null, 'Hello, world!'), document.getElementyById('example') ); 所以,在程序真实运行前有一个编译的过程,一个是编译才能运行,一个是运行时候需要编译,于是我在想前端渲染可以这样做吗? 页面渲染的条件 比较简单的情况下,对于前端来说,页面html的组成需要数据与模板,而服务器也仅仅需要数据与模板,所以简单来说: html = data + template 前后端的模板有所不同的是: 前端模板也许不能被服务器解析,如果模板中存在js函数,服务器模板将无法执行 但是经过我们之前的研究,.net可以运行一个V8的环境帮助解析模板,java等也有相关的类库,所以此问题不予关注,第二个问题是: 前端数据为异步加载,服务器端为同步加载,但是: 简单情况下,服务器端与前端数据请求需要的仅仅是URL与参数 于是,一个方案似乎变的可能。 前端渲染方案 入口页 将如我们的index.html是这样的: debug端: <!DOCTYPE html>
<html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="text/javascript" src="./libs/zepto.js"></script> <script type="text/javascript" src="./libs/underscore.js"></script> <script type="text/javascript" src="./libs/require.js"></script> </head> <body> <% 2015年4月27日星期一2015年4月26日星期日2015年4月25日星期六.NET出现频率非常高的笔试题 - 邹琼俊 本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 .NET出现频率非常高的笔试题 - 邹琼俊 阅读原文»
一、.net基础 1、 a=10,b=15,请在不使用第三方变量的情况下,把a、b的值互换 答:小学算法,加法交换律和加法结合律 int a=a+b; int b=a-b;int a=a-b; 2、session喜欢丢值且占内存,Cookis不安全,请问用什么办法代替这两种原始的方法 答:redis 或者 memcache。当然,微软也提供了解决方案。iis中由于有进程回收机制,系统繁忙的话Session会丢失,可以用Sate server或SQL Server数据库的方式 存储Session不过这种方式比较慢,而且无法捕获Session的END事件。 3、如何处理几十万条并发数据? 答:用存储过程或事务。取得最大标识的时候同时更新..注意主键不是自增量方式这种方法并发的时候是不会有重复主键的..取得最大标识要有一个存储过程来获取. 4、62-63=1 等式不成立,请移动一个数字(不可以移动减号和等于号),使得等式成立,如何移动? 答案:62移动成2的6次方 5、<%# %> 和 <% %> 有什么区别? 答:<%# %>表示绑定的数据源,<% %>是服务器端代码块 6、ASP.Net页面生命周期简单描述 每个页面的生命周期为用户的每一次访问,也就是说每一次客户端与服务器之间的一个往返过程.全局变量的生命周期在此之间. 1. Page_Init(); 2. Load ViewState and Postback data; 3. Page_Load(); 4. Handle control events; 5. Page_PreRender(); 6. Page_Render(); 7. Unload event; 8. Dispose method called; 7、写出程序的输出结果 A B A.Fun() 8、 写出程序的输出结果: 2 5 1 6 9、在下面的例子里 答:X=1,Y=0;x= 1 y = -1 10、如何提高.NET的性能 1. 使用异步方式调用Web服务和远程对象 只要有可能就要避免在请求的处理过程中对Web服务和远程对象的同步调用,因为它占用的是的ASP.NET 线程池中的工作线程,这将直接影响Web服务器响应其它请求的能力。 2. 使用适当的Caching策略来提高性能 3. 判断字符串,不要用""比较。 //避免 if(strABC!=null && strABC!="") {} //推荐 if(!strABC.IsNullOrEmpty) {} 4. 页面优化 5.用完马上关闭数据库连接 6. 尽量使用存储过程,并优化查询语句 7. 只读数据访问用SqlDataReader,不要使用DataSet ………. 11、说出一些数据库优化方面的经验? 索引内部原理:想象成Dictionary,插入、删除、更新的速度慢了,加上索引也多占用了空间,查询的速度快了。加上索引以后速度提升非常明显。 (1)在经常检索的字段上(select * from Person where Name=@Name)使用索引提高查询速度。 (2)select中只列出必要的字段,而不是*。 (3)避免隐式类型转换造成的全表扫描,在索引上使用函数也会造成全表扫描(因为索引只是为字段建立的,一旦使用表达式或者函数,那么索引就是失效了,当然也可以使用“函数索引”、 “表达式索引”解决这个问题),使用索引不一定能提高查询速度。 (4)避免在索引列上使用计算(where Name+'A'=@MyName) ...... 二、程序设计1.请编程实现一个冒泡排序算法? Int[] arrAge = new int[5]; //给数组元素赋初始值 For(int i=0; i<5; i++) { Int intTemp = 0; For(int j=i+1; j<5; j++) { If(arrAge<arrAge[j]) { intTemp = arrAge; arrAge = arrAge[j]; arrAge[j] = intTemp; } } } 2. 一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少, 用递归算法实现。 public class MainClass { public static void Main() { Console.WriteLine(Foo(30)); } public static int Foo(int i) { if (i <= 0) return 0; else if(i > 0 && i <= 2) return 1; else return Foo(i -1) + Foo(i - 2); } } 3、编写一个单例(Singleton)类。 public FileManager { private FileManager(){} public static FileManager Instance = new FileManager(); } 4. 程序设计: 猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。(C#语言) 要点:1. 联动效果,运行代码只要执行Cat.Cryed()方法。2. 对老鼠和主人进行抽象 iOS开发-UITableView自定义Cell - Fly_Elephant 阅读原文» UITableView在iOS中开发的重要地位是毋庸置疑的,基本上应用中用到的比例是一半左右,而且大部分情况都是需要自定义单元格的,这样用户看到的App才能更有美感。之前写过UITableView的基本用法,如果对UITableView不是很熟悉可以参考本人之前的博客,因此很多UITableView的知识点就默认你已经熟悉了,先看下自定义实现的效果,这是自定义的Cell最后展现的效果:
自定义Cell 1.首先新建一个CustomCell.xib文件,方式如下:
2.新建一个继承自UITableViewCell的CustomTableViewCell类,需要重写initWithStyle方法: -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ self=[super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:nil options:nil]; self=[views firstObject]; } return self; } 3.CustomCell.xib中拖入一个UITableViewCell,然后和CustomTableViewCell关联: 关联之后CustomTableViewCell多了一个属性: @property (weak, nonatomic) IBOutlet UILabel *title; UITableView加载Cell 1.viewDidLoad初始化UITableView: self.tableView=[[UITableView alloc]initWithFrame:CGRectMake(10, 10,CGRectGetWidth(self.view.bounds)-20, CGRectGetHeight(self.view.bounds)-10)]; self.tableView.delegate=self; self.tableView.dataSource=self; [self.view addSubview:self.tableView]; 2.初始化标题数组travelArr: -(NSArray *)travelArr{ _travelArr=@[@"北京-清迈",@"北京-香港",@"北京-东京",@"北京-大阪",@"北京-新加坡",@"北京-维多利亚",@"北京-纽约",@"北京-夏威夷",@"北京-维多利亚",@"北京-柬埔寨"]; return _travelArr; } 3.实现UITableViewDataSource中的方法: -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return [self.travelArr count]; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *identifier=@"CustomCell"; CustomTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier]; if (cell==nil) { cell=[[CustomTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } cell.title.text=[self.travelArr objectAtIndex:indexPath.row]; return cell; } 4.实现UITableViewDelegate中的方法: -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; return cell.frame.size.height; } 简单的自定义大概就是如此了,如果有所收获,帮忙推荐下~ 本文链接:iOS开发-UITableView自定义Cell,转载请注明。 2015年4月24日星期五codis集群部署实战 本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 codis集群部署实战 阅读原文» codis集群部署实战 一、概要 1、折腾codis集群已经快两个月了,感谢一直以来codis的作者刘奇和黄东旭的耐心支持,在这里给你们点个赞,现在我司已经有一个业务跑在了codis集群上,目前只是切了整个业务的10%的量,预计下周会全量切到codis上,这个时候大家肯定特别想知道codis稳定吗?有没有什么bug啊,你想知道的也是我想知道的,搞起吧,用了才知道,反正目前我们这没发现啥问题,一些小的问题已经及时联系作者改掉了,好吧,不扯淡了,写这篇文章的目的是帮助想了解codis的初学者快速部署(官方的部署文档对应运维知识弱一点的童鞋看来还是有点费力)还有就是给自己做一个备录以便后期集群的部署。 2、Codis 是一个分布式Redis解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别 (有一些命令不支持), 上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis服务,当然,前段时间redis官方的3.0出了稳定版,3.0支持集群功能,codis的实现原理和3.0的集群功能差不多,我了解的现在美团、阿里已经用了3.0的集群功能了,我们这边的业务主要是php,3.0集群的sdk目前貌似还没有支持php语言的,大家谁的php应用上了3.0集群,请联系我,我去取经,有关redis常见的集群技术,请移步到 @萧田国 萧老师的infoq专栏Redis集群技术及Codis实践 二、架构 三、角色分批
四、部署 1、安装zookeeper
2、go安装(codis是go语言写的,所以那些机器需要安装你懂得)
3、下载并编译codis(codis-config、codis-proxy、codis-server所在的机器)
|