创业团队的项目,唯一不变的是变化。不管你相信还是不相信,有时候,你的项目要么上不了线,要么上线后只会有一个版本,后续你连维护或者重构它的机会都没有,因为你需要做下一个更重要的项目,所谓更重要的项目就是公司可能的下一个方向。按照PDCA循环(Plan,Do,Check和Action四个词首字母的组合)理论,你在大企业可能会有这个循环,但是在小企业,你多数情况下到不了Check这一步!
那么如何才能够让自己在PDCA循环中成长?
Plan不是你做的,或者你只能有很少的时间去做计划,有时候一个任务下来了,就是告诉你,我一个半月想开发一个聊天工具,或者我想弄一个thefancy.com……在大公司,或许你听到这些就是笑一下,在小公司,你需要做出来,因为这是你的工作任务。所以很多在大公司混的很好的人,到了小公司或者是自己创业的时候,结果都一片惨淡。想很好的执行PDCA循环,当然是对产品是最有利的,对团队成长也是最有帮助的,问题是:小公司的资本是稀缺的。
在小公司工作了1年多,拿了半年的时间去适应(半年后差点离职),然后用1年的时间去实践。如果用alexa.com的信息去衡量okhqb.com,我觉得在这个地方,自己架构方面的成长都是吹牛的,没有流量的攀升,架构其实6个月搞定后就稳定了;如果从码字的角度探讨,我进步的就是挽起袖子就把代码写了。我越来越讨厌所谓的Plan,最后发现在按照小公司的人员素质,这TMD就是浪费时间或者说你在给一些没有能力的人培训。
如果想更快的达到预期的效果,确定目标之后,就是去DO了,所谓的设计,所谓的产品探讨,所谓的架构思路,只会无谓的浪费时间(如果你没有一点产品观,我还是建议你探讨一下)。一个有产品观的架构师在项目成败上尤为重要,因为,这个人节省了Plan的时间给Check。而多数产品是Check的时间不够或者让别人占了先机导致项目失败。慢慢的,觉得阿里巴巴的大P带人是相当有道理。
在小企业中,把PDCA变成DCAP的循环,先行动,然后逐步有了规划,选对了方向,加起自己的速度。(移动)互联网创业,还是挽起袖子把代码写了吧!-----写给自己,也给那些创业的朋友们提点建议。
最近一个月公司某部门把系统的问题整理成execl不断的反馈给技术部,这些问题有些是用户发现的,有些是他们自己发现的,有些需求是他们自己谈论的。问题和需求汇聚成册,给到技术部,然后技术部清楚的知道:资源应该向什么地方倾斜一下。如果用打仗来比喻创业,他们清楚的告诉后方,在9点钟方向,距离我2000M的地方发现敌情,迅速的炮火支援。然后我只需要把炮弹准确的击中目标就好了。
“文人相轻”的现象尤其在程序员圈子中表现的明显。我相信不少程序开发团队中,都会存在说系统代码很烂的人,如果你让他们说出50条的理由,他们又说不出来,说别人差劲的人往往自己也不怎么样!“相轻”的行为,需要有各种装逼的利器,如果本身素质不能达到一定的水平,就尴尬了。
case : 程序员
反馈系统问题当然需要具体的证据,程序员想证明您的同事写的代码一般般,必须拿数据说话。“工欲善其事,必先利其器”,所以找到各种利器是你的不二法宝,随手搭建一个Jenkins + Sonar的系统,导入你们的代码,然后搞个PPT show给你的同事们,让他们当场脸红。您至少可以列出以下事实:
- 代码注释率,有没有30%?
- 测试代码覆盖率有多少?
- 重复代码量,是否高于5%?
- 哪些地方的代码需要重构,可以一一列出;
- 通过timemachine看看复杂度,覆盖率,方法复杂度的变化。给出你的建议
- ……剩下的就是自己去研究sonar
或者您可以懒惰一点,给IDE安装一个findbugs去找出系统中的100个问题,如果您觉得想找出更多问题,可以考虑给您的IDE安装一个checkstyle,列出200个系统问题。当然没有前面的方法酷而已。
当然如果你是真正的高手,你需要教一下我在不适用任何工具的情况下,最快的速度把代码中的问题查找出来。查找代码的问题只是小Case,能够通过代码看出系统架构设计的问题才是牛人。例如:日志的规范化,测试的框架化,核心系统plugin的构建,框架的深入使用,服务的抽离……
这个一个没有止境的工作,所以没事只需要行动,不要说话。
case : 产品经理
能够说出
okhqb.com网站的会员营销的产品的50个改进细节的人,您就不要过来凑热闹了,我写的内容对您没有帮助。因为,我只是兼职的搞过产品,说下自己的心得而已。
互联网的产品,需要价值驱动。能够形成产品闭环才能创造价值。例如:用户营销方面,第一步用户注册,应该如何诱惑;第二步用户购买应该如何驱动;第三步如何让用户的朋友也过来买;第四步买完商品后给用户什么样的好处。让用户在第二步和第四步不断循环,创造出指数的价值。
你的系统烂,是不是没有形成闭环,是不是没有指数级的产品,而这些点到面的寻找可以帮助公司和自己成长。而简单的说产品做的差,没有价值。
我理解的产品,一个需要用户价值驱动,一个数据驱动,二者有效的结合起来带来更大的价值,或者说否则是前者优化的驱动力。
case : 用户服务
提到用户最近的,当然是客服人员和销售人员。如果一个程序员去当了客服或者是销售,就能很好的连接到开发端和服务端。例如给我们提交需求的人以前就是一枚程序员,他知道如何和开发人员打交道。
所谓的
Connect The Dots 或许说的就是人应该拥有多重技能去更好的工作,你会发现得诺贝尔奖的不少是在边缘科技上串起来的人(这个是我同学告诉我的,我认为是存在的)。而工作中也需要有这样的角色。有时候在新的领域的努力只需要20%而却能收获80%的成果,或许,这就是所谓的连接点的价值。
古人总结一句话叫:“严于律己,宽厚待人”。“满瓶子不荡半瓶子荡”的情况处处都是存在的,批评别人的时候需要小心,您真的是高手么?请拿出证据!
2012年在架构设计上,个人觉得最有价值的表现在3个方面:
1. LXC半虚拟化技术在线上环境的使用,解决了Java的端口的问题;
2. Nginx-mem-module解决活动期间的并发问题;
3. 使用Node.js + Socket.io + Redis 的架构设计开发出来了一个实时通讯的客服系统;
由于这些架构设计对于我本来说都需要时间的考验,所以,都没有通过bolg写给大家看。简单的给大家说一下架构选型的原因:
1. 使用LXC纯属KVM每次都需要启动虚拟机,LXC使用更加的简单,同时能够解决我们的问题,现在我甚至喜欢上了LXC在宿主机上启动进程的模式。
2. Nginx-mem-module的使用是因为活动期间,我们系统挂掉了,在静态文件和nginx+memcached之间我们选择了Nginx-mem-module,后来发现开启keep-alive模式符合我们的预期。
3. 作为java程序员,没有选择XMPP协议去开发一个实时通讯客服系统,是因为看到了trello.com的实时机制,我很喜欢这个团队实时协助的网站,就拉着人看看trello.com的架构,然后借鉴了去开发我们自己的系统。node.js入门比较简单,socket.io解决了大部分浏览器的问题,redis搞定并发。
虽然沉淀了半年的时间,但是我依然觉得对问题的看法比较肤浅,所以珠三角2013年活动沙龙聚会我没有给大家讲具体的架构设计,而只是谈谈入门级别的内容,欢迎大家和我探讨。
PPT放到slideshare上了,看不到的猛击 这里 下载
Fabric 是基于 SSH 协议的 Python 工具,相比传统的 ssh/scp 方式,用 Python 的语法写管理命令更易读也更容易扩展,管理单台或者多台机器犹如本地操作一般。
官网地址:http://fabfile.org 安装方法这里不在说明,推荐使用:pip 或者 easy_install 来安装。
传统维护方法:
$ ssh x.x.x.x 'uname -a' -- 输出略
Fabric 示例:
$ cat fabfile.py
from fabric.api import run
def uname():
run('uname -a')
$ fab -H x.x.x.x uname -- 输出略
肉眼直观看上去,貌似比 ssh 方式要写不少代码,但是基于 ssh 方式中间可控环节比较少,例如:你想判断某服务是否已经启动,没有启动则执行启动等等操作。ssh 命令式的做法稍显麻烦。(当然龌龊一点可以在被操作机器上写好一个脚本,ssh 调用这个脚本)
说几个 Fabric 的优点吧:
- 角色定义
- 代码易读
- 封装了本地、远程操作(还需要自己封装system/popen/ssh操作么?)
- 参数灵活(动态指定 host/role 等,还有并发执行 基于multiprocessing )
- 完整的日志输出
罗列的这些,其实日常工作里基本都有类似的封装了,但是有现成的一个成熟的工具,干啥不用呢?对吧。
常用的配置:
env.host -- 主机ip,当然也可以-H参数指定
env.password -- 密码,打好通道的请无视
env.roledefs -- 角色分组,比如:{'web': ['x', 'y'], 'db': ['z']}
fab -l -- 显示可用的task(命令)
fab -H -- 指定host,支持多host逗号分开
fab -R -- 指定role,支持多个
fab -P -- 并发数,默认是串行
fab -w -- warn_only,默认是碰到异常直接abort退出
fab -f -- 指定入口文件,fab默认入口文件是:fabfile/fabfile.py
更多请参考:fab --help
常用的函数:
local('pwd') -- 执行本地命令
lcd('/tmp') -- 切换本地目录
cd('/tmp') -- 切换远程目录
run('uname -a') -- 执行远程命令
sudo('/etc/init.d/nginx start') -- 执行远程sudo,注意pty选项
示例1:管理远程 nginx 服务
$ cat fabfile.py
from fabric.api import *
@task
def nginx_start():
''' nginx start '''
sudo('/etc/init.d/nginx start')
@task
def nginx_stop():
''' nginx stop '''
sudo('/etc/init.d/nginx stop')
$ fab --list -- 查看可用命令
Available commands:
nginx_start nginx start
nginx_stop nginx stop
$ fab -H x.x.x.x nginx_start -- 启动 nginx
示例2:基于角色
$ cat fabfile.py
from fabric.api import *
env.roledefs = {'nginx': ['x.x.x.x', 'y.y.y.y'], 'mysql': 'z.z.z.z'}
@task
def mysql_start()
''' mysql start '''
sudo('/etc/init.d/mysql start')
$ fab --list -- 查看可用命令
Available commands:
nginx_start nginx start
nginx_stop nginx stop
mysql_start mysql start
$ fab -R nginx nginx_start -- 启动 nginx
$ fab -R mysql mysql_start -- 启动 mysql
示例3:混合本地和远程操作
$ cat fabfile
def hello():
''' test hello '''
with lcd('/tmp'): # 切换到 /tmp 目录下
local('svn co http://xxx xxx') # check 代码到本地
local('tar czf xxx.tar.gz xxx/') # 压缩本地包
put('xxx.tar.gz', '/tmp') # 上传压缩包到远程 /tmp 目录下
with cd('/tmp'): # 切换到远程 /tmp 目录
run('tar zxf xxx.tar.gz') # 远程解压
是不是看上去都是像本地一样?对吧。
-------------------------------------------------------------------------------------
鱼哥这篇文章写的不错,如果用flask写个界面操作就更加优美了,何不去做一个呢? From:http://chenxiaoyu.org/2012/08/30/deploy-with-fabric.html
1:分布式理论
CAP(Eric Brewer)
Web服务无法同时满足以下3个属性
- Consistency(一致性),数据一致更新,所有数据变动都是同步的
- Availability(可用性),每个操作都必须以可预期的响应结束
- Partition tolerance(分区容错性),即使出现单个组件无法可用,操作依然可以完成
在任何数据库设计中,一个Web应用至多只能同时支持上面的两个属性,不可能三者兼顾。对于分布式系统来说,分区容错是基本要求,所以必然要放弃一致性。对于大型网站来说, 分区容错和可用性的要求更高,所以一般都会选择适当放弃一致性。对应CAP理论,NoSQL追求的是AP,而传统数据库追求的是CA,这也可以解释为什么 传统数据库的扩展能力有限的原因。
ACID解决方案
ACID数据库事务极大地简化了应用开发人员的工作.正如其缩写标识所示,ACID事务提供以下几种保证:
- Atomicity(原子性),事务中的所有操作,要么全部成功,要么全部不做.
- Consistency(一致性)在事务开始与结束时,数据库处于一致状态.
- Isolation(隔离性) 事务如同只有这一个操作在被数据库所执行一样.
- Durability(持久性). 在事务结束时,此操作将不可逆转.(也就是只要事务提交,系统将保证数据不会丢失,即使出现系统Crash,译者补充).
数据库厂商在很久以前就认识到数据库分区的必要性,并引入了一种称为2PC(两阶段提交)的技术来提供跨越多个数据库实例的ACID保证
BASE解决方案
- Basically Available(基本可用)
- Soft-state( 软状态/柔性事务)
- Eventual Consistency(最终一致性)
BASE模型是传统ACID模型的反面,不同与ACID,BASE强调牺牲高一致性,从而获得可用性,数据允许在一段时间内的不一致,只要保证最终一致就可以了。
2:分布式系统基础组件
RPC
message queue
failure detection
- “The φ Accrual Failure Detector”
分布式系统中的一致性
- "Principles of Computer Systems Design" 第十章(可以到MIT 网站下载)
- 虚拟同步(virtual synchrony)系统
- K.P. Birman 的两篇论文,讲述虚拟同步的概念的实现方法
- Reliable Communication in the Presence of Failures
- Exploiting virtual synchrony in distributed systems
- 扩展的虚拟同步(Extended Virtual Synchrony),也称为 TOTEM 协议
- Y. Amir 等,"The Totem Single Ring Ordering and Membership Protocol"
- L.E. Moser 等,"Extended Virtual Synchrony"
- Corosync 是 TOTEM 协议的一个开源实现,当前 RedHat 等提供的企业集群使用它作为一致性协议。
- 采用类似 Paxos 算法的系统
- Leslie Lamport, "Paxos Made Simple"
- "Paxos Made Live - An Engineering Perspective" Google 实现 Paxos 算法时的工程考虑。
- Zookeeper,两篇介绍 ZooKeeper 的论文
- ZooKeeper: Wait-free coordination for Internet-scale systems
- A simple totally ordered broadcast protocol
- Google 的 Chubby,"The Chubby lock service for loosely-coupled distributed systems"
- 最终一致性
- 最终一致性概念
- Cassandra 中最终一致性的应用
- 基于 Gossip 协议的组成员管理,论文 "Efficient Reconciliation and Flow Control for Anti-Entropy Protocols"
- 基于 Merkle tree 的数据同步算法:“Informed content delivery across adaptive overlay networks”
- CAP 理论
- BASE 理论 http://queue.acm.org/detail.cfm?id=1394128
3:分布式数据库和分布式文件系统
Google File System
MooseFS
Ceph
Dynamo
- 论文 "Dynamo: Amazon’s Highly Available Key-value Store"
Big Table
Cassandra
Parallel Database
- Yahoo! PNUTS 论文 "PNUTS: Yahoo!’s Hosted Data Serving Platform"
- GreenPlum 并行数据库,私有软件,非开源
- HadoopDB,论文 "HadoopDB: An Architectural Hybrid of MapReduce and DBMS Technologies for Analytical Workloads"
分布式数据库对比
论文 "Benchmarking Cloud Serving Systems with YCSB"
4:大规模数据处理
- MapReduce
- Hive, Pig
- Hive 论文 "Hive – A Petabyte Scale Data Warehouse Using Hadoop"
- Pig 论文 "Pig Latin: A Not-So-Foreign Language for Data Processing"
- search engine (Lucene)
5:关系数据库
- 数据库设计与实现基本理论
- Book "Database System Implementation"
- transaction processing
- Book "Transaction Processing: Concepts and Techniques"
- Book "Principles of Transaction Processing, Second Edition"
- 性能优化
- Book "High Performance MySQL"
- Book "Physical Database Design"
- SQLite 代码分析
- PostgreSQL
6:分布式系统理论研究
这几本书里面,"distributed algorithms" 比较偏重纯理论,与实际技术相关性不大,阅读优先级较低;"distributed systems: principles and paradigms" 讲了不少实际系统,但是讲的不是很深入(也很难讲深入),初学者可以先浏览一遍;"Principles of computer systems design: an introduction" 是一本新书,对系统设计的很多思想讲的很透彻清晰,优先级较高。
- Lynch's book "distributed algorithms"
- Tanenbaum's book "distributed systems: principles and paradigms"
- "Principles of computer systems design: an introduction"
- CAP theorem paper, "Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services"
7:值得读的博客
网站受到DDOS的攻击,Inbound最高请求58.85Mb/sec 。尽管一开始解决问题的思路是错误的,但是在这个过程中,我们思考问题的思路对团队的成长有所帮助,我们知道什么方法无法解决问题。解决问题的过程分为3个阶段:
1:nginx端屏蔽访问
修改nginx配置文件,添加如下记录
location ~ /\/you_url {
return 404;
}
问题:发现请求堵塞在haproxy上面去了
2:修改haproxy的配置
acl invalid_req url_sub -i c=220
block if invalid_req
问题:依然不能解决haproxy堵塞的问题
3:在haproxy机器上禁止IP访问。
在nginx下找到IP最多的几个IP,到/data/management/logs中去执行
cat www.access.log | awk -F \" '{print $7}' | sort | uniq -c | sort -rn | head -n 300
得到访问最多的IP列表
通过vim的列编辑功能,限制这些ip的访问。(300个是可以继续加大的,看最后一行的最小值)
iptables -I INPUT -s 218.66.51.197 -j DROP
iptables -I INPUT -s 183.205.228.248 -j DROP
iptables -I INPUT -s 59.39.181.217 -j DROP
iptables -I INPUT -s 218.76.255.3 -j DROP
iptables -I INPUT -s 110.81.116.67 -j DROP
iptables -I INPUT -s 220.178.35.226 -j DROP
iptables -I INPUT -s 218.207.198.17 -j DROP
iptables -I INPUT -s 61.175.231.96 -j DROP
iptables -I INPUT -s 221.193.244.115 -j DROP
iptables -I INPUT -s 171.36.103.115 -j DROP
解封1:
iptables -L INPUT
iptables -L --line-numbers 然后 iptable -D INPUT 序号
解封2:
iptables -F 来清空,(比较危险)
iptables -D INPUT 数字
4:网上防止DDOS攻击的方法(我们的思路是错误的,这个脚本的思路才是王道)
正确的思路是查找Haproxy机器的所有连接IP数,然后查找IP数大于某个值的IP,在防火墙层面静止这些IP访问。
安装
wget http://www.inetbase.com/scripts/ddos/install.sh
chmod +x install.sh
./install.sh
卸载
wget http://www.inetbase.com/scripts/ddos/uninstall.sh
chmod +x uninstall.sh
./uninstall.sh
具体使用可以去自行研究,可以把里面的脚本挪出来,简单粗暴的防止DDOS!