我的家乡是国家级的贫困县,也是朱德朱大元帅的家乡四川仪陇县。我是村里第一个考上大学的娃。来北京之前,我只知道北京是中国的首都,是中国经济,文化政治的中心,这个认识是从历史书上得来的。还有一点就是在北京,别比谁的官大,这是英语老师说的,对于北京其它的就一无所知了。
tornado 实时服务架构设计
背景介绍
这是在公司训练的一个小项目。
每分钟需要从tushare的接口中获取到实时的股价数据,存储到文件中和mongodb中,然后对数据进行处理,包括数据检查,分钟线的补齐等。经过以上的处理后,程序需要对外提供API,共web,app等终端使用。
股价数据每分钟都在改变,api的调用次数和频率非常高,因此服务架构在设计的时候需要满足以下几点:
1、容错性能好:
至少要保证在开盘阶段不出问题,由于tushare的接口可能返回不了数据或着请求返回超时等,需要及时的对股票的分钟数据进行补全,如第一分钟获取到一条数据,然后第5分钟才来第二条数据,那么中间的三分钟都需要进行补齐。
假设服务一旦挂掉了,也要求服务重启之后能够及时的恢复数据,继续对外提供数据。
2、实时响应请求:
应用每分钟都要向api请求数据,如果请求被阻塞了,就会影响后续的请求进来。因此要求api能够实时响应,不阻塞IO,并发高,假设并发数达到3w/s。
现阶段的设计先满足以上两点即可,后续在不断的改进。根据上面的分析,考虑到最近在学习python,我选择了tornado。
tornado介绍
tornado和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其非阻塞的方式和对 epoll 的运用,tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web 服务来说,tornado 是一个理想的 Web 框架。并且tornado内置了一个服务器,开发效率高。虽然tornado实现了非阻塞的网络请求,但是其仍然是单线程,在做耗时的CURD任务,仍然会阻塞进程,导致外部访问变慢。
架构的设计
从整体上来看,要支撑如此高的并发量,一个tornado肯定不行的,因此需要多个torando,再加上用nginx做负载均衡,这样就可以支撑高并发。
具体每个tornado的设计就有两种方案。
方案一
在tornado运行一个定时任务,然后每分钟取数据,先更新内存,然后写入文件中,最后写入mongo。
按照这种设计方案,一个tornado干了所有的事,数据采集,数据存储,数据更新,对外提供api 。先来看下Tushare实时数据采集耗时统计。
从图中可以看到:最高28s,平均值为9s。
tornado在执行该任务时会阻塞线程,如果后台正在进行请求任务时,此时来了api请求,那么这个请求就会被挂起,直到后台的数据采集处理完毕后才会对api请求处理。
方案二
我们让采集进程定时取采集数据,然后处理好了,推送给tornado,这样tornado只管对外提供数据,而不管取获取数据,让tornado专注于干自己擅长的事情,并且可以起一个后台进程,每10分钟可以将采集到的数据导入到mongo中。这种设计让每个进程都只专注于干一件事。
异常处理
整个设计中,程序随时可能会出问题,要保证运行稳定,异常处理部分是非常重要的一块。主要有以下几点:
1、网络请求:每分钟从tushare获取股价数据,可能会遇到请求超时,数据错误等异常。采取的解决措施主要有超时重试,数据补齐措施
2、 文件、数据库写入异常:遇到文件,数据库写入异常时,要保证数据存储成功,应该保存重试几次和错误日志记录等,方便后续对错误的处理
3、 服务重启:后台检测到服务挂掉之后,自动重启服务,先从数据库中加载数据,处理后保存在内存中,如果从数据库加载失败,在从文件中读取数据,保证服务的可用性
总结
通过这个小项目的练习,我对框架的选择,方案的设计,数据的获取,存储,处理和对外提供api都有了更加深入的了解。
框架的选择要紧贴业务的需要,能够解决实际的问题。首先要仔细的分析业务的需求是什么,存在什么样的问题,要达到什么样的目标,通过对问题的分析,我们才能清楚需要什么。然后调研分析有哪些可以使用的框架,每种框架的特点是什么,缺点是什么,能否解决现阶段的问题,学习成本高低。通过这些分析,才能选择适合的框架解决问题。
之前在写程序的时候,大多数都不会去处理异常,认为程序会一直按照这个逻辑正确的运行下去,现在认识到,程序设计的每个阶段都需要充分的考虑到异常的处理,才能保证程序能够稳定的运行。
hadoop集群安装
2016总结
2016年,我究竟是怎么过来的?一直都不想去总结过去,但是还是需要去回顾一下。
2016年干的最多的就是实习了,就先从这总结起吧
实习工作
从2016年4月5号入职,到现在累计实习天数130天。期间主要完成了2个项目和一个正在进行的项目,对应的就分为了3个阶段吧:
- 包括内部工具以及数据展现的工作
说白了就是后台给数据,我负责前端的展现。主要熟悉了PHP,ECharts的使用和巩固了html/css,js的基础知识吧。 - 网页版的app开发
通过一个完整的项目,熟悉了项目的开发,测试,部署,维护等流程,并学习到了很多新的知识和开发技巧,使自己的开发水平和解决问题的能力提高了一个档次。 - 综合项目
具体的项目名保密,期间主要用highchart和vue搭建一个图标系统。独立完整的搭建项目的前后端框架,服务器环境部署,测试,代码自动更新维护等,期间不断的去尝试,去踩各种坑,去记录积累,提高了自己整体综合能力。思考越来越多,文档越写越多,代码越写越少。
在公司实现9个月,自己从问题的处理,编程的能力,职业的素质等都有很大提高。公司也有不错发展的前景,从我最开始的10来个人发展到现在60来人吧,业务也越来越多,发展势头很猛,扩张的也很快。公司的成长也带动着我的成长。
下面接着聊聊2016年做的个人项目
个人项目
3d煎饼打印,这个项目绝对是个坑、、、费了2个月,做的也不好,倒是学了MFC编程,opencv使用这些东西。我觉得没有什么价值,还不如我仔细的看看书,不提了。
亚马逊棋,这还算是我做的比较好的一个项目,自己研究搭建对弈引擎,编写界面,搜索函数,测试等。最终比赛得了个二等奖。还准备写一个亚马逊棋专题来总结一下,现在写了2篇了,其它的又拖着了,准备过年的时候写出了。
外包网站,这个是给别人做的一个网站,这个项目有些拖拉了,第一次接外包项目,踩了一些坑,记录下来吸取经验— 一个小外包项目的总结
除了这三个项目,还参与秦皇岛大型港建项目的需求调研和竞标书撰写,在秦皇岛的宾馆中待了接近4天,写到白头发都出来了。还很感谢这次经历,提高了自己的需求调研、分析整合、软件设计、文档编写等技能。还帮女朋友的公司做了个小小的预约系统。
还有些小的就不说了,一直拖着
学习
这一定要分一下,个人学习和学业课程
个人学习
2015年年末,我放弃了继续学习android,转而投入到了PHP,现在想想这是对的。今年学习主要分为两个阶段,web学习和机器学习。
web学习占据大部分时间,PHP从ThinkPHP转到高度上的Laravel框架,前端从基本的html/css,到js,到各种js插件的运用,再到nodejs,最后终于转到Vue全家桶上,剧终了。自认为远远不够,但是前端的技术发展实在是太猛,不知道明年又会出现什么,但是我的领导说的对,你这些东西都玩了一遍,大致怎么用都了解就行了,基础的它不会变。
学习进入下半场,来到了机器学习,为什么要学它,因为内心恐惧。我必须知道这个东西是什么原理才能面对不确定的未来。于是报了斯坦福的机器学习入门课程,经过大概3个月,12周的学习,终于拿到了证书。在我拿到证书的时候,我的领导告诉我,2017年我的主要任务就是机器学习相关。果然机会是留个有准备的人的,开始了自己技术的转型。
今年还看了10几本书,有技术的,心理的,思维的。书还是看的比较少
学业课程
我现在不知道怎么上课,这一年的课基本上都没怎么上。很多课都水过,作业也水过,分数还行。我觉得书都被我变成了工具书,上课时翻一翻目录啥的,做作业的时候就直接在书中现学现用,对待学业课程的态度不好。
感情生活
很高兴去年的很少吵架,总结几个原因吧:
- 就是太忙,没时间吵
- 脸要厚,认错要快
- 个人态度转变,看重感情
- 多花点钱消灾
总结:感情逐渐稳定,偶尔也会吵吵,正常的。作为恋爱弱势一方的男生,要借此机会多练自己的耐性。
总结
- 今年累计赚钱6万,实现自给自足,不再问父母要钱
- 学习能力大幅提升,脱离传统学习方式,实现驱动式学习
- 工作职业素养提高,具备离开校园进入社会的条件
- 累计完成公司以及个人项目10余个
- 恋爱感情稳中有升
- 个人综合能力大幅提升
- 具有一些坏习惯,比如拖拉,没有改正
感觉自己越来越像个程序员。
一个小外包项目的总结
这是一个外包项目,帮别人做一个网站,包括前端和后端。
主要工作如下:
- 系统为客户提供活动申请、抢单、反馈、评论、组织创建,成员管理,微信分享等功能
- 支持后台对活动、组织、用户等资源的统一管理,包括审核,修改,发布,图片上传等功能
- 系统的测试,bug的修复、上线以及维护。已稳定运行2个月
项目从9月份启动,开始是两个人,有一个朋友,最后做了一点点就没有让他做了。基本上所有的功能都是我一个人完成,产品经理,UI设计,代码都一个人包了。
主要是利用晚上或者周末的时间来完成,11月初基本上所有的需求都完成了,之后就一直修修补补,新的需求不断,到了12月中旬就交了。
期间的心情变化
- 有钱赚,干劲十足
- 终于要开发完成了,欣喜
- 不断的改和加新功能的烦心
- 一直改一直改的烦
- 终于交接了,开心
- 尾款一直拖一直拖,一直催,一直催,心急,代码啥的都给了。
- 扣押款项的愤怒,却又忍着同意。
- 自己还是太嫩了吧
项目的结构:
- 后台采用ThinkPHP3.2搭建
- 前端采用了bootstrap,Vue,jQuery,frozenui
- 采用mysql数据库
- 服务器采用阿里云,centos7.2+Nginx+PHP+Mysql
踩到的坑:
- 代码结构没有设计好
- 数据库设计不具有扩展性,一改再改
- 需求不太明确,对方也不明确,用了才来改
- 中间进行了一次UI界面的全部重写
学到的经验:
- 外包必有合同,不能是之前认识就不要
- 文档要齐全,包括需求文档,功能文档,Api文档,数据库设计文档。一样也不要少,在开发一个功能的时候,先要文档化,实现什么样的功能,api如何设计,需要哪些参数等。
- 如何防止对方的需求不断的更改,做了一个功能,又要与之配套的功能啥的。
- 先要搭起整个架子,不要急于敲代码、、
- 代码可以让其审查,但是在没有付尾款的时候不要给
以后外包开发需要以下文档
- 技术合作文档
与对方签订的开发合同 - 功能文档
描述已经实现的功能 - 数据库设计文档
数据库版本,表设计等 - 项目需求文档
项目需要实现的功能列表和说明 - 总体设计文档
描述项目整体采用的架构 - Api文档
后台提供的api文档列表 - bug提交模板
测试提交bug的模板
总结一下:
通过这次外包项目,初步了解了外包的一个整体流程,踩过一些坑,上过一些当,也学到了很多经验,还赚了一点点钱,第一次重在尝试。
nmp的权限问题分析和selinux
nginx,php-fpm,mysql安装好之后是第一步。
将项目部署上去之后,然后访问,发现仍然无法访问。
按照以下步骤进行错误的排查:
- 分析nginx的运行日志access.log和error.log
- 分析php-fpm的运行日志www-error.log
- 分析代码文件的权限
- 分析selinux
通过分析,发现静态文件是可以访问了,至少api无法访问。由于前后端的代码分类,nginx在访问静态文件是不会讲请求转发给php进行处理,而是直接返回静态文件。因此可能是访问将请求转发给php-fpm处理时出现错误。
查看nginx的access.log 发现如下错误:
在网上搜到的答案基本上就是将nginx.conf中的php的配置改为
|
|
这种解决方式没有错,我之前也是这么解决的。我这里配置是对的,因此确认不是nginx.conf的配置问题。
继续分析php-fpm的运行日志www-error.log
在这里找到了原因,文件缺乏写入的权限,因此报错,终止运行。
为了方便,我直接将无法写入的文件夹的权限设置为777。再次访问,发现仍然无法访问,依然是报上面的错误。
那么继续查找问题,开始分析selinux.
查看一下selinux的状态
|
|
说明selinux是开启并且强制的。为了测试是否是selinux的问题。我暂时关闭selinux
|
|
此时访问网站,发现可以访问网站的api。实在无法解决权限的问题,关闭selinux是个好办法,但是毕竟是会造成一些隐藏的安全问题,后面将会总结一下selinux。
下面分析一下nginx,php-fpm的权限
查看nginx在什么用户下运行:
|
|
再查看一下项目文件的用户和用户组:
为501:root
可以看到,三者都是运行在不同的用户和用户组下面,很容易造成权限问题,一次需要统一nginx,php-fpm以及项目文件的用户和用户组。
统一成www
|
|
selinux
在前面我们配置web环境以及用户组之间的关系以及将文件权限设置成777之后,仍然会报错,没有访问权限,这时就需要从selinux上找问题。selinux是linux中的一个安全强化模块,它在linux的传统文件权限和用户关系上增加了一层访问控制,实现了更加严格的访问权限控制。
下面分析一下
传统文件权限和账户关系:自主访问 ,DAC
- 自主访问:依据进程的所有者与文件资源的rwx权限来决定有无访问权限
- Root具有最高的访问权限
- 用户可以取得进程来控制文件权限
强制访问控制:MAC
- 可针对特定的进程与特定的文件资源进行权限控制
- 控制的主体变成了进程而不是用户
- 每个文件资源也有针对该主题进程设置可取用的权限。
根据两种访问控制来判断,进程在向日志文件laravel.log写入时,没有通过selinux的审核。下面将分析selinux的日志,找出解决办法
查看selinux报错信息:
cat /var/log/messages | grep setroubleshoot
根据提示
|
|
这里selinux给出了更加详细的信息,并且也给出了建议
|
|
设置后,生效有点慢,需要过一会儿才能生效。
js对象的拷贝问题
问题如下
点击+之后,新建一行,并赋予初始,从原始的数组中直接复制第一个,然后在push到数组中,结果改变输入框后,其它的值也改变,实际情况,只是想要拷贝该对象的一个值。
代码如下:
|
|
这样直接将对象赋值给newObj,新插入的项与第一项引用的是同一个地址,因此会造成修改的同时发生。
这种直接将对象复制给一个新的对象,是js中的浅拷贝。
对象的深拷贝是只复制对象的属性和值,不是引用对象。
采取的一个方法:把对象的属性遍历一遍,赋给一个新的对象。
|
|
可以lodash的api,可以直接
|
|
很方便。
nginx ,php,MySQL 版本选择和安装
搭建web服务器,我一直选择的LNMP环境:
- centos7.2
- Nginx
- Mysql
- PHP
Centos就不用叙述了,以下主要从Nginx,Mysql ,PHP的的版本选择,不同版之间的差异,安装,以及安装所遇到的问题进行汇总。
Nginx
版本
nginx 主要分为mainline和stable两种version,后者是稳定版本,一般生产环境中采用稳定版本。现在最新的稳定版本是1.10.2。
安装
安装方式有两种,一种是直接yum安装,一种是源码安装。推荐后者,安装过程和配置可控
1、yum安装
要想快,直接yum,首先安装epel,epel是centos等衍生发行版,用来弥补centos内容更新有时比较滞后或是一些扩展的源没有。
|
|
PHP安装
版本选择
Composer 作者 Jordi Boggiano 对 packagist.org 今年 5 月份的 composer install 和 require 的数据做了统计,发现 PHP 开发者,至少使用 Composer 的 PHP 开发者对 PHP 7 的接受度蛮高的。
Composer 在服务器通讯过程中把 PHP 版本号通过 User-Agent 一并发送,通过这个数据,得出以下:
可以看出php5.5,5.6,7.0逐渐占据很大部分的市场份额,其中最新出来的php7.0发展迅速,其他版本逐渐被淘汰。
由于还没有跟上php发展的速度,我这里选择php5.6版本。
php安装
1、检查当前安装的PHP包
|
|
2、安装php的一个安装源
centos的软件安装源更新的有点慢,如果直接用yum安装,会导致安装的php版本过低,可能是5.4版,因此需要安装php的一个安装源。
|
|
3、安装php5.6版
|
|
安装指南
php可以选择源码安装和编译,但是比较费时和可能出现未知的错误,因此先采用yum安装,后续有时间再试下源码编译安装。
如果要升级php版本,最后先卸载之前的然后重新装,省去很多麻烦
MySql
版本选择
自从mysql归于oracle之后,就要闭源的倾向。它的开发者在mysql的基础上又创建了mariadb这个和mysql绝大多数兼容的数据库,现在centos上默认安装的是mariadb,不是mysql。我这里还是选择安装mysql,之前学习的就是这个。
mysql主要的版本有:
- MySQL Community Server 社区版本,开源免费,但不提供官方技术支持。
- MySQL Enterprise Edition 企业版本,需付费,可以试用30天。
- MySQL Cluster 集群版,开源免费。可将几个MySQL Server封装成一个Server。
- MySQL Cluster CGE 高级集群版,需付费。
- MySQL Workbench(GUI TOOL)一款专为MySQL设计的ER/数据库建模工具。它是著名的数据库设计工具DBDesigner4的继任者。MySQL Workbench又分为两个版本,分别是社区版(MySQL Workbench OSS)、商用版(MySQL Workbench SE)
这里选择安装mysql的社区版本。
mysql安装
1、安装mysql的repo源
|
|
2、安全设置
这是必需的,不然谁都可以访问你的mysql
|
|
然后一路Y下去
3、错误解决
安装mysql之后一般有点小麻烦。。。这些基本上都是权限不对造成的。
|
|
这是mysql的用户和用户组不对
解决方法
|
|
防火墙配置
安装完之后,需要重新测试一下是否搞定了。之前还需求进行防火墙的配置
|
|
此时访问就能看的nginx的欢迎页面了。
后续目标:
每次都这么配置,很累,下一步就写个shell脚本自动解决。