!!!由于MySQL官方驱动还不支持Group Replication,因此当前只是服务端可用,客户端驱动还需要等待新版本。

本文描述如何使用Docker+DockerCompose来部署一个MySQL的高可用集群。

此集群由3个MySQL实例组成,一个Master节点,2个Secondary节点。Master可读写,Secondary可读。集群之间会自动同步数据。Master失效剩余的Secondary会自动选举Master。

  • 请准备三台Linux VM(Ubuntu14.04),最好是异地的
  • 每台VM上请部署docker

由于公司内部网络隔离,很多地址需要从公司内镜像网站下载。请注意,某些配置步骤在可以直连外网的情况下并不需要。

配置Docker环境(每台VM)

  1. 在配置文件/etc/default/docker中DOCKER_OPTS选项添加--insecure-registry hub.witcloud.huawei.com,并重启docker服务
  2. 执行apt-get install python-pip
  3. 配置pip公司内网镜像

    1
    2
    3
    4
    5
    6
    7
    在~/.pip/目录下增加pip.conf文件

    然后编辑其内容为:

    [global]
    trusted-host=rnd-mirrors.huawei.com
    index-url=http://rnd-mirrors.huawei.com/pypi/simple/
  4. 安装docker-compose

    1
    pip install docker-compose

部署完成后就可以使用docker-compose来进行镜像的下载和容器的启动了。

Read More

简介

我们的某个服务突然有一天,所有的测试环境全部执行失败,返回500。结果到某台测试服务器上一看,磁盘空间满了!

最后发现是大量的历史版本Docker镜像未清理导致的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
noah-docker.host.huawei.com/noah-service/hunter         <none>              8470735ac8e2        4 weeks ago         1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> d88765ddc8fe 5 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 4aee0b83558a 6 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> add02e6af8f5 6 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 97eb4f2da485 6 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 95b8f4d92383 6 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> a2b51b2e138a 7 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 3b250877a8e1 7 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 3aa940434a99 7 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 68b1ec83803c 7 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 951db5450246 8 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 73b1750b31b9 8 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 13e7b553b4b7 8 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> 4ea2c3cdc7bc 8 weeks ago 1.121 GB
noah-docker.host.huawei.com/noah-service/hunter <none> a5bc7cef75d0 8 weeks ago 1.121 GB

在网络上查询了之后,可以使用docker rmi $(docker images -q -f dangling=true)命令来清理untagged镜像。执行之后清理出大概25G的空间。

1
2
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda2 36G 5.4G 29G 16% /

优化部署

由于测试版本的应用,版本号总是lastest,因此每部署一次就留下了一个untagged镜像。所以我们把清理脚本加入部署阶段,部署最新版本之前先执行一次清理。

1
2
3
echo "Clean old docker images"
docker rm $(docker ps -a -q)
docker rmi $(docker images -q -f dangling=true)

这样就能减少大量的untagged镜像,节省磁盘空间。

更新于2017-10-16

新版本Docker支持prune命令来清理悬挂镜像,使用更方便。

1
docker image prune

通过增加-a参数,我们还可以清理全部没有使用的镜像。

1
docker image prune -a

车侣网存在问题

首页加载慢

车侣网首页加载时间超长,需要30秒以上时间。

我们看看Chrome的加载记录:

homepage

通过加载记录我们可以很清楚的发现,图片加载占用了太多的时间。为什么图片加载这么慢?因为浏览器跟站点的并发数目是有限制的,一般是4-6个。这意味着如果把大量的图片都放在一个网站上,浏览器下载的效率很低,很多图片会处于pending状态,等待下载完成。

我们有什么办法改进首页的加载呢?方法如下:

  1. 有些图片的效果当前通过css文件已经可以完全实现。因此这部分的图片就直接转换为css代码,省去了单个文件的下载,容量也小很多。
  2. 采用按需加载图片模式。用户当前看到的部分才加载图片,看不到的就不加载,这也能极大得提升加载速度。
  3. 将图片保存在又拍云或者七牛云这种专业的图片存储商上,价格挺便宜。

网站设计不合理

商城是一个负荷很高的网站,不应该跟车侣网放在同一个服务器上,应该单独放一个服务器。

jstorimer的博客翻译

Nobody understands the GIL Part1

什么是GIL

提起Ruby的多线程,就不得不说Ruby里面的GIL。GIL全称是Global Interpreter Lock(全局解释器锁),那么GIL到底是啥呢?

1
MRI有一个全局的解释器锁。它用于锁住Ruby代码的执行。这意味着在一个多线程环境中,在同一个时间,只有一个线程能够执行Ruby代码。

因此,如果你有8个线程,工作在一个8核的CPU机器上,在任何时间中,只有一个线程能够在其中一个核上运行(不过这个不一定表示每次都运行在同一个核心上)。GIL用于保护Ruby内部,用于防止产生竞争环境(race condition),进而导致数据损坏。

问题

往数组中增加数据不是线程安全的

在Ruby中,只有很少的操作默认是线程安全的。比如,往数组中增加元素:

1
2
3
4
5
6
7
8
9
10
11
array = []
5.times.map do
Thread.new do
1000.times do
array << nil
end
end
end.each(&:join)
puts array.size

这里有5个线程共享1个数组对象。每个线程往数组里面push1000次nil。所以到最后,数组里面应该有5000个nil,是吧?

1
2
$ ruby pushing_nil.rb
5000
1
2
$ jruby pushing_nil.rb
4446
1
2
$ rbx pushing_nil.rb
3088

这么一个简单地例子,已经暴露出Ruby的一个操作不是线程安全的。在这里到底发生了什么?

Read More

简介

拓扑映射是一个用Ruby实现的组网图搜索算法,用于在大的组网图中搜索满足用户要求的小组网。老版本的拓扑映射算法基于老旧的ruby1.8.6,用户已经多次反馈效率低下。听闻ruby推出了新的2.2版本,我们能否利用新版本ruby的高性能呢?

平台级优化

我们首先考虑代码不做大改动,切换平台和Ruby版本进行优化。方式如下:

  • Ruby升级到最新版本 2.2
  • 使用 Linux 替换Windows

我们使用一个运行时间很长的测试数据来测试性能,测试机器都是公司的E6000高配服务器,12核3.2G至强CPU(CRuby只能用单核,多核没意义)。测试结果请参考下图:

Ruby版本 操作系统 计算时间(秒)
Ruby 1.8.7 Windows2008 790
jruby 9.0.0.0.pre1 Ubuntu 12.04.2/JAVA7 559
Rubinius 2.5.3 Ubuntu 12.04.2 547
jruby 9.0.0.0.pre1 Ubuntu 12.04.2/JAVA8 516
Ruby 2.1.3 Windows2008 436
Ruby 2.1.3 Ubuntu 12.04.2 324
Ruby 2.2.0 Ubuntu 12.04.2 314

从数据来看,在Ubuntu平台的Ruby2.2性能最好。在执行过程中,Rubinius出现过随机错误,感觉不是太稳定。

Read More

淘汰bat/vbs/js吧!

OCRA是一个一键式Ruby打包工具,可以将Ruby脚本及所需环境构建为一个单独的Exe文件发布,用户环境上没有Ruby也可以运行!在公司内部作为小工具使用特别方便。

功能:

  • LZMA压缩(可选,默认打开)
  • 支持Ruby 1.8.7 / 1.9.3 / 2.0.0 ( 通过RubyInstaller安装的版本 )
  • 支持命令行和视窗模式
  • 根据使用包含gem包,或者从gemfile包含gem包

OCRA下载:传送门

使用介绍

ocra的使用方式很简单,只要安装了ocra之后,执行

1
ocra script.rb

即可生成script.exe文件,包含script.rb文件,Ruby解释器和所有的依赖项(DLL文件和gem包)。

实例

test.rb文件打包,生成print_time.exe文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
d:\work\open_source\personal_blog\gem_roadmap\problem>ocra D:\temp\test.rb --output D:\temp\print_time.exe
=== Loading script to check dependencies
********************
Time.now = 2014-02-07 16:52:37 +0800
Time.now = 2014-02-07 16:52:37 +0800
Time.now = 2014-02-07 16:52:38 +0800
Time.now = 2014-02-07 16:52:38 +0800
Time.now = 2014-02-07 16:52:38 +0800
Time.now = 2014-02-07 16:52:38 +0800
Time.now = 2014-02-07 16:52:38 +0800
Time.now = 2014-02-07 16:52:39 +0800
Time.now = 2014-02-07 16:52:39 +0800
Time.now = 2014-02-07 16:52:39 +0800
********************
=== Including 53 encoding support files (3194880 bytes, use --no-enc to exclude)
DL is deprecated, please use Fiddle
=== Building D:/temp/print_time.exe
=== Adding user-supplied source files
=== Adding ruby executable ruby.exe
=== Adding detected DLL C:/Ruby200/bin/zlib1.dll
=== Adding detected DLL C:/Ruby200/bin/LIBEAY32.dll
=== Adding detected DLL C:/Ruby200/bin/SSLEAY32.dll
=== Adding detected DLL C:/Ruby200/bin/libffi-6.dll
=== Adding library files
=== Compressing 10006304 bytes
=== Finished building D:/temp/print_time.exe (2518489 bytes)

运行后即可生成print_time.exe文件,此文件可以在没有安装Ruby的机器中运行。

注意事项

1.9.3之后的RubyInstaller不支持WindowsXPWindows2003。如果要支持老版本Windows(公司内部很常见),请制作EXE文件时选择1.9.3版本的Ruby。

Ruby选择器

你还在为如何使用系统中的各个版本的Ruby而烦恼吗?Uru正是为你设计的。

如何使用

很简单。

  • 在C盘根目录创建一个tools文件夹,然后将tools目录加入系统PATH环境变量,供命令行使用
  • 下载已经编译好的二进制文件,解压到tools目录中
  • 然后打开命令行,执行

    1
    2
    C:\tools>uru_rt admin install
    C:\tools>uru_rt admin add system

到此安装完成。

增加ruby

也很简单。

  • 启动命令行
  • 增加包含ruby.exe的路径到uru中

    1
    2
    uru admin add c:\Ruby193
    uru admin add c:\Ruby21
  • 使用uru ls看下当前安装了哪些ruby

    1
    2
    3
    4
    d:\work\open_source\super-deploy-script\ocra>uru ls
    => 193p550 : ruby 1.9.3p550 (2014-10-27) [i386-mingw32]
    213p242 : ruby 2.1.3p242 (2014-09-19 revision 47630) [i386-mingw32]
    system : ruby 1.8.7 (2013-06-27 patchlevel 374) [i386-mingw32]

切换Ruby

然后即可使用uru 部分名称来进行ruby的切换,比如:

1
2
3
4
5
6
7
8
uru 19 # 切换到ruby 1.9.3p550
---> Now using ruby 1.9.3-p550 tagged as `193p550`
uru 21 # 切换到ruby 2.1.3p242
---> Now using ruby 2.1.3-p242 tagged as `213p242`
uru 2 # 切换到ruby 2.1.3p242
---> Now using ruby 2.1.3-p242 tagged as `213p242`

更多的文档可参考uru的wiki

还在为Ruby代码的质量担心吗?SimpleCov来帮助你了!

SimpleCov是啥

SimpleCov是一个Ruby代码覆盖率分析工具。它使用Ruby内置的代码覆盖率库,但是提供一个更清晰、简单的API用于过滤、分组、合并、格式化和显示这些数据。

看看在我们项目中实际应用中的效果:

Read More

ruby 2.0 json的坑

ruby2.0已经内置了对json的支持,不过在使用时遇到了一些问题。上代码:

1
2
3
4
5
6
7
8
9
10
11
File.open(omsys_file, 'r') do |f|
omsys_data = JSON.parse(f.read)
converter = CawGenerator::Caw::Converter.new
ret = converter.convert(omsys_data, error_file)
File.open(out_file, 'w') do |f|
f.write(JSON.pretty_generate(ret))
end
end

结果代码在JSON.parse的时候抛出异常了:

1
2
3
4
C:/Ruby200/lib/ruby/2.0.0/json/common.rb:155:in `encode': "\xA7\x86" from GBK to UTF-8 (Encoding::UndefinedConversionError)
from C:/Ruby200/lib/ruby/2.0.0/json/common.rb:155:in `initialize'
from C:/Ruby200/lib/ruby/2.0.0/json/common.rb:155:in `new'
from C:/Ruby200/lib/ruby/2.0.0/json/common.rb:155:in `parse'

啥原因呢?从错误来看是Json无法把GBK格式编码转换为UTF-8编码。不过我已经确认过了,要打开的json格式文件确实是UTF-8格式,怎么会是GBK编码呢?

Read More