分类目录归档:未分类

用分布式系统思路解决资源受限问题

通过最近的一个小示例,介绍一下分布式系统的特点,和简单实现方式,目的在于使用高级的思路解决实际的问题。

背景

有个任务,将csv格式的数据读入,加工处理,最后输出一个或者多个excel文件。

问题

为了方便使用,将系统迁移至VPS,由于VPS新能问题(配置1核,1G,别问我为啥不升级配置),处理时大文件时,占用内存过多,程序会崩溃

目标

在资源受限的情况下,让程序正常使用

分析

  1. 发现程序崩溃是由于生成大的Excel文件引起的
  2. 单独生成一个大文件不会出现崩溃,但连续生成3个以上的文件会崩溃
  3. 发现系统崩溃时,程序内存占比达到37%,小于37%可以正常运行
  4. 单独执行有大概2~4分钟,内存占比才会下降
  5. 处理此类任务每月不超过2次
  6. 用户对任务的结果的期待不能超过24小时

方案

根据分析,可以采用时间换新能的方式,另外还可以主动释放内存。
具体方案是:将生成多个大Excel文件的过程分解为多个一次只生成一个Excel文件的过程,即子过程,没执行一个子过程,主动调用垃圾回收方法,而要执行一个子过程时,先看内存占比是否小于37%,是执行,否放弃执行,等待下次执行。
于是打算采用异步、分布式处理的方式。

过程

  • 基本功能:
    1. 主任务拆分(生产者)
      主任务要具有可拆分性,就是可以拆分成简单子任务,子任务之间的关联度要尽量小,否则就不能并行执行了,比如任务A,拆分成a,b,c三个子任务,b依赖于a的结果,c依赖于b的结果,那么子任务只能按a、b、c的顺来执行,无法并行,分布式反而会让处理更复杂更慢;还有后续任务需要明确知道前序任务以及前序任务的结果,所以后续任务执行前需要更多的时间和资源创建执行环境。对于只想让拆分任务,分步执行的,子任务间的关联度大小影响不大。
      处理中,使用了循环,生成多个Excel文件,所以很容易拆分成子任务,且子任务之间没有关联。
    2. 子任务队列(产品和篮子)
      队列是分布式方案中很常用的数据结构,方便先进先出,同时方便调度算法的实现。队列的实现方式很多,其实很简单,这里用库表作为存储,每次获取id最小的记录,实现先进先出的效果。 队列中存放什么是关键,需要充分考虑子任务执行中用到的数据,执行方法,尤其是环境变量,很容易遗漏。程序中,处理完所有的子任务,需要将结果打包成zip文件,zip文件名是个环境变量,也需要保存在记录中,见4结果合成。
    3. 队列调度(消费者)
      简单说就是从队列中获取记录的方法,比如一次获取几个,要不要考虑优先级,怎样才能避免一个任务分配给多个执行者等等,就简单的就是每次只取一条。调度算法将拿到的记录分配给执行者。一般对于队列来说,除了队列就从队列中删除了,我采用了库表做存储,并且想作为执行日志来用,所以采用标记的方式,即获取到的记录打上已分配的标签,表示这个记录已经被取走,调度程序就不会再分配它了。
    4. 结果组合
      分布式执行必须要有这一步,1为表示主任务完成了,2 将子任务执行的结果组合起来作为主任务的结果。
      由于分布式异步执行的原因,不能预测主任务的完成时间,也无法预知最后一个子任务是谁,执行者执行完一个子任务后,需要看一下自己是否是最后一个完成的,如果是就调用结果组合方法。
      程序中,合成方法会将所有子任务产生的文件,打成zip包,最后一个子任务负责打包,由于不知道谁是最后一个,所以每个子任务都会zip包的名字。好傻哈哈,如果任务分配后还需要变更某些变量时,就得更新每个子任务记录了,更优雅的做法是设计一个主任务记录,将zip包文件名,以及和主任务相关的数据记录在这里,当子任务需要时从这里拿就行,不过为了方便实现,没有过多优雅。
  • 还需考虑:
    1. 持久化 —— 断点续传
      断点续传的概念来自于迅雷下载,下载一个大文件,到一半,电脑关机了,下次打开,还可以从关机时下载到的地方继续下载,不必重新开始。分布式处理可能时间长,环境复杂,服务器宕机、重启,服务崩溃等情况不可避免,所以需要记录执行的位置,以便系统恢复后不必重新开始。
      在恢复执行中,有个有意思的地方,先看子任务处理状态图:

      当状态是已分配,系统崩溃了,在执行时,调度程序就会认为这个记录正在被执行,但实际上执行者早随系统死了。于是这个主任务就永远执行不完。其实解决方法很简单:当系统启动时,确认没有任务被执行了,需要对状态为已分配的记录设置状态为未分配,即
    2. 进度反馈
      这个其实挺有个必要的,因为不知道任务什么时候能结束,有个进度提示会人性化很多,当然实现很简单,已完成的子任务数/子任务总数就可以,这里要注意什么叫已完成的子任务数,应该是状态不是未分配的任务个数,这个好处在于不用区分已分配,已完成和存在错误者三个状态了,即将他们归于一类,这样方便些,可能有些不精确的地方,但这里只是显示个大概,所以越简单越好。
    3. 执行中出了问题
      不能保证所有的任务都按预想的那样执行,所以问题总会有的,出了问题需要记录下原因,以便查看和修正,至于是否终止掉整个任务,就看具体场景来定,在我的例子中,子任务之间没有关联,所以就没必要终止任务的执行。无论才有什么策略,都需要在主任务上有所返回,这样就能让使用者及时发现问题。当然更好的做法是有个运维接口,出现问题及时报告给运维人员。
      我的实现中,会见错误信息记录在子任务记录上,并且设置记录的状态为出错,相当于同时充当了日志记录。

概括下要点:

  1. 任务可拆分
  2. 队列调度
  3. 断点恢复
  4. 结果组合
  5. 进度反馈
  6. 错误处理

对blog的一点修改

 

这个博客之前一直没有折腾,最近想继续写些东西,发现有些地方不对就想调整一下,由于时间有限尽可能简单的处理一下。

首先,有新版本提示,可能之前尝试过直接升级,应该是没有成功,今天再试的时候依然没有成功,提示需要ftp,但我的服务器一直没有配置ftp所以选择了手动升级。
如果你习惯读安装文件的readme.html,可以忽略下面的具体步骤。

  1. 下载升级文件,其实就是一个新版的WordPress安装压缩包
  2. 备份网站上曾经修改的文件,比如 一些为个性化修改的文件,以及wp_config.php
  3. 加压安装压缩包,并传到服务器上,没有ftp,我用的是 winscp
  4. 将备份的文件恢复回去,我发现其实不用备份wp_config.php文件,因为安装包中没有,所以上传时没有被覆盖
  5. 访问 yourhost/wp-admin/upgrade.php,一路下一步就搞定了

然后,我没有头像,而在设置中需要登录 Gravatar来设置,结果访问不了,于是搜了一下,看到很多解决方案,比如直接改主题的function.php代码,这里,(没有尝试成功),另外一些是利用插件。在后台的插件中,找Simple Local Avatars,见这里,但是安装插件需要ftp访问,当然可以手动安装,既然好多地方都需要用ftp,那就设置一下吧。

注意:以下是阿里云上的CentOS.6.5fpt的设置步骤

参看阿里云服务器下安装配置 vsftpd —— 基于CentOS 6.3

  1. 先更新软件源 # yum update
  2. 安装vsfptd # yum install vsftpd -y
  3. 创建ftp用户 # useradd -d /www/wwwroot -s /sbin/nologin ftpusername
    useradd 命令是添加用户的,参数-d是为了设置用户主目录,这里最好设置为Wordpess所在的目录,方便之后的操作
    -s是设置用户登录的shell的,由于给ftp设置的用户不需要用命令行登录服务器,所以不需要指定shell,由于默认会指定为Bash shell,所以讲该用户的shell指定为nologin,即不需要登录
    最后一个参数 ftpusername是ftp的用户名,需要你自己指定。
  4. 设置密码 # password ftpusername 即为刚才创建的用户设置密码
  5. 配置ftp,用vi编辑 /ect/vsftpd/vsftpd.conf 设置
    local_enable=YES
    write_enable=YES
    chroot_local_user=YES
  6. 启动ftp # service vsftpd start,并设置为自启动服务 #chkconig vsftpd on
  7. 测试吧 ftp:yourhost

设置完ftp,就可以轻松的使用WordPress的在线功能了,很方便。

最后,我感觉没有简单的事情,只有喜欢折腾的心。

远在天边

今天下午在李笑来的微信公众号《学习学习再学习》上看了最新的文章,写的是特斯拉的自动驾驶给他带来的改变,其中附了行程照片,起点竟然和我住的地方就隔条街。让我很是惊奇。
自从看了李笑来的《把时间当做朋友》,我的改变就开始了,将之前没有认清的道理认清了,建立了自己的价值观和金钱观,对我的人生有了很大的改善,之后又订阅了他的《通向财务自由》,真是受益匪浅,从对价值的判断,到对自身问题的思考,一个完整的自我操作系统升级方案,给了我很大的启发,逐渐的让我从之前迷茫无知的状态中走了出来。对于李笑来,除了敬仰还是敬仰,他总是用实际的例子,朴实的语言将一个复杂的道理(其实道理本身不复杂,只是让无知的我们给复杂化了)将的简单明了,而且震慑人心。
今天才知道,这样一位我崇拜的偶像尽然离自己这么近,不敢想象,我是通过书和互联网认识和了解他的,在意识里总是觉得离他很远,就好像天地之隔一样,当知道了实际情况之后,感觉好实际,好近,受到了更大的鼓舞,就像追星的人见到了自己的偶像一样。
同时也感慨,即使物理距离很近,也未必真的很近,一念一世界,就是和自己对面的人认识不同也会在两个平行世界里,其实物理的距离早就不是距离,人与人之间的距离,早就是心与心的距离,而互联网更拉近了心与心的距离,即使住在隔壁,也难以认识,又哪怕在地球的两端,也可以无阻碍的畅谈与合作。
而我还在因为物理距离的远近感慨,真是太落后了,虽然我从事软件相关工作,但我却生活在套子里,只是大概弄清楚自己周边看的见摸得着的东西,对于其他的哪怕是想想也很少(是因为会给自己看不到的东西妄下结论,阻止了探索)(可恶的答案,哪怕是错的也会让大脑失去探索的欲望)。开始写作,也是想让自己更快的成长,很好的利用元认知,对自己经理的事情反思和总结,这样的体验和方法,是通过网络来到我的思想中的,不能不感叹互联网的伟大,他将之前人与人快速的交流需要面对面,改成了可以在任何地方和任何人交流思想,真是太不可思议,其中的切入点就是,信息可以脱了发收端存在和传播,如果在互联网开始之初有这个认识就能看到甚至得到巨大的机会。写文字,就是一种将自己和远在天边的人交流的很好机会,就这样吧
 qrcode_for_gh_27ea27c8c859_430 (1)