Relax

运动可以放松心情,游个泳,或者降档切7000转。

小知识

把一个大表(23GBytes,60million+记录)导出到csv文件,采用500k记录批量处理,导出成一个个单个的csv文件。
那么怎么样把这些文件合并呢?

cat a.001.csv > all.csv
tail -n +2 a.002.csv >> all.csv

etc.

集成的小工具很好用呢 :)

统计学习和数据挖掘参考书

The elements of statistical learning : data mining, inference, and prediction
ISBN 9780387848570
Authors Haste, Trevor
Publisher Springer
Copyright Date c2009
Price $89.95

Applied predictive modeling
ISBN 9781461468486
Authors Kuhn, Max
Publisher Springer
Copyright Date c2013
Price $89.95

Data Mining: Practical Machine Learning Tools and Techniques
ISBN 9780120884070
Authors Witten, I. H., Frank, E. and Hall, M. A.
Publisher Springer
Copyright Date 2011
Price $75.95

感谢哥大同学提供参考。

自Java 7以来的数字证书兼容性问题

在使用JavaApns做IOS推送的时候报如下错误

javapns.communication.exceptions.
    InvalidCertificateChainException

使用Java 6和PHP就没有问题。网上粗略调查过发现是java 7以来的安全机制的问题。尝试使用如下方法解决:

使用JDK 7附带的keytool做两次转换:

.p12 到 jks:

keytool -importkeystore -destkeystore temp.jks -srckeystore src.p12 -srcstoretype PKCS12

jks 到 .p12:

keytool -importkeystore -srckeystore temp.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore dest.p12

使用新生成的p12密钥文件,一切正常。

Openstack OpenVSwitch GRE 组网下的逻辑架构

虚拟化实例(虚拟机)产生数据包并将其通过其内部的虚拟网络接口( virtual NIC)比如eth0,发送出来,并被传送到计算节点的Test Access Point (TAP)设备上。从/etc/libvirt/qemu/instance-xxxxxxxx.xml文件记录了当前设备的配置信息。

TAP设备的名称由端口ID的前11位组成(10位十六进制码和1位连字符),所以另外一种获取TAP设备名称的方法就是使用neutron命令。neutron port-list命令返回端口列表,第一项是端口ID。利用这里输出的前11个字符,我们可以得到相应TAP设备的名称。



TAP设备连接到整合网桥 br-int。该网桥连接所有实例的TAP设备以及系统内的其他网桥。在本例当中,有 int-br-eth1patch-tun接口。int-br-eth1是连接到br-eth1网桥的桥臂的一端,处理物理接口eth1上承载的VLAN。patch-tun是OpenvSwitch的内部端口,连接到br-tun网桥,用来提供GRE封装隧道网络。

网络节点侧的br-int整合网桥,集成了相应的网络功能,比如DHCP服务(dnsmsq),NS服务(dnsmsq),3层路由服务(实际上就是利用netns和iptables做的隔离),安全组和防火墙(iptables)。还有br-ext可以提供外网的接入支持。

计算节点导网络节点之间的通信,有多种方法实现。可以采用2层VLAN/Vxlan的方式(br-eth1),或者在三层上打GRE隧道(br-tun)。

MySQL 自增ID 和 UUID 做主键的初步性能研究

这几天在纠结数据表主键的设计问题,考虑使用自增ID还是UUID来做主键,数据库后端为MySQL。
首先在互联网上搜索,得到实测 Mysql UUID 性能这篇文章,他的结论是:

当数据表的引擎为MyISAM 时,自增 ID 无疑是效率最高的, UUID 效率略低,但不会低到无法接受。一旦数据引擎为 InnodB 时,效率下降非常严重,已经达到令人发指的地步。由于 InnodB 主键采用 聚集索引 ,会对插入的记录进行物理排序,而 UUID本身基本上是无序的,所以造成了巨大的 I/O 开销。所以如果使用 innodB 千万不要使用 UUID 。

结论经过我后来的测试验证基本正确,但是对这篇文章中间的测试方法不敢苟同。

其测试过程中重大错误:针对自增id的两个表的插入操作没有写入varchar字段,考虑到varchar插入的性能消耗,这一点是绝对不能够忽略的!

建立四张测试用表:

uuidtest_inno(uuid,text),
idtest_inno(id,text),
uuidtest_myisam(uuid,text),
idtest_myisam(id,text)

建立四个存储过程,测试数据量插入100 000行:

DROP PROCEDURE IF EXISTS p_uuid_inno//
CREATE PROCEDURE p_uuid_inno()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i

清空这四个表:

TRUNCATE inttest_inno//
TRUNCATE uuidtest_inno//
TRUNCATE inttest_myisam//
TRUNCATE uuidtest_myisam//

执行存储过程:

call p_int_myisam()//
call p_uuid_myisam()//
call p_int_inno()//
call p_uuid_inno()//

发现执行时间巨长无比。无奈,将测试数据量缩减到1000次插入。
myisam的时间都是0.2s左右,innodb为55s左右。

考虑数据库优化,放弃ACID支持,
设置 innodb_flush_log_at_trx_commit = 2
得到:

mysql> call p_int_myisam();
Query OK, 1 row affected (2.02 sec)

mysql> call p_uuid_myisam();
Query OK, 1 row affected (2.63 sec)

mysql> call p_int_inno();
Query OK, 1 row affected (9.71 sec)

mysql> call p_uuid_inno();
Query OK, 1 row affected (13.88 sec)

再设置 innodb_flush_method = O_DIRECT
得到:

mysql> call p_int_myisam();
Query OK, 1 row affected (2.06 sec)

mysql> call p_uuid_myisam();
Query OK, 1 row affected (2.56 sec)

mysql> call p_int_inno();
Query OK, 1 row affected (7.59 sec)

mysql> call p_uuid_inno();
Query OK, 1 row affected (10.88 sec)

再设置 innodb_log_buffer_size = 8M(之前的设置是3M)
得到:

mysql> call p_int_myisam();
Query OK, 1 row affected (1.96 sec)

mysql> call p_uuid_myisam();
Query OK, 1 row affected (2.63 sec)

mysql> call p_int_inno();
Query OK, 1 row affected (5.28 sec)

mysql> call p_uuid_inno();
Query OK, 1 row affected (9.59 sec)

可以看到对innodb来说插入速度低于myisam,这与选择uuid还是自增ID做主键没有太大的关系,uuid的确要比自增ID慢但是不至于说是数量级上的慢。

利用Java获取网络标准时间

import java.net.*;
import java.io.*;
public class DaytimeClient
{
	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		String[] hostname = new String[]{"", "time.windows.com","time.nist.gov","time-nw.nist.gov","time-a.nist.gov","time-b.nist.gov"};
		int i = 1;
		boolean RecvFlag = false;
		if(args.length > 0)
		{
			hostname[0] = args[0];
			i = 0;
		}
		while(i <=5 && !RecvFlag)
		{
			try
			{
				Socket timeSocket = new Socket(hostname[i], 13);
				InputStream timeStream = timeSocket.getInputStream();
				StringBuffer time = new StringBuffer();
				int c;
				while((c=timeStream.read()) != -1)
					time.append((char)c);
				String timeString = time.toString().trim();
				System.out.println("It is " + timeString +" at " + hostname[i] +" on port " + timeSocket.getPort());
				RecvFlag = true;
				timeSocket.close();
			}
			catch(UnknownHostException e)
			{
				System.out.println("Failed to get the information from " + hostname[i]);
				System.out.println(e);
				i++;
			}
			catch(Exception e)
			{
				System.out.println("Failed to get the information from " + hostname[i]);
				System.out.println(e);
				i++;
			}
		}
		if(i == 6)
			System.out.println("Failed to get the information please check your network settings.");
		else
			System.out.println("Complete.");
	}
}

JavaApplet程序编译注意事项

首先附上一JavaApplet的Helloworld程序,及在html中的嵌入代码:
源代码路径:JavaAppletsrcHelloworld.java
JavaAppletbinJavaTest.html

import java.awt.*;
import java.applet.*;
public class HelloWorld extends Applet
{
	public void paint(Graphics g)
	{
		g.drawString("Hello World!", 5, 35);
	}
}
<HTML>
<HEAD><TITLE>JavaApplet-Text</TITLE></HEAD>
<BODY>
<applet code = "HelloWorld.class" width = 200 height = 200></applet>
</BODY>
</HTML>

要使上述代码正常运行要注意以下几点:
1、Helloworld.java编译成功后会在…bin中生成Helloworld.class文件,要将html文件同class文件放在同一目录下。若不在同一目录,则要在html中加入”codebase”代码,即

<applet code = "HelloWorld.class" codebase= "location" width = 200 height = 200></applet>

2、确保Java是最新版
3、在控制面板->程序->Java->安全设置中,把安全等级调到最低
4、不要为Helloworld创建包(package),否则要在html中指定包名。P.S.目前DS还不会指定包名=。=!

Wireless路由/接入点攻击

近些年来,越来越多的用户的网络接入方式由有线转向了无线,其中不乏大量的个人用户,使用着各式各样的消费级无线路由器/无线接入点。无线安全的发展也历经了十年时间,然而这并不代表个人用户所使用的无线鉴权方式的安全性得到了很大的改善。

在最开始,我们首先来记住一句话:

任何系统都有他的薄弱之处!

无线安全等级我大致划分如下:

  • 无无线安全性设置;
  • WEP安全设置;
  • WPA/WPA2安全设置。

对于企业用户来说,接入点不使用安全性设置一点问题也没有,他们完全可以利用认证网关的方式达到安全性要求,而忽略接入点的安全性以获得更高的兼容性。对于个人用户来说,不设置接入点鉴权,就意味着将你的网络没有防范的摆在每一个人面前,除去数据被截获的担忧意外,对于一般个人用户来说更重要的是,你向运营商付费获得的带宽可以很轻易地被他人占用,或者说,被蹭网。

那么我们现在来看一下两大安全鉴权方式:

WEP

这是一个过时的方式。面对蹭网者,WEP加密仅仅是在不加密的基础上多了一层窗户纸。这层窗户纸能够帮你挡掉小白型的机会蹭网者,但是对有着丰富蹭网经验的人来说,真的是一层窗户纸而已。

这是因为WEP在设计的时候有漏洞,他不会更新IV(初始向量),导致了攻击者在截获了足够数量的数据包以后,完全可以用一定的算法计算出你的加密密钥。一般来说15000数据包是足够计算的了。

破解WEP加密,主要的时间消耗在于数据包的获取,一旦有了足够的数据包,解密只是十几秒的事情。

在没有其他因素干扰的情况下,数据包的获取速度与在线客户端网络使用量、攻击者与接入点之间的信号强度成正比。而攻击者可以使用各种注入攻击,虚假ARP请求等方式来加速获取数据包。另外,有实验表明,无客户端连接的情况下,也完全可以达成对WEP加密的接入点的攻击。

WPA/WPA2

这种加密方式与WEP相比有了很大的提高,他会定时更换随机生成的IV,就目前来说还没有一个像WEP一样的漏洞可以保证一定能够获得加密密钥。但是记住,任何系统都有薄弱点,这个薄弱点很可能就是用户自己!WPA强制使用8位以上密钥,但是如果这个密钥只是弱密码呢?笔记本把8位纯数字跑一遍也不过4个小时,更何况8个1,8个0,12345678或者年月日这种弱密码呢!WPA/WPA2的攻击方法是截获握手包并且利用预先生成的字典文件进行检测。在有客户端连接的情况下,握手包的获取速度很快,一般在5分钟以内。使用Fake Auth等方法更能加快这一过程。在我的笔记本上,Windows下的EWSA可以达到7000key/s的检测速度,弱密码跑一遍估计就是2秒钟。

那么是不是说设置一个复杂的长密码就可以高枕无忧了呢?不是这样的。现在很多家用路由器提供了快速连接WPS功能,一般是通过物理按钮完成无密钥连接。但是WPS实际上还有一个PIN码连接的功能,该功能的设计有缺陷,8位的PIN码全部跑一遍应该是(10^8)数量级,而设计缺陷使得8位PIN码被一分为三:4位第一部分,3位第二部分,1位校验位。所以实际上的数量级是:(10^4+10^3=11000),而平均期望为5500。

按照6s一个PIN码的保守估计,平均用时9小时就一定能够获得真实的PIN码和密钥。而考虑到实际过程当中,会使用加强天线等方式,以及各个厂家的PIN码其实是有规律可循的,总体时间可以控制在2小时以内。不管设置的密钥有多么长,多么复杂,一切皆是无用。