国内云平台价格对比(青云、阿里云、腾讯云),截至 2016-07-13

这两天没事,对比了一下国内几大云平台的成本,对比下主机、宽带、LB、CDN、备份等,先从主机开始吧。

QQ20160713-0

产品类型、规格                   青云                   腾讯云                   阿里云                   备注

北京:1核1G                       72元/月              45/月                     82/月                      腾讯云,买10个月送2个月,阿里云特惠买9个月送3个月

香港:1核1G                       115元/月            无货                       90/月                      阿里云默认送40G硬盘,其它云送20G

北京:4核8G                       500元/月            400/月                   427/月                    腾讯云,买10个月送2个月,阿里云特惠买9个月送3个月

香港:4核8G                       712元/月            400/月                   568/月                    

北京:1M带宽                     23元/月              20/月                     23/月                      腾讯云,买10个月送2个月,阿里云特惠买9个月送3个月

香港:1M带宽                     27元/月              20/月                     30/月                    

北京:10M带宽                   622元/月            565/月                   525/月                    腾讯云,买10个月送2个月,阿里云特惠买9个月送3个月

香港:10M带宽                   778元/月            565/月                   650/月                    

缓存穿透、并发和失效、同步中断,最佳实践及优化方案

原文摘自:

缓存穿透、并发和失效,来自一线架构师的解决方案
https://community.qingcloud.com/topic/463

在我们的实践中,原文中有部分解决方案已经过时,在原文的基础上,添加了几个我们常用的方案。
by shuhai, admin@4wei.cn


我们在用缓存的时候,不管是Redis或者Memcached,基本上会通用遇到以下三个问题:

  • 缓存穿透
  • 缓存并发
  • 缓存失效
  • 同步、复制中断

##缓存穿透

![https://pek3a.qingstor.com/community/resource/pic/2016-6-23-cache-1.png][1]
![https://pek3a.qingstor.com/community/resource/pic/2016-6-23-cache-2.png][2]
![https://pek3a.qingstor.com/community/resource/pic/2016-6-23-cache-3.png][3]

注:上面三个图会有什么问题呢?

我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回。

这个时候如果我们查询的某一个数据在缓存中一直不存在,就会造成每一次请求都查询DB,这样缓存就失去了意义,在流量大时,可能DB就挂掉了。

那这种问题有什么好办法解决呢?

要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。有一个比较巧妙的作法是,可以将这个不存在的key预先设定一个值。比如,"key" , “&&”。

在返回这个&&值的时候,我们的应用就可以认为这是不存在的key,那我们的应用就可以决定是否继续等待继续访问,还是放弃掉这次操作。如果继续等待访问,过一个时间轮询点后,再次请求这个key,如果取到的值不再是&&,则可以认为这时候key有值了,从而避免了透传到数据库,从而把大量的类似请求挡在了缓存之中。

你应该注意,这里缓存未命中的原因,更值得我们关注。

当缓存空间满了,同步失败,网络阻塞,缓存写失败等原因,会出现缓存服务器上并没有这个key。
或者因为同步中断,在主从架构中,写到主却未同步到从的悲剧,就会出现请求穿透到DB层的情况。

出现这样的情况,一定不能直接将请求穿透到DB层,避免DB当机影响其它业务。
我们的解决方案可以参考。

  • 当业务中请求量特别高,缓存未命中的情况,应该在建立DB保护的基础上,放弃一定比例的请求,直接返回空
  • 可以随机释放一些请求到DB,控制好流量的话,能保证缓存重建且DB不受极端压力
  • 后端异步定时检查缓存,主动建立这些缓存
  • 通过建立二级缓存,把之前成功获取的缓存数据放到本机缓存,文件也好,共享内存也好,接受一些过期数据

##缓存并发

有时候如果网站并发访问高,一个缓存如果失效,可能出现多个进程同时查询DB,同时设置缓存的情况,如果并发确实很大,这也可能造成DB压力过大,还有缓存频繁更新的问题。
我现在的想法是对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。

这种情况和刚才说的预先设定值问题有些类似,只不过利用锁的方式,会造成部分请求等待。

##缓存失效

引起这个问题的主要原因还是高并发的时候,平时我们设定一个缓存的过期时间时,可能有一些会设置1分钟啊,5分钟这些,并发很高时可能会出在某一个时间同时生成了很多的缓存,并且过期时间都一样,这个时候就可能引发一当过期时间到后,这些缓存同时失效,请求全部转发到DB,DB可能会压力过重。

那如何解决这些问题呢?

其中的一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

我们讨论的第二个问题时针对同一个缓存,第三个问题时针对很多缓存。

接下来我们将发表一些自己的缓存高可用实践,如《基于云平台的缓存集群高可用实践》,欢迎关注。

总结
1、缓存穿透:查询一个必然不存在的数据。比如文章表,查询一个不存在的id,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成影响。
2、缓存失效:如果缓存集中在一段时间内失效,DB的压力凸显。这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。

当发生大量的缓存穿透,例如对某个失效的缓存的大并发访问就造成了缓存雪崩。

精彩问答
问题:如何解决DB和缓存一致性问题?

当修改了数据库后,有没有及时修改缓存。这种问题,以前有过实践,修改数据库成功,而修改缓存失败的情况,最主要就是缓存服务器挂了。而因为网络问题引起的没有及时更新,可以通过重试机制来解决。而缓存服务器挂了,请求首先自然也就无法到达,从而直接访问到数据库。那么我们在修改数据库后,无法修改缓存,这时候可以将这条数据放到数据库中,同时启动一个异步任务定时去检测缓存服务器是否连接成功,一旦连接成功则从数据库中按顺序取出修改数据,依次进行缓存最新值的修改。

问题:问下缓存穿透那块!例如,一个用户查询文章,通过ID查询,按照之前说的,是将缓存的KEY预先设置一个值,,如果通过ID插过来,发现是预先设定的一个值,比如说是“&&”,那之后的继续等待访问是什么意思,这个ID什么时候会真正被附上用户所需要的值呢?

我刚说的主要是咱们常用的后面配置,前台获取的场景。前台无法获取相应的key,则等待,或者放弃。当在后台配置界面上配置了相关key和value之后,那么以前的key &&也自然会被替换掉。你说的那种情况,自然也应该会有一个进程会在某一个时刻,在缓存中设置这个ID,再有新的请求到达的时候,就会获取到最新的ID和value。

问题:其实用Redis的话,那天看到一个不错的例子,双key,有一个当时生成的一个附属key来标识数据修改到期时间,然后快到的时候去重新加载数据,如果觉得key多可以把结束时间放到主key中,附属key起到锁的功能。

这种方案,之前我们实践过。这种方案会产生双份数据,而且需要同时控制附属key与key之间的关系,操作上有一定复杂度。

问题:多级缓存是什么概念呢?

多级缓存就像我今天之前给大家发的文章里面提到了,将Ehcache与Redis做二级缓存,就像我之前写的文章 http://www.jianshu.com/p/2cd6ad416a5a 提到过的。但同样会存在一致性问题,如果我们需要强一致性的话,缓存与数据库同步是会存在时间差的,所以我们在具体开发的过程中,一定要根据场景来具体分析,二级缓存更多的解决是,缓存穿透与程序的健壮性,当集中式缓存出现问题的时候,我们的应用能够继续运行。

ThinkPHP 3.2 性能优化,实现高性能API开发

需求分析

目前的业务全站使用ThinkPHP 3.2.3,前台、后台、Cli、Api等。目前的业务API访问量数千万,后端7台PHP 5.6,平均CPU使用率20%。

测试数据

真实业务
php5.6:500 QPS
php7.0:850 QPS

真实业务中减少一次Mysql查询业务或者减少一次Redis读写
php5.6:800 QPS
php7.0:1250 QPS

目前优化的结果:
ThinkPHP可以完整的跑在缓存中;
在不需要mysql查询时,不建立mysql连接;
不读写redis时,不建立redis连接。

以上数据在开发机器使用ab获取,同时也跟其它的框架做了简单对比,性能不低于其它框架。
使用zend debugger profile 可以看到框架层的时间开销占比约24%,相对于yaf这样的C语言框架10%的性能损失,一个包含缓存和ORM的框架已经算比较好的性能了。
再次吐槽一提ThinkPHP框架就喷性能不好的人,任何一个框架拿过来多做几次数据库操作,测试性能都渣得不逼,只测试输出一个HelloWorld并什么卵用。

优化过程

0x00

在项目中早期,开发压力大,没有什么时间进行项目和架构优化。
经过测试,通过添加 mysql 长连接和redis长连接,api稳定性得到非常大提升,业务最慢响应时间从4s优化到0.5s,曲线非常平稳。
PHP-FPM单机200进程,2000Request,7台PHP后端,长连接数稳定在1700左右。

产生的问题
长连接数超过5k时,性能会下降。出现过两次Mysql Server 内存用光的情况。

0x01

经过分析,发现很多API请求,是不需要建立Mysql连接的。调整代码,Mysql的查询逻辑尽量缓存到Redis里,减少对Mysql的压力。
同时对ThinkPHP的代码逻辑进行化,调用 Model 中的方法、属性,不建立Mysql连接,只有在读写db时才建立连接。减少了非常多的资源开销。
经过上述调整,Mysql的连接从1700下降到100以内,query and read QPS从5k下降到50。

优化的ThinkPHP的代码已推送到Github:

https://github.com/vus520/thinkphp/tree/shuhai/db_link_lazzy

后续是对ThinkPHP中Mysql主从、读写分离进行深度测试,增加Mysql的读能力。

0x03

当业务都严重依赖redis时,Redis的QPS一度飙升到7k,内存占用6G左右。
为了缓解redis的读压力,生产中使用了4台Redis Standalone做了1主3从架构。
并给ThinkPHP添加Redis读写分离的支持,减少Redis的压力。

https://github.com/vus520/thinkphp/blob/shuhai/db_link_lazzy/ThinkPHP/Library/Think/Cache/Driver/Redisd.class.php

目前存在的问题
Redis的高可用运维,本身也比较复杂,遇上网络抖动等原因,Redis会出现同步失败和延迟问题。
特别是在云服务器架构的环境中,网络瓶颈和延迟问题对分布式应用有非常大的影响。
很可惜,我们目前使用的青云,目前尚不能实现Redis超高可用,也不能实现无缝扩容,私网内的网络传输性能、延迟都有很大优化空间。

后续的优化计划
对redis业务进行清理,减少不必要的请求;
压缩内容;
key:value => hash;
一主多从,每个php后端部署一个redis从,优先读本机,减少网络延迟;

0x04

API项目中,禁用ThinkPHP的Session、路由、视图、行为等,进行精简加速。
经测试,性能有30%的提升。

https://github.com/vus520/thinkphp/tree/shuhai/tiny

  • 1,去掉路由
  • 2,去掉URL调度
  • 3,去掉行为、Hook
  • 4,去掉视图
  • 5,去掉控制器的反射、空操作
  • 6,去掉Session,可实现无状态的Api

0x05

在PHP7中进行深度测试,升级到PHP7,ThinkPHP 3.2的性能会有50+%的提升

Redis 优化要点

http://www.imooc.com/article/3645
http://www.cnblogs.com/mushroom/p/4738170.html
http://linusp.github.io/2015/12/16/redis-performance-analysis.html
https://segmentfault.com/a/1190000002906345

#info 分析

## Memory
>实际缓存占用的内存和Redis自身运行所占用的内存(如元数据、lua)。
>它是由Redis使用内存分配器分配的内存,所以这个数据并没有把内存碎片浪费掉的内存给统计进去
>如果used_memory > 可用最大内存,那么操作系统开始进行内存与swap空间交换
>当 rss > used ,且两者的值相差较大时,表示存在(内部或外部的)内存碎片。
>内存碎片的比率可以通过 mem_fragmentation_ratio 的值看出。
>当 used > rss 时,表示 Redis 的部分内存被操作系统换出到交换空间了,在这种情况下,操作可能会产生明显的延迟

>used_memory:9892187056
>used_memory_human:9.21G

>从操作系统上显示已经分配的内存总量, 包括碎片
>used_memory_rss:11148713984
>used_memory_peak:11236792296
>used_memory_peak_human:10.47G
>used_memory_lua:35840

## 内存碎片率
>内存碎片率稍大于1是合理的,这个值表示内存碎片率比较低,也说明redis没有发生内存交换。
>但如果内存碎片率超过1.5,那就说明Redis消耗了实际需要物理内存的150%,其中50%是内存碎片率
>若是内存碎片率低于1的话,说明Redis内存分配超出了物理内存,操作系统正在进行内存交换。内存交换会引起非常明显的响应延迟
>mem_fragmentation_ratio:1.13
>mem_allocator:jemalloc-3.6.0

## stats
>total_commands_processed:105868 #总共处理的命令数
>instantaneous_ops_per_sec:0
>rejected_connections:0
>evicted_keys:0 #因为maxmemory限制导致key被回收删除的数量

# 性能分析

## 延迟

>redis-cli -h 127.0.0.1 -p 6379 --latency
>持续采样,结果单位是ms;
>redis-cli -h 127.0.0.1 -p 6379 -–latency-history
>间隔采样,结果单位是ms;

## bigkeys

>redis-cli -h 127.0.0.1 -p 6379 --bigkeys
>持续采样,实时输出当时得到的 value 占用空间最大的 key 值

## 慢日志

>默认配置
>slowlog-log-slower-than 10000
>slowlog-max-len 128

>获取慢日志
>slowlog get 3

## 统计

>redis-cli -h 127.0.0.1 -p 6379 info commandstats
>查看所有命令统计的快照,执行次数,所耗费的毫秒数,总时间和平均时间

## 调试

>redis-cli -h 127.0.0.1 -p 6379 monitor

## 内存占用分析

redis-rdb-tools
>pip install rdbtools
>rdb -c memory /var/redis/6379/dump.rdb > memory.csv

# 优化与禁忌

停止使用 KEYS *,如果避免不了,请使用scan命令
精简键名和键值,减小key长度,压缩value
设置 key 值的过期时间,避免长时间占用内存,缓解同步和持久化的压力
选择合适的回收策略,如果不能丢数据则建议使用 volatile-lru 策略,如果key可以自动重建则推荐allkeys-lru
业务层要考虑读写分离和主从模式
合理分配snapshot,aof,主上关闭aof和snapshot,在主从上开启snapshot和aof
如果数据不需要持久,可关闭所有的持久化方式可以获得最佳的性能以及最大的内存使用量
合理选择最优的数据结构解决实际问题,那样既可以提高效率又可以节省内存
合理使用长连接
maxmemory=8g, 不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5
sysctl vm.overcommit_memory=1
关闭vm-enabled,3.0以后默认废弃

解决保存快照失败后redis无法写入的问题
>config set stop-writes-on-bgsave-error no

定期日志重写,减小aof重载时的时间开销
>auto-aof-rewrite-percentage 100
>auto-aof-rewrite-min-size 64mb

# 安全
使用普通用户启动服务,且禁止该用户登录
在可以保证内网安全的情况下,无密码性能最好
客户端可能会发送config命令,会有安全问题,建议禁用
客户端可能会发送flushall、flushdb命令,为避免误操作,建议禁用
客户端可能会发送save命令,会严重影响服务器的性能,建议禁用并使用bgsave替代

>rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command KEYS ""
rename-command save ""

# 备份策略
主关闭aof, 开启rdb
每十分钟/10000变更生成一次rdb
每个小时保存一次最新的rdb到当前磁盘
每个小时保存一次

选择一台从节点,开启rdb,开启aof,并定期重载日志
```shell
path=/opt/data/redis/
name=dump_6380.rdb
file=$(date -d "yesterday" +"%Y%m%d%H.rdb")
/bin/mv $path/$name $path/$file
echo "move file $path/$file"

file=$(date -d "-3 days" +"%Y%m%d%H.rdb")
/bin/rm -f $path/$file
```

解决"Logstash不能识别unzip解压的文件"

step 1.

find *.zip -exec unzip -j {} \;

change to

find *.zip -exec unzip -aanXj {} \;

step 2.

#Here is a working workaround:

sudo vi /etc/init.d/logstash

#modify

LS_GROUP=logstash
#by

LS_GROUP=adm
#then

sudo /etc/init.d/logstash start

遇到一个两天都没有解决的问题。

启用新的es集群,elk都使用最新的2.0+版本,同时把以前的数据打包复制到新机器上进行解压。
配置好所有文件以后,发现logstash能正常启动却不能索引日志。

好像根本没有包含任何文件。
后来发现手工写的日志可以索引,把解压后的文件cat到新的文件中,也可以索引。

测试的时候,安装了logstash 2.0, 2.1, 2.2都不能解决。Logstash 1.5却正常。

解压的文件和自己生成的文件,用户组,用户权限,md5都完全一样,除了...

OneApm 的使用总结

我司的部分业务从去年起,开始接入OneApm,到目前已经有50台机器的规模。
业务层的Nginx、PHP、Mysql,到Redis、ElasticSearch监控,到业务模拟测试可用度,到自定义SDK实现的特殊业务监控,目前都有涉及到(http://www.4wei.cn/archives/1002578)。

总的来说,好评满满,DevOps时代不可或缺的必备工具服务。

QQ20160414-0

20+监控服务器,Nginx、Mysql、ES、REDIS、PHP_FPM等数个平台服务的监控

QQ20160414-1

配置自定义仪表盘

QQ20160414-2

设置告警策略

CentOS远程重装系统

公司内网的一台Linux弱口令机器让扫出来了,数据洗劫一空,悲剧啊
还好不是什么重要的东西,赶紧重装系统。

人不在公司,只能使用远程重装,方案如下:

Fedora 14需要下载的文件在http://nas1.itc.virginia.edu/fedora/releases/14/Fedora/x86_64/os/images/…
64位Centos需要下载的文件在 http://mirror.centos.org/centos-5/5/os/x86_64/images/pxeboot/

修改服务器的/boot/grub/grub.conf文件,在这个配置文件中,添加如下启动项:

title CentOS Reinstall
root (hd0,0)
kernel /vmlinuz vnc vncpassword=12345678 headless ip=10.36.64.238 netmask=255.255.255.0 gateway=10.36.64.254 dns=10.36.10.8 hostname=0map238 ksdevice=eth0 method=http://mirrors.163.com/centos/6/os/x86_64/ lang=
en_US keymap=us
initrd /initrd.img

在"hiddenmenu" 和 "title CentOS..." 增加一项:
method中的url为安装centos的源

重启后使用vnc软件连接服务器 IP:1 ,并输入刚刚设置的vnc密码即可进行centos的重装。这个过程中机器需要下载一些镜像,大约要等待15分钟,VNC才可以访问。

使用OneApm CI SDK实现业务响应速度监控

目前负责的业务处于急速扩张期,每周会增加几台服务器,业务日访问量在5000万左右。

目前的监控需求在可用性和响应速度。运营的需求要求每次接口响应控制在0.1-0.5s内。

在现在的基础监控中,可以分析出http业务的可用性,但没法监控具体的响应时间。
最开始使用的方法为在后端添加serverId和处理时间并放到http header中,通过curl去获得后端信息和处理时间,采样后生成报表。
听起来就比较复杂。
再后来,改成通过nginx记录upstream的response time,采样生成可视化。
由于nginx日志分布于不同的机器中,收集数据相对来讲还是比较麻烦的。

后来将一部分监控迁到OneAPM上,折腾一段时间以后,无意中发现了CI有一个SDK,学习了一下,发现可以实现一些业务层的监控。
经过一段时间的试验,发现CI SDK使用起来非常方便,能方便的接入丰富的业务数据。

其实现的原理为隔一段时间采样一个数据,上报给CI,CI会根据输入的数值,生成线性报表。
下面是一些使用的经验,分享给大家。

以下是抄了OneApm的官方介绍,供参考。

==============================

OneApm CI是什么
http://docs-ci.oneapm.com/

Cloud Insight SDK For Python
http://docs-ci.oneapm.com/api/python.html

Cloud Insight 集成了数十种互联网流行基础组件的监控,开箱即用,您只需要进行最小化的配置就可以实现复杂的基础组件监控, 免除了传统基础组件监控中的复杂流程。Cloud Insight 采集这些基础组件的权威指标,所有指标都是标准化的格式,您再也不需要 自己定义各种指标,以及思考如何进行各种指标的组合展示,一切就只有两步,安装探针,查看仪表盘,如果您使用的是阿里云、UCloud 等云厂商,甚至不需要安装探针,Cloud Insight 会直接通过这些云厂商提供的 API 收集服务器以及基础组件的性能和健康情况的 指标,并友好的展示在定义好的仪表盘中。

OneApm CI还提供了SDK,可以实现自定义的业务数据监控,比如业务的订单趋势,响应速度曲线等。配合CI的丰富报表功能,非常轻松的实现自定义业务监控。

==============================

按照文档,安装CI, 及CI SDK,这里不再赘述。
step 1, OneAPM CI Agent 安装
step 2, OneApm CI SDK For Python安装
step 3, 编写一段简单的python 代码

#!/usr/bin/env python
# -*- coding:utf8 -*-

import commands
import socket
from oneapm_ci_sdk import statsd

hostname = socket.gethostname()
error, result = commands.getstatusoutput(""" tail /opt/dataroot/nginx/access.log |grep "download" | awk -F '" "' '{print $7}' """)
if ( error == 0 ):
        code = result.split("\n")
        statsd.gauge('php_response_time.download.%s' % hostname, float( max(code) ) )
        print 'php_response_time.%s : %04f' % ( hostname, float(max(code)) )

上述代码实现的逻辑为调用系统命令,获取nginx中,php的responsetime,从几个响应时间中取最大值。

step 4, 部署收集数据

#获取Nginx Upstream response time
* * * * * for i in $(seq 3); do sleep 15; python /opt/ci_check_php_response_time.py; done

添加上述计划任务,每秒统计三次响应最慢的请求。由于默认的系统计划任务无法实现按秒制定任务,通过sleep间接实现。

step 5, 查看报表

进入 https://cloud.oneapm.com/dashboard#/,在最右下角找到自定义仪表盘,
效果如下:

QQ20160318-0

根据官方文档的说明,未来还会开放不需要SDK的API,非常适合做一些私有业务的监控和告警,非常期待。

Cloud Insight API

API 提供了更加强大的功能,您可以不受任何约束的发送符合Cloud Insight数据格式标准的任意数据,无论本机是否安装了Cloud Insight Agent。目前API正在开发之中。

在几个月的使用中,OneApm CI和AI,给我们提供了非常多的帮助,慢慢的使用才发现OneApm的强大,感谢 OneApm 志利在使用过程中给我们的帮助,不管是晚上还是周末,响应速度非常快,非常感动。
下次分享一下在使用AI的过程中,通过AI定位ThinkPHP中Redis连接异常的一个故障处理。

Update:

CI在这个月发布了新版,也提供了新的PHPSDK,可以愉快的从之前的python sdk切过来了。同时,也增加了仪表盘分享功能。

aws ami 执行yum出现"Protected multilib versions: openssl-1.0.1e-42.el6_7.2.x86_64 != openssl-1.0.1e-42.el6.i686"

[txtplain]
--> Finished Dependency Resolution
Error: Multilib version problems found. This often means that the root
cause is something else and multilib version checking is just
pointing out that there is a problem. Eg.:

1. You have an upgrade for openssl which is missing some
dependency that another package requires. Yum is trying to
solve this by installing an older version of openssl of the
different architecture. If you exclude the bad architecture
yum will tell you what the root cause is (which package
requires what). You can try redoing the upgrade with
--exclude openssl.otherarch ... this should give you an error
message showing the root cause of the problem.

2. You have multiple architectures of openssl installed, but
yum can only see an upgrade for one of those arcitectures.
If you don't want/need both architectures anymore then you
can remove the one with the missing update and everything
will work.

3. You have duplicate versions of openssl installed already.
You can use "yum check" to get yum show these errors.

...you can also use --setopt=protected_multilib=false to remove
this checking, however this is almost never the correct thing to
do as something else is very likely to go wrong (often causing
much more problems).

Protected multilib versions: openssl-1.0.1e-42.el6_7.2.x86_64 != openssl-1.0.1e-42.el6.i686
[/txtplain]

原因未知,卸载掉openssl-1.0.1e-42.el6.i686即可

php版本的文件夹合并

#!/bin/env php
<?php
error_reporting(7);

$dir1 = $argv[1];
$dir2 = $argv[2];

if(empty($dir1) || empty($dir2))
{
    echo "php {$argv[0]} dir_merged dir_merge_save\n";
    exit(0);
}

if(! is_dir($dir1))
{
    echo "{$dir1} is not a dir\n";
    exit(0);
}
if(! is_dir($dir2))
{
    echo "{$dir2} is not a dir\n";
    exit(0);
}

merge_dir($dir1, $dir2);

function merge_dir($from, $to)
{
    $from  = rtrim($from, "/")."/";
    $to    = rtrim($to, "/")."/";
    echo "search file from {$from}";
    $files = glob($from."*");
    echo "\t\tdone\n";

    foreach($files as $f)
    {
        $relative_path = substr_replace($f, "", 0, strlen($from));
        $ff = $to . $relative_path;

        //目录不存在则直接复制目录
        if(is_dir($f))
        {
            if(!is_dir($ff))
            {
                $cmd = "cp -r '{$f}' '{$ff}'";
                `$cmd`;
                logs($relative_path);
            } else {
                merge_dir($f, $ff);
            }
        }else{
            if(!is_file($ff))
            {
                copy($f, $ff);
                logs($relative_path);
                continue;
            }

            //对特殊文件进行检查
            $ext = substr($relative_path, strrpos($relative_path, ".")+1);
            if($ext == "apk" && filesize($f) != filesize($ff))
            {
                $compare = apk_version_compare($f, $ff);
                if($compare)
                {
                    copy($f, $ff);
                    logs($relative_path);
                }
            }
        }
    }
}

function apk_version_compare($apk1, $apk2)
{
    return aapt($apk1) > aapt($apk2);
}

function aapt($apk)
{
    $apk = realpath($apk);
    $aapt = "aapt d badging {$apk} | grep versionCode | awk '{print $3}'";
    $aapt = `$aapt`;

    return substr($aapt, 13, -2);
}

function logs($file)
{
    printf("%s\n", $file);
}

基于CloudFlare + Conoha搭建的企业级廉价CDN

中国的流量很贵,流量越大越贵。

目前我负责的业务一半国内,一半海外。目前日均请求过千万,流量过10T,总成本不超过500元/天。跟传统的CDN服务相比,便宜到可以忽略。

CDN介绍
在项目早期,为了业务简单,直接使用传统CDN提供商网宿,在CDN宽带超过 5G 的时候,CDN的成本开始显现出来。
一般国内的CDN(网宿、帝联、蓝汛,还有一些如七牛、又拍这样的二手贩子)均有宽带和流量计费,新起的云平台(阿里、腾讯、uCloud)基本上使用流量计费。

国内的CDN价格,网宿的95峰值计费,一般价格在45-55元/M,根据宽带高值、公司背景、销售人员关系等等因素,合同的价格可以签到30-40元左右,其它二线的CDN可以签到25-30元左右。

其它的云服务平台,价格相对固定,业务购买一般是自助服务,价格基本上没得可谈,普遍价格在0.9元-1.2元/G。

国内服务商运营的国外CDN价格比国内高出几个数量级,网宿的报价为150元/M,其海外节点为少数自建加akamai代理。其它几家传统的CDN服务商完全代理甚至没有海外业务。

海外的CDN服务商,计费一般是按流量计费,常见的如MaxCDN, KeyCDN,价格一般为0.04-0.1美元/G。

业务介绍
我们的业务早期使用网宿,业务从0M跑到3G,业务一直比较稳定。后来业务推到海外,直到CDN的成本越来越高,CDN成本差不多占了利润的一半。

网宿现在有市场优势,价格一直砍不下来。经过跟几家CDN服务咨询、测试,从最初的七牛,MaxCDN,KeyCDN,到最后的CloudFlare+Conoha,终于实现成本与速度的平衡。

在第一次使用CloudFlare和Conoha的时候,都被其极低的价格吓得不敢相信,企业级项目中总觉得低价的服务肯定会出问题(事实上确实是这样,毕竟价格高的也会出问题)。


cloudflare.com

和国内的安全宝、百度云加速的业务类似,CloudFlare提供的安全服务是帮助网站阻止来自网络的黑客攻击、垃圾邮件等,并提升网页的浏览速度,这和一般的安全软件往往会影响网页的运行速度大相径庭。目前CloudFlare在全球拥有23个数据中心,如果用户使用了其服务,那么网络流量将通过CloudFlare的全球网络智能路由。CloudFlare会自动优化用户的网页交付,以期达到最快的页面加载时间以及最佳性能。 CloudFlare提供包括CDN、优化工具、安全、分析以及应用等服务。

2015年9月,CloudFlare正式宣布与百度合作改善外国网站在中国的可访问性。双方早在去年7月就签署了合作协议,CloudFlare将其技术转让给百度(CEO称此举是为了增加信任),而采用CloudFlare技术的百度云加速服务于去年12月开始运作。

CloudFlare称,百度在中国大陆的17个中心地区节点与 CloudFlare 全球的45个节点结合起来,提升中国国内外的访问体验,当客户激活中国网络服务后,他们的中国访问者将会访问百度节点,而CloudFlare节点则继续服务海外访问者,可将中国流量的响应时间缩短超过200毫秒。
但外国客户如果要激活中国网络服务将需要ICP备案。网站备案是中国工信部要求所有在中国大陆使用主机或CDN服务的许可证书。

via:http://www.cnbeta.com/articles/429815.htm

conoha.jp

ConoHa日本gmo.jp旗下的一个VPS主机商,成立于2014年。ConoHa提供日本、新加坡及美国机房云VPS服务。

ConoHa的业务跟国内的云服务平台类似。说是云服务器,个人感觉跟vps差不多,跟常见的Linode和digitalocean基本上相同。
ConoHa的官网支持中文,支持信用卡和支付宝,支持扩容支持按时间收费,可以按小时按月计费。

ConoHa的价格非常廉价,常见的配置如1GB、2Core、SSD50GB,每个月50元人民币。

最重要的是,ConoHa不限流量,100M宽带,可扩容,可加IP。

ConoHa有激励政策,通过我的邀请链接注册,你可以获取1000日元,相当于免费赠送一台主机,
https://www.conoha.jp/referral/?token=V3xoVa5812CYk15rhJkKiiNc5E340f3uNaNjQCiaBmnWZdA30Zk-0VJ

业务实现
在CloudFlare中,添加一个免费(我们使用付费方案是200美元/月)的域名,主要使用其提供的IP隐藏、文件缓存来实现防DDOS和CDN需求。

在我们的单个项目中,CloudFlare每天可以缓存数百万次的请求,差不多8-12TB左右的流量。按最低4美分的价格,每天的CDN成本应该在3000元左右,一个月10万元,一年超过100百万元。
采用了CloudFlare以后,只需要1200元一个月,一年只需要1万元,CloudFlare实实再再的帮老板省了一大笔钱。
老板是不是该奖励我一台特斯拉了哎?

QQ20160110-1

经过我们跟数家CDN服务商的对比和测速,给CloudFlare的节点和速度5个星,稳定性和速度让我们非常意外,点赞。
但作为一个非专业的CDN解决方案,CloudFlare目前还没有完善的数据报表。不能分析请求的URL列表,不能按常见维度分析用户和行为,对运营人员来讲是个缺憾。
同时,CloudFlare默认只对一些基本的文本、图片文件进行缓存,有特殊的文件,比如apk、exe等文件,则颇费周折。

via:https://support.cloudflare.com/hc/en-us/articles/200172516

CloudFlare中非默认缓存的文件,比如apk文件,如果需要缓存,则不能携带任何参数,否则会回源,无法缓存。
CloudFlare另外一个巨坑便是其缓存重建只能通过pull方式。回源pull方式存在严重的风险。我们这边出现过一个50M的文件清理缓存以后,源站瞬间出现近千个请求。这包括CloudFlare的全球节点的缓存请求,也有用户的的真实请求。
CloudFlare无法设置限速,所有请求全落到源站,源站的流量瞬间飙上500M。放在云上的整个路由器下的所有业务全部卡死。

源站的流量可以通过扩容的方式提升上限,为了解决巨大的回源请求,我们曾差不多把宽带提高了到1G。
云平台1.2元/G的流量价格也是贵到滴血,逼得我们必须要为回源的请求再构建一个廉价的中转服务器。

在测试过Linode和digitalocean以后,我们选中了ConoHa。主要看中其极低的价格、无限流量、多节点等优势。
我们把文件rsync到ConoHa的多台主机以后,再将CloudFlare的回源请求重定向到不同的ConoHa服务器。
虽然业务架构越来越复杂,但比起源站业务被中断,以及宽带扩容的成本,ConoHa上一个月不到一千块钱的成本实再便宜得让人心疼。

其它
在目前的架构中,所采用的方案均为比较新的服务商,稳定性存在非常大的风险,如果有一天CloudFlare或者ConoHa倒闭,则会对现在的业务造成致命的影响。

为了降低风险,我们也在采用了一些优化手段,也在积极寻找备用方案。
比如,为了避免单个域名流量太大,被CloudFlare封掉,或者要求我们使用更高的付费方案,我们把CDN拆到多个域名下,减少单个域名的请求和流量。我们也在寻找与CloudFlare相同的的平台,比如Incapsula。甚至有人建议直接购买廉价vps自建CDN。考虑到现在云计算基础服务相对完善,自建一个全球性的CDN平台也不是太大难事。

为了避免ConoHa出故障,我们也在其它几个廉价的vps服务商购买了几个备用服务器,定期将文件同步过去进行灾备。

同时,我们发现CloudFlare中添加一个在国内备案的域名,其节点尚不能确认是否已经使用了百度云加速的节点,有没有知晓内幕的朋友。

最后
经过项目的实践和数月的运营,这个廉价的CDN实现,节点数可以达到成熟商用CDN节点数的30%-80%(海外优势尤其明显)。跟同行业的一些朋友交流时发现,也有其它同行业的业务使用CloudFlare+Digitalocean实现,稳定支撑月流水数百万美元的业务,而其成本非常低廉。

云服务越来越成熟,成本越来越低廉,对于我们这样的创业公司来讲,是一大福音。而对于那些传统的基础服务商来讲,又是什么呢?

简单获取并验证client ip

function get_ip_address()
{
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key)
    {
        if (array_key_exists($key, $_SERVER) === true)
        {
            foreach (explode(',', $_SERVER[$key]) as $ip)
            {
                $ip = trim($ip);

                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
                {
                    return $ip;
                }
            }
        }
    }
}