线上数据库崩溃,怀疑是utf8mb4编码导致的,目前已经重现,并找到具体的解决办法。

原因:
当支持utf8mb4的字段中出现emoji表情时,用like '%xx%'方式全搜索时,崩溃。
应该是MySQL的bug,怀疑是因为emoji的编码长度是4,而utf8_unicode_ci是3,MySQL的like非左匹配操作时,碰到占4字节的utf8mb4时出现问题(猜测)。

解决办法:
用instr函数取代like。不崩溃且效率高。instr('abcd','ab')值为1,instr('abcd','ca')值为0。即大于0为命中。

总结:在like左匹配的时候,用原生like靠谱。如果是两边匹配的时候,like支持复杂语法,所以效率较低。普通的%xx%类型的搜索,直接instr即可搞定。
另外:instr的大小写匹配跟like一样,默认是大小写不敏感的。

以下是完整的异常信息。

- 阅读剩余部分 -

最近申请了startssl的多个https证书,碰到一系列问题,逐个备忘一下。

1、nginx对同一个IP上多个域名证书的支持,下面的:TLS SNI support enabled。
[code]
#./nginx -V
nginx version: nginx/1.x.x
built by gcc 4.x.x 201xxxxx (Red Hat 4.x.x-x) (GCC)
TLS SNI support enabled
[/code]
如果不支持,需要重新编译openssl及nginx。

2、wget认证不过及firefox认证失败的问题。
[code]
ERROR: cannot verify www.xxxx.com's certificate, issued by `/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA':
Unable to locally verify the issuer's authority.
[/code]
某些浏览器或wget等工具没有内置StartCom Class 1 Primary Intermediate Server CA的证书为中级认证机构,认证链不完整,所以认证失败。
base64编码的cer,只需要把它的public的cer文件放到自己站点的public的cer下面即可。网上有人直接>>操作,导致中间没有换行,证书不认了,加个换行就对了。
加上它以后,它是被StartCom的根认证机构认证的,论证链就完整了。

3、apcache的Java的DefaultHttpClient,碰到nginx上配置多个证书时,访问其它域名的时候会出错。
[code]
javax.net.ssl.SSLException: hostname in certificate didn't match: <test.api.xxx.com> != <www.xxx.com> OR <xxx.com> OR <www.xxx.com>
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:228)
at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:149)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:130)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:641)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:480)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
[/code]
跟了一下代码,AbstractVerifier.verify中得到的确实是默认的www.xxx.com的证书链,第一个是当前站点,第二个是问题2中加的中级证机构的public证书。
再往下没跟动,怀疑httpclient是用ip得到的证书,也就意味着它不支持同一个IP多个域名证书。解决方案就是实现X509HostnameVerifier以取消域名的验证。
[code]
final X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() {

@Override
public boolean verify(String host, SSLSession ssl) {
return true;
}

@Override
public void verify(String host, SSLSocket ssl) throws IOException {//实际上只会调用这个。
}

@Override
public void verify(String host, X509Certificate cert) throws SSLException {
}

@Override
public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
}
};
final SSLSocketFactory ssf = new SSLSocketFactory(ctx, hostnameVerifier);
[/code]

如题,发现Workspace的.metadata目录暴涨,备份的时候略吃力。
找了一下,发现是maven的插件导致的,清理一下就可以了:.metadata/.plugins/org.maven.ide.eclipse/nexus

前几天让强子搭建VPN穿墙,很快搞定了,简单记录备忘之,以下是强子的原文转贴:

本次实验使用的centos 6.3 64bit。

一、安装之前检查系统兼容性。检查内核MPPE补丁,确定内核是否支持mppe:
[code]
modprobe ppp-compress-18 && echo ok
[/code]
如果显示ok,表示内核已经具备了mppe支持。

二、安装VPN需要安装三个组件ppp、pptp、pptpd。本机yum命令有问题,只能通过wget方式进行。
可以到http://pkgs.org/search/pptpd?type=name这个网站上进行查找相应的安装包:
1.下载:
[code]
wget http://mirror.centos.org/centos/6/os/x86_64/Packages/ppp-2.4.5-5.el6.x86_64.rpm
wget http://mirror.centos.org/centos/6/os/x86_64/Packages/pptp-1.7.2-8.1.el6.x86_64.rpm
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/pptpd-1.4.0-3.el6.x86_64.rpm
[/code]
2.安装:
[code]
rpm -ivh ppp-2.4.5-5.el6.x86_64.rpm
rpm -ivh pptp-1.7.2-8.1.el6.x86_64.rpm
rpm -ivh pptpd-1.4.0-3.el6.x86_64.rpm
[/code]

三、以上把需要的三个组件都已经安装完毕,我们接下来进行配置。
1.pptpd的配置文件在/etc/pptpd.conf。
(1)在这个文件中需要把logwtmp注释掉:
[code]
#logwtmp
[/code]
(2)然后配置本机的内网IP地址,以及客户端拨号进来后所要分配的IP地址:
[code]
localip 192.168.0.1
remoteip 192.168.0.201-250
[/code]
2.启用ms-dns。路径在/etc/ppp/options.pptpd。
该DNS可以填写公共的DNS服务器,也可以是你自己配置的。一般使用谷歌公网DNS:
[code]
ms-dns 8.8.8.8
[/code]
3.下面开始配置VPN访问的用户名、密码以及分配的IP地址。路径在/etc/ppp/chap-secrets。
[code]
user pptpd pwd *
[/code]
4.开启防火墙的IP转发功能,路径在/etc/sysctl.conf。
(1)把net.ipv4.ip_forward赋值为1:
[code]
net.ipv4.ip_forward = 1
[/code]
(2)保存并退出,使用sysctl –p命令使刚刚的配置生效。
[code]
sysctl -p
[/code]
5.在防火墙中添加规则允许NAT转换。命令如下:
[code]
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
[/code]
6.现在开始启动pptpd服务。
[code]
service iptables start
service pptpd start
[/code]
7.将服务配置为开机自动启动
[code]
chkconfig pptpd on
chkconfig iptables on
[/code]

四、客户端连接。
在VPN服务器上查看多了一张网卡,而且也可以看到VPN客户端获取到的IP地址:
[code]
ifconfig
[/code]

五、pptpd服务相关命令。
[code]
#重启:
service pptpd restart
#关闭:
service pptpd stop
#开启:
service pptpd start
[/code]

转自贝贝的blog,略有补充,贝贝的原贴地址:http://www.thinkingquest.net/articles/449.html

有两个补充之处:
1、GATEWAY配置
Centos的GATEWAY配置不仅在ifcfg-eth0中,也可能在/etc/sysconfig/network中。ifcfg-eth0中对单个网卡有效,network配置的是全局,作用范围不同。
原理都是改GATEWAY。

2、转发配置:
修改/proc/sys/net/ipv4/ip_forward是临时性的,是内核的当前运行状态,永久的改动位于:
/etc/sysctl.conf的
[code]
net.ipv4.ip_forward = 1
[/code]
改完后执行以下命令生效
[code]
#sysctl -p
[/code]
生效后,/proc/sys/net/ipv4/ip_forward会自动变为/etc/sysctl.conf中net.ipv4.ip_forward的值。

下面附上贝贝的原文(我这访问只能绑host访问贝贝的blog,原文转过来更方便)。
--------我是分隔线,以下是引用的全文----------

几个vps(虚拟主机),只有一个拥有公网ip地址,所有的vps都拥有内网ip地址。其它的vps需要通过拥有公网ip的这个vps进行公网访问,以方便yum安装软件等需求。

在没有公网ip的vps上需要进行的设置:

/etc/sysconfig/network-scripts/ifcfg-eth0 文件中: GATEWAY=10.x.x.x

service network restart

到此完成。

接下来是拥有公网ip的那台vps上进行设置:

echo "1" > /proc/sys/net/ipv4/ip_forward

注意,这条命令是临时开启系统的转发功能,系统重启后会恢复为默认设置。 可以通过在/etc/rc.d/rc.local中加入上述命令,使之在系统启动时被执行。

打开iptables的nat功能:

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

到此设置完成。

其它vps应该可以访问公网了。

缘起:线上发现一条慢查询日志,耗时32秒,对用户来说此次访问直接失败。

原因:用户长期未上线,拉群离线消息时扫描了几千万行数据。

现状:主键为消息唯一编号msgId,用户拉消息时,使用msgId > xxxx来拉,正常用户间隔较近,基本上耗时为毫秒。间隔越大,时间越长。

修改:当前msgId差值小于200w时,用主键索引。超出时,强制使用群编号groupId索引。msgId差值200w时用主键索引耗时为5秒左右。差值4000w时强制使用groupId索引,耗时600毫秒左右。

结论:用默认方案hold绝大多数的case,当特例出现时,强制使用另一个索引,确保用户可用。