>上文主要介绍了邮箱管理相关的函数,本文介绍内存管理相关的函数:OSMemCreate()内存块创建函数,OSMemGet()函数,OSMemPut()函数,OSMemQuery()函数.以前用过的uC/OS-II笔记分享到这里。
2015年9月30日星期三
uC/OS-II 函数之内存管理相关函数 - One-peace
2015年9月29日星期二
哪种监控工具才是运维人的最爱?
哪种监控工具才是运维人的最爱?
那些指标需要监控?我能监控到什么?能监控到何种程度?或许这些问题连你自己都难说清楚。先看看运维兄弟们的现状。
1.运维现状
传统企业的计算机运维是在用户使用计算机过程中发现故障之后,通知运维人员,再由运维人员采取相应的补救措施。运维人员日常大部分时间和精力都花在处理简单且重复的问题上,而且由于故障预警机制不完善,往往是故障发生后才会进行处理,这种情况使运维人员的工作经常处于被动"救火"状态,这种被动的运维模式让IT部门疲惫不堪。运维质量如何提高?生产部门能对运维部有满意的评价吗?
目前我们在运维管理过程中缺少明确的角色定义和责任划分,以及自动化的集成运维管理平台,以至于问题出现后很难快速、准确地找到原因,而且在处理故障之后也缺乏必要的跟踪与记录。
2.隐藏在流量背后的秘密
网络接口的通端,流量的大小,已满足不了目前运维故障排除的需要。我们需要将流量分析的更深入,更细致。
图1 传统流量监控工具看表象
很多漏洞利用攻击、ShellCode攻击都混杂着正常流量进入企业网层层防护关卡。要想知道每个数据包中携带了什么内容,普通的摄像头已经失效,需要更强大的X透视相机-进行协议分析,只有准确理解事物的本质,才能对症下药,Shellcode攻击(下图是shellcode和botnet的实例)和各种蠕虫也是如此。
3.大数据时代下安全运维的新挑战
运维工程师们在大数据时代,下面对大量网络安全事件,若没有有效工具是无法完成分析工作,他们往往面对如下挑战:
1) 每天出现巨大数量的安全报警,管理员很难对这些报警做出响应。
2) 误报严重,管理员无法准确判断故障。
3) 大量重复、零散而没有规律的报警,黑客的一次攻击行动,会在不同阶段触发不同安全设备的告警,这样导致报警数据之间在时间和空间上存在大量重复数据,如果不实现安全事件的关联处理,就无法有效的提高告警质量。
当出现这些问题的部分原因是企业缺乏事件监控和诊断等运维工具,因为如果没有高效的管理工具支持,就很难让故障事件得到主动、快速处理。市面上有很多运维监控工具,例如商业版的Cisco Works 2000、Solarwinds、ManageEngine以及专注故障监控的WhatsUp,在开源领域有MRTG、Nagios、Cacti、Zabbix、Zenoss、OpenNMS、Ganglia等。由于它们彼此之间没有联系,即便是你部署了这些工具,很多运维人员并没有从中真正解脱出来,原因在于目前的技术虽然能够获取计算机设备、服务器、网络流量,甚至数据库的警告信息,但成千上万条警告信息堆积在一起,让人根本没办法判断问题的根源在哪里,缺乏对信息进行筛选、数据挖掘的能力,其实我们并不缺少工具,商业的也好,开源的也吧,一抓一大把,为什么还是用不好?真正缺少的是分析数据的智能化。
另外我们的查看各种监控系统需要多次登录,查看繁多的界面,更新管理绝大多数工作都是手工操作,即使一个简单的系统变更或更新,往往需要运维人员逐一登录系统,当设备数量达到成百上千时,其工作量之大可想而知。而这样的变更和检查操作在IT 运维中往往每天都在进行,这无疑会占用大量的运维资源。因此,运维工作人员需要统一的集成安全管理平台已迫在眉睫。
过去仅靠几个"技术大拿"来包打天下已不能满足要求,企业需要一种安全的运维平台,满足专业化、标准化和流程化的需要来实现运维工作的自动化管理。因为通过集成监控系统能及时发现故障隐患,主动的告诉用户需要关注的资源,感知网络威胁,把故障消除在萌芽状态。这极大降低了运维人员的工作负担,最大限度地减少维修时间,提高服务质量。
4.人工整合开源工具
既然找不到合适的,我们就把常用的开源工具集成到一个Linux平台,这不是就实现统一管理平台了吗?
人工整合开源监控系统的难点:
1. 软件和依赖依赖问题难以解决。
2. 各子系统界面重复验证和界面风格问题。
3. 各子系统数据无法共享。
4. 无法实现数据之间关联分析。
5. 无法生成统一格式的报表。
6. 缺乏统一的仪表板来展示重要监控信息。
7. 无法对网络风险进行检测。
8. 各子系统维护难度,增大了运维成本。
实践中发现,这种方案首先遇到了性能问题,一些脚本周期性消耗了较多的CPU和I/O资源,所以无法做到实时数据分析。试想有多少且能投入大量人力、时间去开发一个未知的监控平台?
5.集成安全运维平台的选择
一个好的安全运维平台需要将事件与IT 流程相关联,一旦监控系统发现性能超标或出现宕机现象,就会触发相关事件以及事先定义好的流程,自动启动故障响应和恢复机制。还需要能够筛选出运维人员完成日常的重复性工作,提高运维效率。要实现这些功能都是常规监控软件Cacti、Zabbix所无法实现。
同时,还要求能够预测网络蠕虫威胁,在故障发生前能够报警,让运维人员把故障消除在萌芽状态,将所产生损失减到最低。总的来说运维人需要能够在一个平台中实现资产管理、分布式部署、漏洞扫描、风险评估、策略管理、实时流量监控、异常流量分析、攻击检测报警、关联分析、风险计算、安全事件告警、事件聚合、日志收集与分析、知识库、时间线分析、统一报表输出、多用户权限管理的功能,这种集成开源工具到底有没有?它去哪儿啦?
目前市面上有两种产品可满足这样的要求,目?p>阅读更多内容
2015年9月28日星期一
基于svg中的path画40%表示的环型图(js类库Raphal) - jinhuazhe2013
【摘要】一、可供参考的文档资料。raphaeljs官网:http://raphaeljs.com/w3c关于path的介绍:http://www.w3.org/TR/2003/REC-SVG11-20030114/paths.htmlmdn关于path的介绍(英文版):https://developer.m... 阅读全文
在表单(input)中id和name的区别
但是name在以下用途是不能替代的:
1. 表单(form)的控件名,提交的数据都用控件的name而不是id来控制。因为有许多name会同时对应多个控件,比如checkbox和radio,而id必须是全文档中唯一的。此外浏览器会根据name来设定发送到服务器的request。因此如果用id,服务器是无法得到数据的。
2. frame和window的名字,用于在其他frame或window指定target。
例如:<framesetcols="200,*">
<framesrc="/example/html/toc.html">
<framesrc="/example/html/pref.html" name="view_frame">
</frameset>
等同于其他标签中target="view_window":
<ul>
<li><a href="/example/html/pref.html" target="view_window">Preface</a></li>
<li><a href="/example/html/chap1.html" target="view_window">Chapter1</a></li>
</ul>
以下两者可以通用,但是强烈建议用id不要用name:
1. 锚点,通常以前写作<a name="myname">但name属性只能针对a标签定位,现在可以用任何的元素id来指定:<div id="myid">。
例1:<a href="001">跳到001</a>
……
<aid="001"> (为了兼容,a标签不能空)</a>
Href的值要跟id一致,前面必须加#
例2:想显示某页面的某锚点内容
<ahref="123.html#001">跳到001</a>
……
<aid="001"> </a>
以下只能用id:
1. label与form控件的关联,
<label for="MyInput">MyInput</label>
<input id="MyInput"type="text">
for属性指定与label关联的元素的id,不可用name替代。
2. CSS的元素选择机制,以#MyId的方式指定应用样式的元素,不能用name替代。
3. 脚本中获得对象:
3.1 如果用DOM的话,则用document.getElementById("MyInput").value,
document.getElementByTagName("MyInput").value
JQ中——$(".firstname").value
3.2提交表单——如果要用name的话,通常先得到包含控件的form,例如document.forms["MyForm"],然后从form再引用name,注意这样得到的是经过计算后将发送给服务器的值。
例子:<head>
<scripttype="text/javascript">
functionformSubmit() {
document.forms["myForm"].submit();
}
</script>
</head>
<body>
<form name="myForm"action="http://www.jb51.net/example/html/form_action.asp"method="get">
Firstname: <input type="text" name="fname" /><br />
Last name: <input type="text"name="lname" /><br />
<inputtype="button" onclick="formSubmit()" value="Send formdata!" />
</form>
</body>
name与id的还有区别是:
id要符合标识的要求,比如大小写敏感,最好不要包含下划线(因为不兼容CSS)。而name基本上没有什么要求,甚至可以用数字。
补充:name主要是表单元素里才有的属性。通过js的document.表单名称.文本框.value来获取文本框的值,其中的表单名称和文本框名称指的是name,而非表单元素例如div,span等是没有name属性的,而id属性是任何一个HTML元素都会有的。当你需要用js获取非表单元素对象是就得用document.getElementById("id")
本文链接:在表单(input)中id和name的区别,转载请注明。
2015年9月26日星期六
DOM选择器API - 小火柴的蓝色理想
getElementById()
getElementById()方法接收一个参数:要取得元素的ID,若找到相应元素则返回该元素,若不存在则返回null
【IE7-浏览器bug1】ID属性不区分大小写
<script>
var oBox = document.getElementById('Box');
console.log(oBox);//IE7-可以找到该元素,但其他浏览器都返回null
</script>
如果页面中多个元素的ID属性相同,则只返回文档中第一次出现的元素
<div class="box" id="box">2</div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.innerHTML);//1
</script>
【IE7-浏览器bug2】表单元素的name属性也会被当作ID属性识别出来。因此为了避免这种问题,最好不让表单元素的name属性和其他元素的ID属性相同
<div class="box" id="box">1</div>
<div class="box" id="box">2</div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.innerHTML);//0
</script>
getElementsByTagName()
getElementsByTagName()该方法接收一个参数,即要取得元素的标签名,而返回的是包含0或多个元素的NodeList。在HTML文档中,这个方法会返回一个HTMLCollection对象,作为一个动态集合,该对象与NodeList非常类似。对于HTMLCollection对象而言,我们可以向方括号中传入数值或字符串形式的索引值。在后台,会对数值索引调用item()方法,对字符串索引调用namedItem()方法。HTMLCollection对象还有一个方法是namedItem(),可以通过元素的name特性或者直接用方括号来取得集合中的项。但safari和IE都不支持该方法。
<li class="in">1</li>
<li class="in">2</li>
<li class="in" name="in3">3</li>
</ul>
<script>
var oList = document.getElementById('list');
var aIn = oList.getElementsByTagName('li');
console.log(aIn.length);//3
console.log(aIn[0].innerHTML);//1
console.log(aIn.item(0).innerHTML);//1
console.log(aIn["in3"].innerHTML);//在safari和IE下报错,在其他浏览器下输出3
console.log(aIn.namedItem("in3").innerHTML);//在safari和IE下报错,在其他浏览器下输出3
要想取得所有的元素,可以向getElementsByTagName传入"*",表示全部
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
var aAll = document.getElementsByTagName('*');
//标准浏览器下结果为[html, head, meta, title, body, script]
//IE8-浏览器下结果为7个,由于它把<!DOCTYPE html>识别为注释,且把注释识别为元素,所以多1个
console.log(aAll);
</script>
</body>
</html>
在HTML中getElementsByTagName()里的元素不需要区分大小写,但在XML包括XHTML页面需要区分大小写
<script>
var aAll = document.getElementsByTagName('DIV')[0];
console.log(aAll.innerHTML);//所有浏览器都返回1
</script>
getElementsByName()
getElementsByName()该方法会返回带有给定name特性的所有元素,所有浏览器都支持。
最常用的是取得单选按钮。
<li class="in">
<input type="radio" value ="red" name ="color" id="colorRed">
<label for="colorRed">红色</label>
</li>
<li class="in">
<input type="radio" value ="blue" name ="color" id="colorBlue">
<label for="colorBlue">蓝色</label>
</li>
<li class="in">
<input type="radio" value ="green" name ="color" id="colorGreen">
<label for="colorGreen">绿色</label>
</li>
</ul>
<script>
var radios = document.getElementsByName('color');
console.log(radios.length)//3
</script>
getElementsByClassName()
getElementsByClassName()方法接收一个参数,即一个包含一个或多个类名的字符串,返回带有指定类的所有元素的NodeList。传入多个类名时,类名的先后顺序不重要。(IE8-浏览器不支持)
<li class="in" >1</li>
<li class="in ab" >2</li>
<li class="in ab c">3</li>
</ul>
<script>
var oTest = document.getElementsByClassName('in ab');
console.log(oTest.length);//2
</script>
classList
在操作类名时,需要通过className属性添加、删除和替换类名。因为className是一个字符串,所以即使只修改字符串一部分,也必须每次都设置整个字符串的值。要从className字符串中删除一个类名,需要把类名拆开,删除不想要的那个,再重新拼成一个新字符串。(IE9-浏览器不支持)
<li class="in" >1</li>
<li class="in ab" >2</li>
<li class="in ab c">3</li>
</ul>
<script>
var oTest = document.getElementsByClassName('in ab')[1];
function removeClass(obj,str){
var classNames = obj.className.split(/\s+/);
var pos = -1;
for(var i = 0, len = classNames.length; i < len; i++){
if(classNames == str){
pos = i;
break;
}
};
classNames.splice(i,1);
obj.className = classNames.join(' ');
}
removeClass(oTest,'in');
console.log(oTest.className)//ab c
</script>
HTML5为所有元素添加了classList属性,这个classList属性是新集合类型DOMTokenList的实例,它有一个表示自己包含多少元素的length属性,而要取得每个元素可以使用item()方法,也可以使用方括号法。此外,这个新类型还定义如下方法:
add(value):将给定的字符串值添加到列表中,如果值已存在,则不添加
contains(value):表示列表中是否存在给定的值,如果存在则返回true,否则返回false
remove(value):从列表中删除给定的字符串
toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。
<li class="in" >1</li>
<li class="in ab" >2</li>
<li class="in ab c">3</li>
</ul>
<script>
var oTest = document.getElementsByTagName('li')[1];
console.log(oTest.classList);//JavaScript中关于隐式转换的一些总结 - andygo 阅读原文»
JavaScript运算符中的隐式转换规律:
一、递增递减运算符(前置、后置)
1.如果包含的是有效数字字符串或者是有效浮点数字符串,则会将字符串转换(Number())为数值,再进行加减操作,返回值的类型是:number类型。
2.如果不包含有效数字字符串,则会将字符串的值转换为NaN,返回值的类型是:number类型。
3.如果是boolean类型,则先会把true或者false转换为1或者0,再进行加减操作,返回值的类型是:number类型。
4.如果是null类型,则先会把null转换为0,在进行加减操作,返回值的类型是:number类型。
5.如果是undefined,则先会把undefined转换为NaN,再进行加减操作,返回值的类型是:number类型。
6.如果是对象,则先会通过对象的valueOf()方法,进行转换,如果返回的是NaN,调用toString()方法,在进行前面的操作,返回值的类型是:number类型。(注:空数组[]会返回0,在进行加减操作,空对象则会返回NaN)。
二、逻辑操作符中的隐式转换规律(注:只有undefined、null、NaN、0、空字符串会被转换为false,其余都为true):
逻辑操作符一般用于语句判断中。通过判断结果返回的值进行后面的语句操作。
1.逻辑非(!)操作符:首先会通过Boolean()函数将其操作值转换为布尔值,然后求反。
2.逻辑与(&&)操作符:如果第一个值经过Boolean()函数转换后为true,则返回第二个操作值,否则返回第一个操作值。如果有一个操作值为null这返回null,如果有一个操作值为undefined,则返回undefined,如果有一个值为NaN,则返回NaN。
3.逻辑或(||)操作符:如果第一个值经过Boolean()函数转换为false,则返回第二个操作值,否则返回第一个操作值。
(注:逻辑操作符的运算为短路逻辑运算:前一个条件已经能够得出结果后续条件不再执行!)
三、关系操作符的隐式转换规律(关系操作符的操作值也可以是任意类型):
1.如果两个操作值都是数值,则直接比较大小。
2.如果两个操作值都是字符串,则字符串进行其Unicode编码进行比较。
3.如果一个操作值是数值,则另一个值转换为数值进行比较。
4.如果一个操作值是对象,则调用对象的valueOf()和toString()方法,然后再进行上述比较。
5.如果一个操作值是布尔值,则将布尔值转换为数值再进行比较。
(注:NaN和任何值都不相等,包括自己,同时它与任何类型比较都会返回false。)
相等操作符==和===的隐式转换规律:
1.布尔值、字符串和数值进行比较,会先将其转换为数值再进行比较。
2.null和undefined比较是相等的,但不是全等的。
3.NaN与任何值都不相等,都会返回false。
本文链接:JavaScript中关于隐式转换的一些总结,转载请注明。
2015年9月24日星期四
Web端导出CSV - 木的树
前端导出文件大部分还是通过服务器端的方式生成文件,然后传递到客户端。但很多情况下当我们导出CSV时并不需要后端参与,甚至没有后端。
做过WebGIS的同学经常会碰到这种场景,用户的兴趣点数据以csv文件形式上传到web应用中以表格形式展示,并可以编辑属性信息,编辑完成后需要将数据下载到本地。特别是对一些敏感数据,用户不希望传递到应用服务器端,整个过程完全在客户端进行。
上传过程我们暂且不讨论,只讨论生成CSV以及下载过程。
CSV的生成
问题一:如何分行分列?
思路:分行使用“\n”,分列使用","
实际应用中发现导出的csv用excel打开后,列可以分开但行无法分开。
解决方法是,将生成的csv字符串使用encodeURIComponent编码
问题二:字段值中含有特殊符号影响csv文件的正确解读,如:“,”,"\n"
思路:将含有特殊符号的字段用双引号包装起来,如:a,b => "a,b"
if (value && /[,\r\n]/g.test(value)) {
value = textField + value + textField;
}
实际应用发现少考虑了一种情况,如果字段值中含有‘ " ’这个符号,经过上方代码处理反而会出现问题:a"b => "a"b"。显然是语法错误。
解决方法是将"换成"",a"b => "a""b"
if (value && /[",\r\n]/g.test(value)) {
value = textField + value.replace(/(")/g, '""') + textField;
}
在解决以上问题后生成CSV字符串代码如下
//_outFields: 字段名称数组
exports.createCSVStr = function(data, _outFields) {
var textField = '"';
var content = "";
var len = 0,
n = 0,
comma = "",
value = "";
try {
array.forEach(_outFields, function(_field) {
content = content + comma + _field;
comma = ",";
});
content = content + "\r\n";
len = data.length;
n = _outFields.length;
for (var i = 0; i < len; i++) {
comma = "";
for (var m = 0; m < n; m++) {
var _field = _outFields[m];
value = data[_field];
if (!value && typeof value !== "number") {
value = "";
}
if (value && /[",\r\n]/g.test(value)) {
value = textField + value.replace(/(")/g, '""') + textField;
}
content = content + comma + value;
comma = ",";
}
content = content + "\r\n";
}
} catch (err) {
console.error(err);
content = "";
}
return content;
};
问题三:如果字段中含有希伯来文、法语、德语等文字('éà; ça; 12\nà@€; çï; 13'
),导出的csv文件在Excel中打开后,这些文字呈现出乱码
解决方法:严格来说这并不是csv文件的问题,而是Excel处理文件编码方式问题,Excel默认并不是以UTF-8来打开文件,所以在csv开头加入BOM,告诉Excel文件使用utf-8的编码方式。
var csvStr = BOM + csvStr;
实际应用中发现,这种处理方式在windows中的Excel中打开后可以正常显示,但在mac上的Excel无法正确显示。目前没有完全的解决方案,但mac中可以使用自带的Numbers软件打开,不会出现乱码问题。
CSV的下载方式
问题一:如何在解决不同浏览器中的下载问题?
思路:
- IE10以下,利用execCommand方法来保存csv文件var oWin = window.top.open("about:blank", "_blank");
oWin.document.write(encodeURIComponent(text));
oWin.document.close();
oWin.document.execCommand('SaveAs', true, filename);
oWin.close();在实际应用中浏览器会打开一个新窗口,并弹出保存文件对话框,而对话框中保存类型时,只有html和text两项可选,此时需要在文件名中手动加上“.csv”后缀
- IE10以及Edge浏览器使用navigator.msSaveBlob(blob);虽然这些浏览器也支持上面的方法,但可以避免上面遇到的问题。var BOM = "\uFEFF";
var csvData = new Blob(, { type: 'text/csv' });
navigator.msSaveBlob(csvData, filename);msSaveBlob是IE的私有方法,只有IE10及以上和Edge浏览器支持。
- Firefox、Chrome、Safari浏览器中使用a标签,利用html5中增加的download属性来下载csvvar link = html.create("a", {
href: 'data:attachment/csv;charset=utf-8,' + BOM + encodeURIComponent(text),
target: '_blank',
download: filename
}, this.domNode);
if (has('safari')) {
// # First create an event
var click_ev = document.createEvent("MouseEvents");
// # initialize the event
click_ev.initEvent("click", true /* bubble */ , true /* cancelable */ );
// # trigger the evevnt/
link.dispatchEvent(click_ev);
} elseDOM特性节点ATTRIBUTE - 小火柴的蓝色理想 阅读原文»定义
每个元素都有一个或多个特性,这些特性的用途是给出相应元素或内容的附加信息。实质上,特性节点就是存在于元素的attributes属性中的节点。
特征
nodeType:2
nodeName:特性的名称
nodeValue:特性的值
parentNode:null
childNode:chrome、firefox下为undefined,safari下为Text,IE9+下为子元素的特性名,IE8-下报错
[注意]尽管Attribute也是节点,但却不被认为是DOM文档树的一部分,开发人员常用getAttribute()、setAttribute()、removeAttribute(),很少直接引用特性节点<div id="box"></div>
<script>
var oBox = document.getElementById('box');
var oAttr = oBox.attributes;
//(chrome\safari\IE9+\firefox) 2 id box null
//(IE7-) 2 onmsanimationiteration null null
console.log(oAttr[0].nodeType,oAttr[0].nodeName,oAttr[0].value,oAttr[0].parentNode)
//(chrome\firefox) undefined
//(safari) Text
//(IE9+) box
//(IE8-) 报错
console.log(oAttr[0].childNodes[0])
</script>特性节点属性
Attr对象有3个属性:name、value和specified
【1】name是特性名称(与nodeName的值相同)
【2】value是特性的值(与nodeValue的值相同)
【3】specified是一个布尔值,用以区别特性是在代码中指定的,还是默认的。这个属性的值如果为true,则意味着要么是在HTML中指定了相应特性,要么是通过setAttribute()方法设置了该属性。在IE中,所有未设置过的特性的该属性值都为false,而在其他浏览器中根本不会为这类特性生成对应的特性节点<div class="box" id="box"></div>
<script>
var oBox = document.getElementById('box');
var oAttr = oBox.attributes;
//(chrome\safari\IE8+)class class true
//(firefox)id id true
//(IE7-)onmsanimationiteration onmsanimationiteration true
console.log(oAttr[0].name,oAttr[0].nodeName,oAttr[0].name == oAttr[0].nodeName)
//IE7- "null" null false
//其他浏览器 box box true
console.log(oAttr[0].value,oAttr[0].nodeValue,oAttr[0].value == oAttr[0].nodeValue)
//IE7- false
//其他浏览器 true
console.log(oAttr[0].specified)//true
</script><div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.attributes.id.specified)//true
console.log(oBox.attributes.onclick.specified)//在IE7-浏览器下会返回false,在其他浏览器下会报错
</script>特性属性attributes
Element类型是使用attributes属性的唯一一个DOM节点类型。attributes属性中包含一个NamedNodeMap,与NodeList类似,也是一个动态的集合。元素的每一个特性都由一个Attr节点表示,每个节点都保存在NamedNodeMap对象中。
【attributes属性的四个方法】
[a]getNamedItem(name):返回nodeName属性等于name的节点
removeNamedItem(name):从列表中移除nodeName属性等于name的节点
[c]setNamedItem(node):向列表中添加节点,以节点的nodeName属性为索引
[d]item(pos):返回位于数字pos位置处的节点,也可以用方括号法[]简写<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.attributes);//NamedNodeMap {0: class, 1: id, 2: name, 3: index, 4: title}
var getTest = oBox.attributes.getNamedItem("index");
console.log(getTest);//index = "123"
var removeTest = oBox.attributes.removeNamedItem("class");
console.log(removeTest);//class = "box"
console.log(oBox.attributes.getNamedItem("class"));//null
console.log(oBox.attributes.setNamedItem(removeTest));//null
console.log(oBox.attributes.setNamedItem(getTest));//index = "123"
console.log(oBox.attributes.item(0));//id="box"(每个浏览器获取的不一样)
</script>attributes属性中包含一系列节点,每个节点的nodeName就是特性的名称,节点的nodeValue就是特性的值
<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
var oBox = document.getElementById('box');
console.log(oBox.attributes);//NamedNodeMap {0: class, 1: id, 2: name, 3: index, 4: title}
console.log(oBox.attributes.id.nodeName);//"id"
console.log(oBox.attributes.id.nodeValue);//"box"
</script>【特性遍历】
attributes属性主要用于特性遍历。在需要将DOM结构序列化为XML或HTML字符串时,多数都会涉及遍历元素特性
function outputAttributes(element){
var pairs = new Array(),attrName,attrValue,i,len;
for(i = 0,len=element.attributes.length;i<len;i++){
attrName = element.attributes.nodeName;
attrValue = element.attributes.nodeValue;
pairs.push(attrName +"=\"" + attrValue + "\"");
}
return pairs.join(" ");
}[注意1]针对attributes对象中的特性,不同浏览器返回的顺序不同
<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>
function outputAttributes(element){
var pairs = new Array(),attrName,attrValue,i,len;
for(i = 0,len=element.attributes.length;i<len;i++){
attrName = element.attributes.nodeName;
attrValue = element.attributes.nodeValue;
pairs.push(attrName +"=\"" + attrValue + "\"");
}
return pairs.join(" ");
}
//(chrome\safari)class="box" id="box" name="abc" index="123" title="test"
//(firefox)title="test" index="123" name="abc" id="box" class="box"
//(IE8+)title="test" class="box" id="box" index="123" name="abc"阅读更多内容
2015年9月23日星期三
Linux 高可用(HA)集群之keepalived
用户名:飞残月 文章数:125 评论数:18
访问量:6882:2273:1284:5 注册日期:2015-02-25
一、keepalived介绍
1、Keepalived 定义
Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以利用其来避免单点故障。一个LVS服务会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。Keepalived是VRRP的完美实现,因此在介绍keepalived之前,先介绍一下VRRP的原理。
2、VRRP 协议简介
在现实的网络环境中,两台需要通信的主机大多数情况下并没有直接的物理连接。对于这样的情况,它们之间路由怎样选择?主机如何选定到达目的主机的下一跳路由,这个问题通常的解决方法有二种:
-
在主机上使用动态路由协议(RIP、OSPF等)
-
在主机上配置静态路由
很明显,在主机上配置动态路由是非常不切实际的,因为管理、维护成本以及是否支持等诸多问题。配置静态路由就变得十分流行,但路由器(或者说默认网关default gateway)却经常成为单点故障。VRRP的目的就是为了解决静态路由单点故障问题,VRRP通过一竞选(election)协议来动态的将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。
3、VRRP 工作机制
在一个VRRP虚拟路由器中,有多台物理的VRRP路由器,但是这多台的物理的机器并不能同时工作,而是由一台称为MASTER的负责路由工作,其它的都是BACKUP,MASTER并非一成不变,VRRP让每个VRRP路由器参与竞选,最终获胜的就是MASTER。MASTER拥有一些特权,比如,拥有虚拟路由器的IP地址,我们的主机就是用这个IP地址作为静态路由的。拥有特权的MASTER要负责转发发送给网关地址的包和响应ARP请求。
VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP多播(multicast)包(多播地址224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-255)和一组IP地址组成,对外表现为一个周知的MAC地址。所以,在一个虚拟路由 器中,不管谁是MASTER,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因为MASTER的改变而修改自己的路由配置,对客户端来说,这种主从的切换是透明的。
在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息(VRRPAdvertisement message),BACKUP不会抢占MASTER,除非它的优先级(priority)更高。当MASTER不可用时(BACKUP收不到通告信息), 多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性。由于安全性考虑,VRRP包使用了加密协议进行加密。
4、VRRP 工作流程
(1).初始化:
路由器启动时,如果路由器的优先级是255(最高优先级,路由器拥有路由器地址),要发送VRRP通告信息,并发送广播ARP信息通告路由器IP地址对应的MAC地址为路由虚拟MAC,设置通告信息定时器准备定时发送VRRP通告信息,转为MASTER状态;否则进入BACKUP状态,设置定时器检查定时检查是否收到MASTER的通告信息。
(2).Master
-
设置定时通告定时器;
-
用VRRP虚拟MAC地址响应路由器IP地址的ARP请求;
-
转发目的MAC是VRRP虚拟MAC的数据包;
-
如果是虚拟路由器IP的拥有者,将接受目的地址是虚拟路由器IP的数据包,否则丢弃;
-
当收到shutdown的事件时删除定时通告定时器,发送优先权级为0的通告包,转初始化状态;
-
如果定时通告定时器超时时,发送VRRP通告信息;
-
收到VRRP通告信息时,如果优先权为0,发送VRRP通告信息;否则判断数据的优先级是否高于本机,或相等而且实际IP地址大于本地实际IP,设置定时通告定时器,复位主机超时定时器,转BACKUP状态;否则的话,丢弃该通告包;
(3).Backup
-
设置主机超时定时器;
-
不能响应针对虚拟路由器IP的ARP请求信息;
-
丢弃所有目的MAC地址是虚拟路由器MAC地址的数据包;
-
不接受目的是虚拟路由器IP的所有数据包;
-
当收到shutdown的事件时删除主机超时定时器,转初始化状态;
-
主机超时定时器超时的时候,发送VRRP通告信息,广播ARP地址信息,转MASTER状态;
-
收到VRRP通告信息时,如果优先权为0,表示进入MASTER选举;否则判断数据的优先级是否高于本机,如果高的话承认MASTER有效,复位主机超时定时器;否则的话,丢弃该通告包;
5、ARP查询处理
当内部主机通过ARP查询虚拟路由器IP地址对应的MAC地址时,MASTER路由器回复的MAC地址为虚拟的VRRP的MAC地址,而不是实际网卡的 MAC地址,这样在路由器切换时让内网机器觉察不到;而在路由器重新启动时,不能主动发送本机网卡的实际MAC地址。如果虚拟路由器开启的ARP代理 (proxy_arp)功能,代理的ARP回应也回应VRRP虚拟MAC地址;好了VRRP的简单讲解就到这里,我们下来讲解一下Keepalived的案例。
6、keepalived组成
keepalived主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。
二、keepalived的配置文件说明
keepalived只有一个配置文件keepalived.conf,里面主要包括以下几个配置区域,分别是global_defs、static_ipaddress、static_routes、vrrp_script、vrrp_instance和virtual_server。
1、global_defs区域
主要是配置故障发生时的通知对象以及机器标识。
global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 enable_traps router_id LVS_DEVEL }
-
notification_email 故障发生时给谁发邮件通知。
-
notification_email_from 通知邮件从哪个地址发出。
-
smpt_server 通知邮件的smtp地址。
-
smtp_connect_timeout 连接smtp服务器的超时时间。
-
enable_traps 开启SNMP陷阱(Simple Network Management Protocol)。
- 傻瓜式操作Nagios图解 阅读原文»傻瓜式操作Nagios图解
傻瓜式操作Nagios
不少接触Nagios的朋友都会觉得安装配置困难,应用在企业网中所花费的时间成本很高,下面通过OSSIM来搞定它把。
为了节省资源,首先在淘汰的机器上安装一个低版本的OSSIM系统,接下来在WebUI中无需编写任何代码和配置文件便可开启傻瓜化操作Nagios之旅。
1.在左侧菜单中设置网络发现。
开始扫描,发现设备,点击完成后可出现扫描结果,接着选则更新数据库。
2.主机列表
查看监控效果
3.查看拓扑
4.列出另一网段更多主机,列出主机状态.
很轻松就完成了Nagios设置,今后增减服务器都可以通过这种图形化方式修改Nagios,非常方便,刚才说了这只是一个低版本的OSSIM所具功能,至于新版本还有那些本事,大家可以参考我的OSSIM专栏。如果大家也想找台就机器,内存只要大于2GB就可以安装下面提供的32位版本,有兴趣就去试试吧。
本文出自 "李晨光原创技术博客" 博客,请务必保留此出处http://chenguang.blog.51cto.com/350944/1696387
每日博报 精彩不止一点返回顶部
2015年9月22日星期二
zzuoj10408--最少换乘(***最短路***) - 微风向上
10408: C.最少换乘
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 38 Solved: 10
[Submit][Status][Web Board]
Description
欧洲某城是一个著名的旅游胜地,每年都有成千上万的人前来观光旅行。Dr. Kong决定利用暑假好好游览一番。。
年轻人旅游不怕辛苦,不怕劳累,只要费用低就行。但Dr. Kong年过半百,他希望乘坐BUS从住的宾馆到想去游览的景点,期间尽可量地少换乘车。
Dr. Kon买了一张旅游地图。他发现,市政部门为了方便游客,在各个旅游景点及宾馆,饭店等地方都设置了一些公交站并开通了一些单程线路。每条单程线路从某个公交站出发,依次途经若干个站,最终到达终点站。
但遗憾的是,从他住的宾馆所在站出发,有的景点可以直达,有的景点不能直达,则他可能要先乘某路BUS坐上几站,再下来换乘同一站的另一路BUS, 这样须经过几次换乘后才能到达要去的景点。
为了方便,假设对该城的所有公交站用1,2,……,N编号。Dr. Kong所在位置的编号为1,他将要去的景点编号为N。
请你帮助Dr. Kong寻找一个最优乘车方案,从住处到景点,中间换车的次数最少。
Input
第一行: K 表示有多少组测试数据。(2≤k≤8)
接下来对每组测试数据:
第1行: M N 表示有M条单程公交线路,共有N站。(1<=M<=100 1<N<=500)
第2~M+1行:每行描述一路公交线路信息,从左至右按运行顺序依次给出了该线路上的所有站号,相邻两个站号之间用一个空格隔开。
Output
对于每组测试数据,输出一行,如果无法乘坐任何线路从住处到达景点,则输出"N0",否则输出最少换车次数,输出0表示不需换车可以直达。
Sample Input
23 7
6 7
4 7 3 6
2 1 3 5
2 6
1 3 5
2 6 4 3
Sample Output
2NO
HINT
Source
看题目就知道喽, 换路线最少次数。 指定方向1 --> n, 有向边。 为啥用最短路可以解出来, 现在有点儿蒙圈。 明天好好想想。
#include <cstring>
#include <iostream>
#define M 501
using namespace std;
const int INF = 0x3f3f3f3f;
int map[M][M], dis[M], vis[M], num[M]; char str[1001];
int n, m;
void init()
{
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
if(i == j)
map[j] = 0;
else
map[j] = INF;
}
}
void GetMap()
{
int cnt;
for(int i = 1; i <= m; i++)
{
cnt = 0; gets(str);
for(int j = 0; j < strlen(str); j++)
if(str[j] != ' ')
{
int sum = 0;
while(str[j] != ' ' && j < strlen(str))
{
sum = sum*10 + (str[j] - '0');
++j;
}
num[cnt++] = sum;
}
for(int j = 0; j < cnt; j++)
for(int k = j + 1; k < cnt; k++)
map[num[j]][num[k]] = Shell 常用命令总结 - 天才白痴梦 阅读原文»
Shell常用命令总结
1 ls命令:列出文件
ls -la 列出当前目录下的所有文件和文件夹
ls a* 列出当前目录下所有以a字母开头的文件
ls -l *.txt 列出当前目录下所有后缀名为txt的文件
2 cp命令:复制
cp a.txt b.txt : 把文件a的内容复制到b文件
cp a.txt ./test : 把文件a复制到text目录下
cp -a test test2:递归的把目录test下所有文件(包括隐藏的文件)复制到新的目录 test2
3 cat命令:查看 组合文件
cat a.txt:查看文件的内容
cat a.txt >> b.txt:把a文件的内容组合到b文件内容的末尾
cat -n a.txt:查看文件并给文件标上行号
4 touch命令:建立文件
touch a.txt:建立一个名为a的txt类型文件
5 rm命令:删除文件
rm -rf a.txt:强制删除文件a.txt
tm -i a.txt:删除文件前会有提示是否确定删除该文件
6 mkdir命令:创建目录
mkdir test:创建一个名为test的目录
7 rmdir命令:删除目录
tmdir test:删除一个目录
8 echo、cat命令:添加内容
echo “hello world!” >> a.txt:添加内容到文件a里面
cat <<EOF>> a.txt : 可以添加多行语句到文件本身内容的末尾
cat <<EOF> a.txt:添加内容到文件并覆盖到原始的内容
9 mv命令:移动 重命名文件
mv a.txt b.txt:文件a重新命名为b
mv a.txt ./test:把文件移动到一个目录下
10 cd命令:更换目录
cd ~ : 切换到用户目录
cd .. :返回到上一层目录
cd ../.. :返回到上二层目录
11 grep命令:搜索文件
ls -la | grep a.txt :搜索a.txt文件
12 find命令:查找文件和目录
find filename:查找当前目录下是否有该文件/目录
13 rz sz命令:上传和下载文件
14 head命令:显示文件的前10行内容
15 tail命令:显示文件最后10行内容
总结:
之前有段时间学习了下Shell 常用的文件处理命令,上面列举的这些只是Shell命令的非常一小部分,Shell命令有非常强大和快速的处理能力,给我们平常的学习和工作任务提供了很多方便。再则,单就以上的15个命令而言,其功能远不止列举的那一两条命令这么简单,大家可以通过ls --help(其他命令以此类推)来查看命令的用法。
2015年9月20日星期日
一步一步搭建客服系统 (6) chrome桌面共享 - 疯吻IT
本文介绍了如何在chrome下用webrtc来实现桌面共。因为必要要用https来访问才行,因此也顺带介绍了如何使用SSL证书。
1 chrome扩展程序
- 先下载扩展程序示例:
https://github.com/otalk/getScreenMedia/tree/master/chrome-extension-sample
或 http://yunpan.cn/cHfwnrZcG2hsH 访问密码 1cf9
- 打开 manifest.json 文件,修改下面的内容:
"content_scripts": [ {
"js": [ "content.js" ],
"matches": [ "https://localhost:*/*" ]
}],
- 加载扩展程序
打开chrome,输入 chrome://extensions/ 以打开chrome的扩展程序,按下图的顺序加载:
2 共享桌面
共享桌面方法:
webrtc.shareScreen()
停止共享桌面方法:
webrtc.stopScreenShare()
var button = document.getElementById('screenShareButton'),
setButton = function (bool) {
//button.innerText = bool ? 'share screen' : 'stop sharing';
$('#screenShareButton').attr('value', bool ? 'Share Screen' : 'Stop Sharing');
};
setButton(true);
function screenShare() {
if (webrtc.getLocalScreen()) {
webrtc.stopScreenShare();
setButton(true);
} else {
webrtc.shareScreen(function (err) {
if (err) {
setButton(true);
} else {
setButton(false);
}
});
}
}
.
3 本机显示共享的内容
本机显示:
webrtc.on('localScreenAdded', function (video) {
//video.onclick = function () {
// video.style.width = video.videoWidth + 'px';
// video.style.height = video.videoHeight + 'px';
//};
video.className = 'localVideo';
document.getElementById('localScreenContainer').appendChild(video);
$('#localScreenContainer').show();
});
个人觉得本机没必要,在点击时放大共享的内容,所以把上面click事件注释掉了。
移除显示:
webrtc.on('localScreenRemoved', function (video) {
document.getElementById('localScreenContainer').removeChild(video);
$('#localScreenContainer').hide();
});
.
4 接收桌面共享
接收桌面共享:
webrtc.on('videoAdded', function (video, peer) {
console.log('video added', peer);
var remotes = document.getElementById('remotes');
if (remotes) {
var container = document.createElement('div');
//container.className = 'videoContainer';
container.id = 'container_' + webrtc.getDomId(peer);
container.appendChild(video);
// suppress contextmenu
video.oncontextmenu = function () { return false; };
video.className = 'remoteVideos';
// resize the video on click
video.onclick = function () {
launchFullscreen(video);
};
// show the ice connection state
if (peer && peer.pc) {
var connstate = document.createE
对于开发人员来说,其应用性能是需要特别关注的。在用户体验至上的大环境要求下,性能优化是十分必要的。无意中在知乎看到的这个问题,发现了成都华天创腾一位开发人员的回答分析了阿里云监控功能及 OneAPM 服务器端监控的使用对比,那么就来看下他的故事吧!以下是未经修改的原文:
太久没有写博客了,只是一味的吸收网上的攻略,感觉有点对不起这个行业。做了太多的拿来主义,从来没有几个原创给行业带来一点点的贡献!好吧装 B 装完了。说正事。
话说工欲善其事必先利其器,这里最近发现一个造神器的公司,OneAPM - 端到端的应用性能管理软件云解决方案。
先介绍下我的服务器,作为创业公司没有那么多 ¥ 去买实体服务器,托管,运维,安全防护都是一个大问题。所有当时还好有点经验,理智的给老板介绍了购买阿里云服务器。一下就搞定了这些所有的烦恼(当时是这么认为的),并且阿里云提供了服务器状态监控,服务监控。但是这些仍然只是满足了日常监控和运维的需求。一旦遇到详细点的性能监控的需求就嗝屁了。
本来是在找服务器运行状态监控软件的时候,无意在网上发现了 OneAPM,注册了一个账号后后来没有怎么使用,他们当时还没有推出我需求的服务器监控的软件,后来他们出了新版本后积极联系我,本以为他们和阿里云的东西差不多,后来在他们客服妹妹的悉心调教(我真没有吃过她豆腐)下装了一个试了试,不用不知道一用吓一跳,这个东西比阿里云的监控的详细多了。
上图有图才有真相
阿里云的监控
OneAPM 的监控
优势一下就出来了有木有,阿里云的监控只提供了总体的一个数据监控,而 OneAPM 提供了非常详细的占用信息。虽然 Linux 下也可以用命令看,但是我是比较懒的人(尼玛事情多的爆啊,能用一分钟解决的问题绝不想花两分钟)
话说他给我解决了什么问题吧,由于最近业务量暴涨,突然多了非常多的写库操作。导致数据库服务器的 CPU 暴涨一直都是 100%,尼玛这东西当时导致监控的服务器和服务各种报警,直接吓尿了,到阿里云监控上只看到了 CPU 占用了百分之但是那个程序占用的尼玛完全木有任何信息啊全靠自己去慢慢琢磨,老板的要求是服务器报警不能超过 30 分钟必须解决时间紧迫。当时登陆了 OneAPM 后台看采集回来的数据,清清楚楚的看到是 MySQL 数据库。几乎吞噬了所有数据库服务器的 CPU 这样下去不导致数据库服务器宕机才怪。
接下来 用OneAPM 的应用监控,查看服务对数据库的读写操作按次数进行排序,基本上是9:1的读写比例。
还好哥当时留了一手有先见之明,在另外的服务器上准备了一个从备份库,并且配置 **oeba
的读写分离,因为 PHP 接口用 amoeba 会报错,所以都是直连的主库。但是分析了最近的写库业务都是来源于 Java 服务,赶紧把 Java 的服务都切到 **oeba
服务的数据库中间件上,做了读写分离后 CPU 分分钟降到了 50% 的正常水平,从早上 8 点报警到中午十二点,基本解决了由大量数据写入数据库导致的 CPU 暴涨引起的一次性能问题。神器在手天下我有!!
其实我就是做了一次打酱油的其他的都给工具做了!!
------以上是分享的全部内容------
本文链接:如何打造前所未有的服务器端监控体验?,转载请注明。