Welcome to Snooda's Blog
    最近遇到一个bug,定位了非常久,感觉有必要分享出来。。。避免后人掉坑。

    前段时间发现了一个raft主从间内存不一致的场景,导致切主后数据异常。。当时费了很大的力气排除掉其他模块逻辑问题。后来问题缩小到raft state machine里。由于raft高度依赖state machine幂等性(重启、切主都会导致状态机重做,如果逻辑不是严格幂等,就会出现状态不一致问题),一般要求日志中必须记录绝对操作,尽量不记相对操作。但有一个round-robin分配资源的场景,还是依赖了一下资源节点的排序问题。

    最早是使用std::map来存,使用迭代器遍历。由于map本身是有序的,所以三副本之间是一致的。
    后来有不熟悉的同学为了优化map的lg(n)性能,改用了基于哈希的unorderedmap,那么问题就来了。逻辑上map和unorderedmap都支持迭代器遍历。所以只修改数据类型,不修改逻辑是可以兼容的。简单执行也没有问题。

    已知unorderedmap肯定不能保证遍历结果的有序,但是目前场景也并不要求结果有序,只要每次遍历结果顺序不变就行,那么unorderedmap能否保证遍历顺序幂等性?目前看答案是“不能”。

    简单来想,hash表就是对元素做哈希,然后选定桶,对于桶内的元素就串到list上。那么只要按同样的顺序插入,似乎也是可以保序的。因为unorderedmap内部存在自动rehash过程。。一旦rehash,节点的遍历顺序就会变化。。。

    所以一定要重视“unordered”关键字。。。任何情况下unorderedmap都不保证任何顺序。。。。
Tags: ,
        生产环境线上一般是不允许开启conntrack的,因为默认的连接跟踪表也就万级别,不小心打满后,容易导致很难排查的网络问题。(iptables -t nat只查看也会不知不觉启用conntrack)所以很多团队是规定禁止线上运行iptables的。        但是某些设备上,conntrack是必备的一项功能,比如网关,用来做防火墙、包转发等。        今天就遇到了一个很特殊的场景。。表现特征是iptables配的MASQUERADE看起来并不生效。有时不知怎么回事生效以后,删掉规则居然仍然能转发。。明明删除了规则,居然还能ping通,新增了规则,居然还转发到老的地方。。

后来研究了一下,发现原来对于iptables的nat表来讲,只有连接新建时,才会查表进行一次匹配。当连接被conntrack后,就不再走nat表匹配了。
对于icmp来讲,默认conntrack会保留30s,所以如果添加规则前30s如果ping了一下。那么添加完并不会生效已有的。。。。反之亦然。
可以使用conntrack -E作为验证手段。该命令会打印conntrack模块对连接的跟踪情况。

如果想手动移除映射关系,可以使用conntrack -D
最近看到很多科技网站上提出,在ios10.3中引入了Apple File System,由此可以节省2GB的系统存储空间,个人对这个说法是持一定怀疑态度的,毕竟这个缩减比例还是有点高的。

昨天ios10.3 Beta3发布,决定实际测试一下升级效果。

找了一部16GB ipod touch6,升级前为10.1.1版本。剩余空间<500M。系统总可用空间是12GB+

安装ios10.3 Beta3描述文件后重启设备,可以看到新版本了,大小提示1.6GB,点击下载并安装,居然开始下载了,因为按现在的剩余空间是不够存放rom的,进入容量页面查看,发现可用容量持续上涨,按home进入主页面检查,发现app开始轮流显示“清理中”。等app都清理完后,扣除已下载的rom占用空间,系统多出来1-2GB的可用容量。此时系统并未升级。

然后进行升级,升级后进入系统,总可用空间依然是12GB+,大概比之前增加了500MB,可用空间比升级前(清理后)同步增加了500MB。

综上,升级后确实可用空间多出来2GB左右,但ios10.3升级本身只贡献了500MB,其余大部分都是ios在准备升级阶段调用清理操作节省出来的。

所以对于不想升级系统、又想获得空闲空间的同学,只需要点击升级,就会触发系统清理,清理完后停掉升级流程即可。







Tags:
    今天写了一个自动拉起脚本,调试的时候出了点状况,导致启动了很多个openvpn实例,并且还在不断启动中。对于使用同证书的实例,默认会后面的踢掉前面的,所以网络就陷入了还没连上就被踢掉的循环,无法登陆,也就失去了控制。

    首先尝试打开server端的duplicate-cn支持。这样每个连接都会分配到一个单独ip,不会互相踢掉。但由于进程太多,每个进程连接上后都试图刷新路由表,导致路由表不停变更,网络依然不能连通。

    这时就需要从server端限制:只能有一个客户端连接上。首先调研了下是否支持只接受第一个连接上的实例而忽略掉后面的连接请求,发现是没有这个特性的。因为如果正常使用中客户网络闪断,这种情况下就不得不等待很久session超时后才能连上,用户体验太差。

    对于网络层面的控制,iptables是个很有效的利器。于是采用了如下的方式:
    1,首先设置DROP掉指定机器所有入包     iptables -I INPUT 1 -p udp -s xxx.xxx.xxx.xxx -j DROP
         这时候所有连入请求都会timeout。
    2,然后使用tcpdump host xxx.xxx.xxx.xxx
         查看所有连入请求的来源端口,选取其中一个。
    3,执行          iptables -I INPUT 1 -p udp -s xxx.xxx.xxx.xxx --source-port yyyyy -j ACCEPT
         为这个实例单独开一个入口。

等待几秒,等待其重试连接,这时候只有这一个实例可以连入。成功恢复连接。

这里需要注意,第一步应使用DROP而不是REJECT,因为前者会让请求方重试的时间间隔更长一些,为后续操作赢得更多时间。









Tags:
    早在大学的时候就买过一套电烙铁。大概二三十块吧。有一个电烙铁、烙铁架、松香、海绵、一小卷焊锡丝。当时也没怎么用过,后来小焊锡丝找不到了。于是又买过3块钱的一小管焊锡。前几年试图在洞洞板上焊接一个51最小系统,焊接的很痛苦。感觉焊锡丝很难溶化,并且化了也不往电路板上沾,都堆在烙铁头上。当时以为是因为操作技术问题。后来由于树莓派、arduino的兴起,很多传感器都有焊接好的最小系统板卖了。只需要杜邦线插一下就能完成连接,焊接这事就放下了。

    前段时间买了一块tm7705,排针没有焊,于是又把尘封很久的设备翻了出来。依然难用,搞了很久也不行,上了助焊剂也毫无作用。思考了一下,既然焊锡丝不好化,是不是烙铁温度不够?于是上京东搞了一个宝工的206焊台,心想这下换了高级设备是不是就可以搞定了。。。买回来后发现依然如故。温度调到350以下焊锡丝不化,400度以上能化但是不沾板,并且烙铁头很容易就烧死了。上网仔细搜了下教程。发现问题主要有两个:一个是手法问题,即应该是烙铁头加热引脚几秒后,焊锡丝接触烙铁头和引脚溶化焊接。而不是先把焊锡丝化到烙铁头上往引脚涂,因为这么操作焊盘温度不够,就会不沾锡,并且焊锡沾到引脚就凝固,会虚焊,焊点形状也不好控制;第二个就是焊锡丝质量很可能有问题,有人提到焊锡丝不容易化或者焊点呈豆腐渣样有一个原因是铅和杂质比例太高。由于大部分情况下我的焊锡丝直接按到烙铁头上都不能融化,那么手法问题就是其次的了,焊锡丝质量的问题更大一些。于是决定重新买一些焊锡丝。


    调研了一下,出于健康考虑,现在工业生产用的焊锡已经不允许含铅了。但是卖的焊锡丝很多还是传统的铅锡合金。这种焊锡丝熔点低,焊点亮,所以在diy市场里还是很受欢迎。我倾向于健康一些的无铅焊锡。于是调研了一下。

    目前无铅焊锡主要是锡铜合金,99.3%的锡和0.7%的铜,熔点227度。比传统的63%锡铅合金的183度要高了四十多度。还有比较小众的锡银合金,主要是音乐发烧友使用(个人对于那零点几个点的银能否发挥什么作用持保留态度,不过b格是够了,可以号称焊出来的板子比小米的还nb了,不但含黄金,还含白银),熔点221度。还有黄花的锡银铜铈合金,含稀土不知道有什么特性。

    这次不敢随便买了,准备还是选择大品牌产品。首先还是考虑和焊台同品牌的宝工,宝工的无铅焊锡只有锡铜合金,含银的那款是含铅的。于是转向考虑其他品牌,发现广州黄花在烙铁和焊锡市场上也比较受欢迎,于是选择了黄花的锡银焊锡。为了不把鸡蛋放到同一个篮子里,还选了友邦的锡铜焊锡。前两天收到了。做工比较精致,今天打开试了一把。刚开始心情还是比较忐忑的,毕竟无铅焊锡焊接难度要高一点。先尝试黄花锡银,打开焊台调到325度,十几秒后温度稳定。烙铁加热焊点->加焊锡,很快焊锡就融化了,向上抬起烙铁头,一个焊点就焊好了。。果然不是一个世界的体验,换用友邦,也很顺利。。。原来问题的根源在于几块钱的焊锡丝。。



    终于掌握了焊接技术,以后diy的自由度又高了一些,不用再忍受乱糟糟的线了。没想到的是问题居然一直出在最不起眼的几块钱的焊锡丝上。。。搞diy还是不能马虎啊,新手更应该用好东西。否则出了问题都不知道是啥原因。



dns缓存nscd原理及相关知识

[| 不指定 2016/06/12 15:05]
    由于sshd是支持包转发的。所以最近配置了一些规则,将指定uid的包转发到指定目标。通过统计包数量,发现tcp的数据是正常的,但dns请求包不生效,还是走原路径。tcpdump抓包发现确实是发到系统配置的resolver那里去了。看了眼sshd的代码,是使用了libc里面的res_query方法来做域名解析的。像gethostbyaddr也是使用的这个方法。考虑到可能是这里发生的问题,于是用strace抓包看了一眼。发现该方法是先去连接/var/run/nscd/socket。如果成功,则发送域名解析请求,然后由nscd服务进行dns解析。所以按uid来抓包会失效。

    nscd是一个缓存服务。会缓存passwd、hosts、resolv三类信息。和dnsmasq类似。先试图停掉nscd服务再进行尝试,果然进程在试图连接/var/run/nscd/socket失败后,转为连接resolv.conf里指定的server,可以成功被iptables转发。


    定位了具体问题原因后,开始寻找更多解决方案。停掉nscd固然最简单,但会导致整个系统都失去dns缓存,对性能还是有一定影响的。于是寻找优化一些的方案。思路是对于指定进程绕过nscd机制。


    研究了一下。发现nscd为了避免自己的请求发送给自己导致死循环,调用了一个__nss_disable_nscd方法。调用该方法后即可关闭nscd机制。于是改动了一下sshd源码,重新编译了一个。再次重试。果然ok了。












Tags: ,
最近由于需要拨号到l2tp vpn服务器上。弄了一下linux下的客户端xl2tpd
其实xl2tpd既可以当服务端。又可以当客户端。在本文里只介绍客户端相关的功能

安装比较简单。apt-get或者yum直接搜xl2tpd,装上即可。没有自己编译也很简单。
注意依赖了/dev/ppp设备。如果不存在,需要
mknod /dev/ppp c 108 0
创建一下。

配置文件/etc/xl2tpd/xl2tpd.conf
[lac myvpn]
name = 'myvpn'
lns = myvpn
pppoptfile = /etc/ppp/peers/myvpn.l2tpd
ppp debug = yes

配置文件 /etc/ppp/peers/myvpn.l2tpd
remotename myvpn
user "xxx"
password "ooo"
ipcp-accept-local
ipcp-accept-remote
refuse-eap
require-mschap-v2
noccp
noauth
noipdefault
mtu 1410
mru 1410
usepeerdns
debug
lock
connect-delay 5000


然后就可以启动xl2tpd。然后echo "c myvpn" > /var/run/xl2tpd/l2tp-control
来连接了。

注意ppp的配置里有:noipdefault  选项。
其他很多资料都没有这一项。包括阿里云的官方文档。但在debian系里面。不加这个且机器有内网网卡时,是不太好用的。
连接的ppp0设备会自动使用内网ip。导致很多奇葩的事情发生。

noipdefault这个选项表示不使用本地默认ip分配策略。直接用服务器分配的。如果不要求每次拨号都使用固定ip的话,建议加上该参数




Tags: ,
    mysql中经常用到的字段类型就是varchar和char。一般还会指定长度用来规定最长可以支持多长的内容。那么问题就来了。对于utf8字符集来讲。一个字符所占的空间是1-6字节不等的。那么varchar(100)是指的字节数还是字符数呢?


    可以通过mysql官方文档来看:
    http://dev.mysql.com/doc/refman/5.0/en/char.html
    

The CHAR and VARCHAR types are declared with a length that indicates the maximum number of characters you want to store. For example, CHAR(30) can hold up to 30 characters.

    即支持的是30个字符(characters),而不是30字节(bytes)

    经测试,结果也是符合文档的。varchar(30)可以存储30个汉字


    附加问题:如果传入了超出长度的内容,会有什么结果。

If strict SQL mode is not enabled and you assign a value to a CHAR or VARCHAR column that exceeds the column's maximum length, the value is truncated to fit and a warning is generated.

     文档中提到。默认情况下会截断而不返回错误。如果需要返回错误,需要开启strict mode










Tags: ,

更换了泛域名证书

[| 不指定 2015/01/22 00:26]
    之前搞的单域名ssl证书要到期了,最近正好搞了个泛域名证书,换上了。

    好久没更新blog了,比较忙。刷一下新文章。
    最近程序发现了个奇葩现象,即从文件载入的证书链用openssl校验是通过的,而用curl远程获取的就校验失败,错误码7。而这些内容写入文件在下一次程序启动时载入校验,又是成功的。

    排查了各种内存泄露、不可见字符的可能性后。突然想起来是不是libcurl静态链接了openssl跟主程序动态链接的打架。查看后发现libcurl未静态链接openssl。

     不过这也是一个启示。想起来既然curl也用到了openssl,那么它在最后cleanup的时候会不会把全局的openssl数据结构给释放掉。


     尝试了一下,果然好了。原来我在一个函数里开头调用curl_global_init,结尾调用curl_global_cleanup。这样的话在程序结束时就会释放openssl的全局数据结构。导致后续调用证书校验报错。

     不过openssl也不够友好,报证书签名错误,让人很难联想到是初始化问题。


      不过aes加密部分并不受这个影响。
分页: 1/31 第一页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]