上次写了一篇博文大家很喜欢,但是主题范围偏大,且偏理论,这篇博文说说纯技术方面的一些想法,对于一个互联网创业公司来说,有这几个特点:(1)什么都要求快,这个快也许并非来自用户,而来自于自己,比如恨不得开发一天就开发一个新功能(2)变化快,比如一个想法落实到开发,可能会有很多变化(3)资源稀缺性,资源就是时间、金钱和人力成本,对于创业公司来说,有效的花费资源本身就很重要,看看多少创业公司都是胡乱花钱而撑不下去的,而对应的技术上就是能省则省。
针对这三个主要特点,创业公司在技术使用的策略上有什么准则呢?个人认为就是“简单化“,当然这个简单是建立在理性分析的基础上的。技术人员有个通病,认为技术实现越复杂,越膨大,越全面就越能体现技术水平,这是非常错误的一个观点,衡量技术水平的唯一标准其实就是“是否有效支撑业务发展”,要看结果论,比如说开发速度快,后期问题少,假如能做到这些,那么这个技术团队就是牛逼的。
而提倡简单化的理论,就会让你从另外个角度去审视技术本身,下面的一些技术使用建议也许看上去并不高大上,好像每个人都能明白,但假如能有效的实行,在创业初期能够解决大部分的技术问题。
使用云服务器
对于创业团队来说,并不知道你未来用户有多少,需要使用多少服务器资源(Web 服务器,DB 服务器 等等)并不好衡量,而云服务器的可扩容性则能很好的满足这个需求,换句话说创业初期使用云服务器能有效节省成本。
当然云服务器的特点还不至这么多,它代表了一种开发模式,这就是分层架构,比如云服务器的类型有很多(云服务器、云缓存服务器、云数据库服务器、云存储服务器),正因为有了这样的分层模式,让你有了更好的选择,假如自建服务器,很多技术团队可能会把 Web 服务器和 DB 服务器放一块,从而带来很多问题。
另外云服务器也有沙箱功能,在安全性上也有很好的保证。虽然可能很多人觉得现在云厂商做的不好或不安全,不过说句实话你自己搞可能更差。
当然使用云服务器也并不能说明一定就省钱,这取决于你是是否真正了解系统以及其背后需要的资源。
重视你的数据存储
先入为主,推荐 Mysql 存储数据。
在设计上要尽量规范化,索引利用合理一点,因为数据有个特点,假如前期设计不好,后期想重新调整结构是非常痛苦的一件事情,原来公司某个产品,最重要的博文数据库表(blog 表)有个字段存储的是文章的具体内容(content 字段),从而导致这个表非常庞大,查询性能和内容非常不好控制,就我了解到的情况是目前 content 字段还是没有从 blog 表中拆分,这不仅仅是技术的问题,对于一个在线的服务,数据量很大的服务,做表结构的调整是非常困难的,所以前期尽量设计好。
Mysql 主要的作用还是存储,虽然可以通过 Sql 完成很多复杂的查询,但是建议尽量少使用,否则性能会急剧下降,我几年前了解到一个爆款的产品,用户量上来后,第一个压垮她的就是数据库,最大的原因就在于查询非常不合理,做了非常多的联合查询。
假如不合理使用 Mysql,很多人会质疑性能不行,其实这都是错觉,我一直相信的一个原则就是,既然这么多人用,说明必然有他的优势,我们要做的就是学会使用而不是抱怨。
对于 Mysql 这样的数据库,很重要的观点就是备份和安全性,刚工作的时候领导说过这样一句话,“代码可以重构,但是数据不能丢,所以在写操作数据程序的时候一定要慎重”,而 Mysql 是非常成熟的软件,备份和安全性上有很多选择。
另外一个观点就是假如你并不知道数据量和访问量是多少,开始不要选择分库发表策略,也不要搞很多路由策略,尽量简单点。单表数据量在一百万级别,只要设计和使用上保持稳健性,性能不是问题。
Mysql 的主辅同步本来是做备份用的,但是现在很多人多当分布式查询使用,其实也能分担很多查询压力。
现在很多 Nosql 服务特别多,比如 Redis ,对于创业公司来说建议不要使用:
第一就是这些服务并不完全成熟,在使用上很需要有很多经验,尤其在备份和安全性上,在运维上并不简单,需要有极大的成本。
第二虽然它有很多有点是数据库比不了的,但是还是那句话,它能做的 Mysql 也能做,对于创业团队来说,上手简单和维护简单,成本是优先要考虑的。当然假如应用场景非常适合用 Nosql 这样的服务,还是要大胆的使用。
一定要有一个开发框架
开发框架在我看来有两个最主要的作用,分别是规则和最佳实践。
所谓规则就是框架定义了一些制度,框架理论上不应该让你随意写代码,尤其在 PHP 语言中,由于太灵活了,假如没有一套框架去制约开发者,那么写出来的系统会很脆弱。
最佳实践就是框架集成了很多优秀的思想和功能,要做的就是去合适的用,框架能够解决分层的问题,能够解决安全性的问题。
所以在创业团队一定要有一套开发框架,但是在选择上必须谨慎,不要选择太难以理解的框架,比如说 PHP 框架 Laravel ,对于使用者来说需要具备很强的设计模式和 OOP 理解能力,没有经验就选择简单易学的框架;第二个选择框架不要选择封装太多的框架,举 Jquery 的例子,很多人可能会 Jquery 但不会 JavaScript,所以选框架应该选用接近开发语言本质的框架。
另外框架没有绝对的好坏,一个创业团队能够快速上手的框架就是好框架,使用框架 20% 的功能即可,开发人员喜欢过度的使用软件,说到开发框架,不要强迫开发人员使用统一的 IDE,只要最终代码输出标准一样即可(比如 PHP 语言重要符合 PSR-2 即可)。
假如使用 Cache,必须有一个优良的 Cache 管理器
在互联网产品中,可以说 Cache 为王,很多人不管三七二十一必须要使用 Cache,可个人觉得系统假如没有瓶颈(这个词需要好好理解),不一定需要使用 Cache,首先有容量资源成本,另外也会增加系统的复杂度,从而导致开发和维护成本提高。
假如实在需要使用 Cache,一定要充分理解应用场景,是 pull 式的 Cache,还是 push 式的 Cache ,如何衡量 Cache 的效果。
假如必须要使用 Cache ,一定要有一个 Cache 管理器,什么意思呢?对于技术人员来说,代码在写的时候,意识不到 Cache 的存在,全部优雅的封装了。而封装能带来开发和维护成本的减低。
最重要的一点就是不要过度追求命中率这一指标,从而把代码搞的非常复杂,比如使用 Memcached,可以基于 Sql 查询语句做 Cache ,多采用 pull 的方式,过期时间可以设置短一点(意思就是不要主动的去更新 Cache)。另外一种使用方式就是将数据库的联合查询的结果主动放入到 Cache 中。
尽量异步化
异步化是一种开发策略,对于创业团队的产品来说,资源有限的情况下,没有必要每个功能追求及时响应,比如说现在很多 SNS 产品,没有必要评论数、点赞数及时更新,排行榜也不用及时更新,假如什么功能和需求需要做到极致,对于开发和时间是极大的挑战。
所以对于创业团队来说,请有效使用异步化,举简单的几个例子:
(1)比如说用户点赞,没有必要程序即使响应这个用户有没有点赞,直接将这个请求放入队列,这样这个接口的响应和吞吐能力就提升了。
(2)每天博文访问的排行榜,没必要查询数据库,每天或者每个间隔时间从数据库中查询出结果放入缓存即可,减少了多少数据库的查询。
日志系统
在互联网应用中,日志无处不在,操作系统运行的日志,服务器的日志,软件的运行日志,数据库操作的日志,应用程序日志,产品业务日志。这些日志是了解服务运行状况的最好的来源,在创业团队,最忌讳系统出了问题不知道如何分析问题,产品人员需要一些数据却拿不出,系统的历史运行状况也完全一抹黑。
所以对于创业团队来说,一定要重视日志,对于开发人员来说,在开发框架中一般都有日志模块,良好的定义好日志格式和含义。假如服务器众多,可以使用一些分布式日志系统来搜集和压缩日志,其实 Linux 发行版自带的 Syslog 其实非常好的一款软件。这样从侧面说明我们不用寻找多少高大上的软件,用好操作系统自带的工具就很不错了。
监控
有了日志,下个话题就是监控,因为监控都是基于日志的分析,确定合适的阀值,选择是否报警,所以对于技术团队来说,有了日志就要充分的分析。而一套完善的监控系统很重要,能够对系统的运行状况有更好的了解,主动的去发现问题,而不是等待用户去投诉。
监控的维度可以有很多,比如系统运行的慢日志、资源调用的错误率、数据库更新频率突然飙升,某个接口访问数异常,写代码其实很容易,难的是如何知道系统出现异常背后的原因。
监控软件其实有很多,在使用的时候一定要精确定义阈值和阈值背后的含义,比如说我们公司也有监控系统,可问题出了后还是没有通过监控系统发现,最后发现报警短信太多了,忽略了,运维呵开发人员对于报警短信也麻木了,所以说使用监控系统很简单,正确使用则有难度。
Wiki 系统
Wiki 个人理解其实就是提倡写文档,文档的作用其实很多,如何写不重要,重要的是这个文档的作用是干嘛的?能让人明白吗?
假如一个新员工来了,看了文档后,就知道系统包括了什么模块,自己如何快速开发,如何上线,这就是一个好文档;
假如要优化一个原有的服务,开发人员不是通过代码去找逻辑,而是通过文档去了解大概的逻辑和包含的模块,当然文档也不需要太详细。
文档是开发人员和运维人员之间的协作工具,比如服务器的 IP 是多少,系统中资源的路径和 IP 是多少(比如数据库的域名、外部 API 的地址),说个简单的笑话,原来公司运维人员维护了一百多个 Memcached 端口,最后发现找不到使用方是谁了,最后不得不发邮件让大家认领,可大部分最后也没人认领,有了文档这些问题就能解决了。
文档是开发人员之间的协作工具,在创业团队,变化太快了,大部分都是通过人与人之间的沟通,可沟通假如总是变化,最后发现双方理解的有偏差,浪费了很多开发时间,而约定的文档能在一定程度上解决这问题。
上面举得例子就简单解释了文档的重要性,其实文档代表了一种开发思维,可以这么说没有文档,代表开发混乱,有了文档从侧面也能大概看出代码实现的是否合理,这才是文档最重要的用户。
写文档避免的几个误区,第一就是不要太遵循写作规则,能够说清楚就行,有些开发人员不想写文档的原因之一就是写文档比写代码还要求严格;
第二就是文档一定要保持更新,比如说一个功能上线初期是有文档的,后来代码一直在迭代,最后开发人员发现文档和代码的逻辑完全不一样,大家也就失去了看文档的动力,所以文档最重要的就是要持续更新;
第三文档不要强制开发人员去写,也不用及时让大家去更新,让大家的约束少一点可能效果更好。
代码构建,部署,发布系统
对于创业团队来说,假如一个新员工来了,需要快速能够让其进行开发,所以需要有一套集成化的环境,主要包括:代码协作工具,代码构建,代码部署(开发环境、仿真环境、线上环境)。
为什么需要这套环境呢,目的就是为了缩短产品上线时间,让技术人员专注于业务开发,而不是被其他的一些因素困扰;第二个目的就是为了产品的质量;下面分别说下:
在很多开发团队,有的时候出现问题,都是开发人员直接线上修改代码,从而导致潜在的问题;还有任何开发人员都有线上的服务器的权限,导致安全性得不到保障;在产品上线后,测试人员说怎么测试的时候没有问题,一上线就有问题,开发人员说测试人员测试的环境不是线上环境;新来一个员工,一个星期都没法搭建自己的开发环境;反正很多此类问题,从而也导致了时间的浪费和质量的下降,而更大的危害就是失去别人的信任。
所以有这样一套环境很重要,不用特别的高大上,下面就简单说一说:
(1)首先要有一个代码版本控制系统,这个现在大部分都会使用,也不用特别介意用 SVN 还是 Git。
(2)让运维人员写一个脚本,能够配置开发环境、仿真环境、线上环境(环境一定要隔离),说真的,简单的 Shell 脚本就能完成。这里的环境不仅仅是服务器,包括数据库资源等等,这时候大家也意识到 Wiki 的重要性了,假如没有文档,不可能能搭建这样的系统。
(3)代码构建系统,其实在 PHP 这样的高级语言中,本质上不存在代码构建这一说,假如有特殊需要,也是可以通过 Shell 脚本来实现。
(4)代码部署系统,在开发环境中,完全可以借助 IDE 和 FTP 将实时变动的代码同步到开发环境中;假如代码需要部署到线上,可以借助于 SVN 和 Rsync 这样的工具将有差异的代码快速发布到线上,有问题也支持快速的回滚。
假如可能的化由开发人员做运维
运维这个岗位其实需要了解网络,Linux ,Shell等相关知识,而开发人员本身也应该掌握这些知识,假如开发人员不了解这些,而只是会编码,那代表他并不真正会编码,了解这些知识开发人员可以更好的理解一个系统,当系统出现问题的时候能够从多方面去排查,更好的维护。
在我工作的这么多年中,开发岗位和运维岗位总是不能很好的协作,出现问题的时候开发人员说这是网络问题,是运维的服务器不够,或者说数据库响应慢;而运维人员则更痛苦,你开发人员写的什么程序啊,数据库全是联合查询,导致数据库性能严重下降。或者说上线一个项目我们啥也不知道,你让我们在吗运维;出现这些问题的原因在于双方对于对方掌握的技术领域不了解,互相不理解或者不明白对方的职责,而这些会导致整个产品和系统的稳定性出现很大的问题。
所以对于创业团队来说,假如技术能力足够,运维工作尽量由开发人员来做,当然这里的运维可能更多的是产品运维的角色(在大企业,运维岗位的分工也越来越明确),具体的工作比如说安装软件开发包,进行 Nginx、PHP 配置,切割日志,这些工作本身也不复杂,开发人员假如能够掌握好,对于系统的维护是由极大的好处的,另外潜意识告诉开发人员,出现问题没有人能依赖,代码和环境需要你自己去攻克。
以上说的观点大家可能发现了一个规律,这些都不涉及到人的因素(比如开发人员素质,协作能力),大家只要遵守就能很好的完成,而完成这些,就能解决软件开发中的大部分问题,让你系统更稳健,让你的开发更快速,让你的成本更低。对于创业团队开发人员来说,不要高度追求技术的高大上,有效解决问题很重要。