关于TCP之序号与确认号

 

  1. tcp序号是两个方向的,每个方向有自己的序列号
  2. 依次发出的两个tcp数据包的序号可能相同、可能加1、也可能加更多,规则:
    1. 如果上个数据包不需要确认,则下个数据包的序号不增加
    2. 如果上个数据包没有数据,但是也需要确认,如SYN,则下个数据包的序号加1
    3. 如果上个数据包有n个数据,则下个数据包的序号加n
  3. 确认号比较简单,就是要确认的数据包的序号加1
  4. 确认包可以是包含在响应的数据包中的
  5. 不是每个数据包都要对应一个确认包的,一个确认包可以确认好几个数据包的,如:
    1. 由于接收方buffer比较大(就是tcp的win比较大),发送方连续发送了3个数据包,这时候,接收方可以只确认最后一个数据包就足以说明前两个数据包都已经收到了

wireshark 问题包分析

问题包如下图:

138 数据包问题: 其实 138、139、140 三个包是在某个设备上因超过mtu值而被拆分的一个包; 138是首先被收到的一个子包,所以有此标识

140数据包问题: 其实从ip的标识头(序号自增)来看,140应该出现在139前面,所以说:Out-Of-Order (就是所谓的乱序)

139数据包问题: 从ip的标识头来看,139前面应该有一个数据包没被抓到(其实就是140),实际是迟到了那么几微妙; 也就是说,如果140数据包能赶到139前面,那么139和140的问题就都没有了

142数据包问题: 从tcp协议的seq来看,141和142是重复了; 从ip数据包来看,这不是同一个数据包的重传,至于为啥会重复ack,不知道啊!

 

问题: ip分包标识是在ip协议上的,这里的重组为什么是reassembled TCP Segments

Etcd初步

源码: https://github.com/coreos/etcd

说明:

  1. master分支可能还不稳定,使用最新的release分支(下面测试的是2.3.6)
  2. 源码编译需要下载100MB左右的源文件,包含依赖文件(如果是在新的golang环境上编译的话)
  3. 如果在etcd目录下go install的话,只编译安装etcd,不编译etcdctl;需要进入ectdetl目录下go install,才会有etcdctl; 基本上就这两个二进制文件了
  4. 直接下载编译的文件比较快捷,而且这里有最新的release的二进制文件: https://github.com/coreos/etcd/releases/
  5. https://github.com/coreos/etcd 下面有一些参考文档的链接

 

集群配置:

https://github.com/coreos/etcd/blob/master/Documentation/op-guide/clustering.md

 

集群实现方式有三种:

今天了解了DNS Discovery,其中:

  1. DNS server使用的是dnsmasq
  2. DNS配置
    添加文件: /etc/dnsmasq.d/etcd.srv.conf

    其中:_etcd-server._tcp.        _etcd-client._tcp.  都是etcd自动添加的
    _etcd-server._tcp.    用于server之间交互,使用 2380 端口
    _etcd-client._tcp.     用于client(如: etcdctl )发现server,使用 2379端口

问题:

上面的dns配置基本是可用的,目前发现的唯一问题是: etcdctl –discovery-srv  etcd.i.beebank.com 来工作时,期望srv记录中拿到的是域名,而不是ip;不过etcd –discovery-srv  etcd.i.beebank.com 却没有这种苛求; 解决办法,把上面的IP换成域名,然后对域名做解析,而且,同一个域名解析出来多个IP也是不错的

 

修改如下:

/etc/hosts

/etc/dnsmasq.d/etcd.srv.conf

 

今天的测试没有涉及认证,server端启动参数:

其中:

–discovery-srv: 用于服务发现

–initial-advertise-peer-urls: 告诉其他成员,通过这个地址来联系我(对于服务发现的时候似乎用途不大,因为dns上已经注册了呀)

–initial-cluster-token: 应该是加群的暗号,暗号对不上是不让进群的

 

测试点:

  1. 通过proxy进行读写
  2. 同时通过单个实例进行读写
  3. 通过etcdctl的–discovery-srv进行读写
  4. 其中一个实例死掉一会儿,重启后依然能读到死后写入的数据
  5. 集群中一个节点到另一个节点之间都不止一个长连接
  6. 稍后测试一个全新的节点接入会是什么样子

======= v3.0.4 试用 ======

server端通过srv记录发现时,如果srv记录中解析到的是域名,则不会发现该域名下的所有IP (这个行为和v2.3.6不一致)

client端通过srv记录发现时,如果srv记录中解析到的是多个IP:PORT, 则etcdctl会试图解析已解析到的IP而报错

所以配置可修改成这样:

看起来好恶心

mysql 之 sql_mode

sql_mode 之影响:

  1.  sql_mode=’ansi’; 则当插入时,如果数据超长,则截断插入;有时候,这不是我们想要的

总结:

  • sql_mode=’TRADITIONAL’; 可以避免很多不必要的意外;

    TRADITIONAL 等价于 下面一系列标准的集合
  • 注意: 与innodb_strict_mode的区别

实际应用:

  1. 可以直接在 /etc/my.cnf 中修改sql_mode,如下:(需要重启mysql)
  2. 如果不方便重启mysql,则可以在执行sql语句前进行回话级别的设置,如下:

    (每次连接后都需要执行,比较麻烦;对于长连接的场景,该设置的花费可以忽略)
  3. 设置全局sql_mode:

    注意:
    1) 需要有超级权限
    2) 对当前session无效;要么退出再进来,要么再设置一下当前回话的sql_mode
    3)  该设置重启mysqld就没了,最好在my.cnf 中写一下

参考资料:

小米2刷机体验

首先, 刷机程序是windows程序,为此特地找了个windows的笔记本,虽然刷机过程还算比较快,但是,放下那个dell的windows,拿起mac,立马感觉舒服了好多。

刷机教程: http://www.miui.com/shuaji-393.html

如果第三步没有看到自己的手机,很可能是没有安装对应的USB驱动,设备管理器中有一个设备是带叹号的,参考: http://jingyan.baidu.com/article/e4511cf32d40e82b855eaf5e.html

到现在刷机完成已有半小时了,手机依然停留在开机的MI字界面,估计是刷坏了;让他起着吧,我先睡觉去

早上醒来,发现居然起来了,MIUI7的界面,????????

很快我就把一些主要的配置弄好了,然后,我这个小米2 的老毛病又犯了:屏幕触摸没反应,按键中只有一个重启功能有效,郁闷。。。。

 

sshd 之登录用户限制

问题:

linux机器配置了ldap验证,但是,又不期望ldap中所有用户都能登录,只是想用ldap中的密码,你们有一种办法就是通过pam_listfile.so 来实现,第一次配置非常顺利,立马就生效了;后来不小心执行了authconfig-tui ,配置文件就被重新生成了,手动添加的配置就没有了,再次添加就傻X了,怎么也不生效,都快哭了,如下图/etc/pam.d/password-auth 的一部分,因为/etc/pam.d/sshd include了这个文件,就直接在这里添加了,下图是正确的配置,错误的配置为:第5行写在了第6行的下面;

或者第5行直接添加在/etc/pam.d/sshd 文件中也可以,但是要写到 auth include password-auth 之前,否则也是不生效

暂且不知道原因,浪费了很多时间,555555555555

更正: 图中的 item=ruser 应该为 item=user

docker 之centos7虚拟机

想用docker安装一个centos7虚拟机,类似传统虚拟机那种;但是遇到一个问题,systemctl 启动服务的时候报错如下:

centos7默认使用systemd,其实 /usr/sbin/init 软连接的就是systemd,如果不用这个初始化,则目录: /run/systemd/system/ 是没有的; 也就是说,对于centos7,如果要想当做传统虚拟机来用,则首先要运行systemd进行初始化,而且需要超级权限,如此一来,宿主机将会感觉很不安全,如: 虚拟机可以直接修改宿主机时间。当启动的时候不适用超级权限来执行/usr/sbin/init ,虽然也能执行,但是依然不能使用systemctl来启动服务

结论: 在搞定该问题之前,暂不提供centos7的docker虚拟机

docker 容器资源管理

缘起

想用docker容器来做传统虚拟机的事情,但是从docker的api接口来看,如果限制容器的资源使用情况,需要在创建容器时指定,如: 内存、cpu等;一旦创建,将无法修改。

但是,资源限制本身就是运行时的事情,何故必须在创建时指定而且无法修改呢?比如:我创建一个容器允许使用4G内存,但是过了一段时间,我想将内存限制调整到8G,难道真的不行吗?

docker api似乎真做不到。

我们知道资源限制是通过cgroup实现的,其实可以跳过docker,直接调整cgroup也应该是可以的; 可以通过mount来查看各子系统都mount到哪里了。

如:

修改内存限制:

注意: 1. 如果容器已经使用了4g内存,修改为2g时会失败,错误如下:

2. 把占用内存多的进程先杀掉,让内存使用回归到合理值后,再降低内存配额是可以的

不过,有些东西目前还没发现如何修改,如: hostname

 

docker容器不同于真正的虚拟机,直接使用top、free等命令看到的是整个宿主机的资源使用状况,而无法知道本容器的资源限制和使用情况,可以借助一些监控软件:

http://www.tuicool.com/articles/nuE7b2E

参考资料:

php 之 xhprof

参考资料:http://blog.aboutc.net/profiling/17/php-profiler-xhprof

这里不说别的,只记录一个小有意思的事情:

由于所谓的PHP内存泄漏,在程序跑上几分钟后就耗尽内存而退出,据说xhprof很是厉害,可以分析是哪个函数占用了太多内存;由于xhprof没有现成的环境,配置起来花费了一些功夫,最后发现,是pdo_mysql的execute占用了90%+的内存,天哪,用了N多年的东西突然有问题了?冥思苦想,夜不能寐。

突然间,想到一个其他的办法,就是在每段代码前后添加memory_get_usage()来检查是否内存使用有发生变化,如果没有变化,则这部分代码没有问题;如果有变化,则这部分代码有问题;(注意:如果这部分代码有函数调用,则函数调用不应该有大的返回值,如果有自己看着处理);就这样,通过二分法一步一步排查,终于发现,小朋友为了提高性能,使用类的静态变量数组cache了sql查询的结果,这个cache没有大小限制。

然后回到xhprof分析的结果,可以想象,之所以xhprof认为pdo_mysql的execute有问题,是因为这些内存都是该函数申请的,你说pdo_mysql 冤不冤?