IT圈持续部署并不是毫不费力 确是不平凡

  这几年,持续集成随着敏捷在国内的推广而持续走热,与之相伴的持续部署也一直备受关注。自前两年,持续交付这个延续性概念又闯进了国内 IT 圈,慢慢开始在社区和会议中展露头角。许多不明真相的群众跟风哭着喊着要“上”,而许多前 CI 的半吊子玩家换件衣服就接着干,有的甚至衣服都来不及换……。国内的这些土财主如果不巧请了某些所谓的战略家,除了建了一堆持续集成环境,以及每天嚷嚷着要这个要那个,混乱的状况在根本上没有得到改善。本文无意费力探讨持续集成和持续交付的概念,而是打算谈谈对于大型软件企业,以持续集成为基础实现持续部署(交付)时,所要面对的问题以及可行的解决方案。地主老财们,夜黑风正猛,山高路又远,注意脚下……
  And God Said, Let there be light: and there wa — GENSIS, Charpter 1, King James
  一、起步
  先来讲个故事……
  几年前,一对留美的夫妇通过朋友找到我,让我帮忙在国内组建一个开发团队,该团队负责为其开发一款基于社交网络的客户关系管理软件,(暂且称之为项目A)。这个项目除了尚不清晰的需求范围和很紧的期限外,作为业内人士的老公 Richard 根据眼下流行的软件开发过程还提了诸多额外的要求:
功能要及早交付(以便拿去和潜在的投资人洽谈)
功能在部署到生产环境前要先部署到一个测试环境(Richard 要试用后给予反馈)
功能必须经过测试(长期作为软件外包的甲方,对质量要求严格)
要减少后期维护的工作(美国人精贵,少雇一个是一个)
支持协同开发(以便维护人员及早介入)
……
  这正是持续集成所要解决的典型场景。针对 Richard 的要求,我们只要建立一个基于 Hudson(现在叫 Jenkins)+ Maven + SVN 的持续集成环境(再加上持续集成所要求的测试和过程)就可以很好地满足上述要求,此方案的结构如下:


  对于上述方案,让我们近距离看看各个服务器的内部情况,以及人员在这种方案下的分工协作:


  我们先谈谈上面的图中涉及的一些概念性问题:
  1. 1)编译时依赖和运行时依赖
  从字面上不难理解这两种依赖的类型。但要注意虽然编译时依赖常常也是运行时依赖,但并不能推断出一方必然是另一方。比如,在开发的过程中需要某些提供 API 的 Jar 包,而运行时可能是具体 API 实现的 Jar 包。再者,被依赖的包会有其自身的依赖,因此,项目对这些包产生间接依赖(运行时依赖),依此类推,最终形成一个依赖树。当项目运行时,这些依赖树上的包必须全部就位。
  Maven 在 POM 中通 scope 来界定依赖的类型,从而帮助开发和运维人员摆脱手动处理依赖树的工作,然而运行时所依赖包最终是要安装到生产环境的,这部分工作 Maven 并不能自动完成。因此,一个常用方式是将运行时所依赖的包拷贝到项目文件中,比如 Java Web 应用的 WEB-INF/lib,然后将项目总的打一个包。在安装项目包后,修改环境变量,将这些包所在的路径加入相应的环境变量中,如 ClassPath。
  再看个例子,现代的操作系统和其它系统框架都考虑到了运行时依赖树的处理问题,比如 Ubuntu 的 apt-get,CentOS 的 yum,Ruby 的 RubyGem,Node 的 npm 等等。
  1. 2)依赖时的复杂度
  项目除了对程序包的依赖,对于运行环境也有些具体的要求,比如,Web 应用需要安装和配置 Web 服务器,应用服务器,数据库服务器等,企业应用中可能需要消息队列,缓存,定时作业,或是对其它系统以 Web Service 方式暴露的服务。这些可以看做项目在系统层面对外部的依赖。这些依赖有些可以由项目自行处理,而有些则是项目无法处理的,比如运行容器,操作系统等,这些是项目的运行环境。
  总之,依赖的复杂度主要有两个:
依赖包间的版本兼容性问题。兼容性问题是软件开发的恶梦。
间接依赖,或多重依赖问题。这个问题可以类比想像一下 C++ 中的多重继承中出现的很多问题。
  比如:A 依赖于 python 2.7,A还依赖于B,但是B却依赖于 python 3,而 Python 2.7 和 Python 3 不兼容。这是依赖中最恶心的事。
  1. 3)任务分工
  由于项目简单,因此并不需要专门的运维人员。以一个 100 人左右以交付为主业(恩,就是做外包)的公司为例,由于没有任何历史项目和代码的拖累,且各个项目间也没有任何关联,故而只需要配备一个 IT 支持人员进行资源方面的管理:分配机器,报修,初始化系统,分配 IP 地址等。各个项目的运行环境、数据库、开发环境等都由具体项目的开发人员手动完成。 环境出问题怎么办?很简单,凉拌——重装系统。实际的运行效果不错。
  1. 4)自动化部署
  由于 Hudson 这样的持续集成环境提供了自动编译(定时或触发式)的功能,而且可以在编译过程中提供了一些扩展点,因此通过提供一个部署用的脚本,就可以非常容易实现简单的自动化部署。
  毫无疑问,持续集成就是敏捷的魔法药,它见效快、副作用小、业界的争论少。每每运用在混乱的项目中时,几周内项目就开始持续的产出经过测试的功能。对于独立项目,以持续集成为中心的持续部署绝对是不二选择。
  但是,我们有没有想过,这会是一个自动化部署的通用解决方案吗?持续集成应该位于持续交付的中心吗?
  二、困境
  回到我们的故事:项目A上线两年后,运营业绩不错,投资人第一轮注资后,Richard 的公司进行了扩张,他们对项目进行了重构,而且随着用户数量的增长,公司分别在美国、英国和日本等地建立了运营中心,并且对亚洲市场进行的定制功能开发(项目A+),接下来,公司又投入开发了团购系统(项目B)。在获得了新一轮投资后,各条本来比较简单的业务和功能线上越来越复杂,需要不断地细分,于是公司再度扩张(开发人员达到了 300 人,国内 200 多人,而运维团队主要在美国),随后又为项目 A/A+ 的高级用户开发了问答系统(项目C)。目前,他们正准备开发手机系统。 看看下面的图,公司增长的过程中,整个项目环境也变得复杂。(注意,这里是一种逻辑结构,而在物理层面项目B和项目A的生产环境可能部署在相同的机器上)。


  同时,原本单一的项目软件结构随着业务系统的增加也不再简单:


  而软件间的版本依赖使这个问题变得更为复杂:


  现在,Richard 的公司已经不再是一条快乐的小鱼,而是渐渐成为一直庞大的巨兽。虽然只有四个产品,但公司却要支持几百台开发机,几十台生产服务器,还有对应的测试环境,数据库服务器,以及几十个开发小组,和一大堆的内部项目。我们尽可以使用持续集成来为我们完成自动化部署。但,当我们为各个项目建立起持续集成环境后,它能满足我们对于持续部署的要求吗?我们前期的工作可以简化我们今后项目的持续交付的工作的难度吗?它需要我们为之建立一个庞大的运维团队,还是可以让我们能节省下每一毛钱来投入到真正的业务价值中去?
  让我们先来看看复杂的项目环境中的几个场景:
  场景1:环境升级
  项目A和项目B都依赖于 Web 容器,公司决定升级 Web 容器版本,而公司要升级的机器有上百台,依赖人肉升级已不现实,维护团队因此针对各种软件开发了相应的自动化脚本,但当新的软件出现时,必须要开发新的脚本。而且当同时升级若干环境软件时,则难度随之增大,手工调度的方式极易出错,当升级失败时仍需要大量人工处理。由于存在大量升级脚本,有一定的维护成本。
  场景2:依赖于环境的软件升级与回滚
  针对环境升级,公司为项目A和项目B开发了新的版本。但环境的升级和软件的升级不是同步进行,出错的可能性非常大(想一想间接依赖和多重依赖的情况)。当新版本部署到生产系统时,发现问题,需要回滚到之前的版本——所有运行时版本都需要回滚,而且环境也需要同步回滚。几百台机器……
  场景3:运行时依赖
  在第一节的方案中,我们将所有的运行时依赖都打包到一起。当项目依赖关系复杂时,这样产生的包将非常臃肿,潜在地延长了部署的时间(想一想全世界有几百台服务器,一个部署计划需要部署几百兆文件的情况),而且产生冲突的可能性非常大,而且对于不同类型的项目(Java 和 Ruby 项目)缺乏通用性。2006年左右,Nortel 可是拿 Excel 统计过运行时依赖的,牵涉若干项目组,反复多次,没有个把月真搞不定。
  场景4:泛滥的部署
  每个项目相关的持续集成环境都需要开发自己的部署脚本,重复投入大,而且各个项目的部署过程不一致,并且对于同一个项目无法同时满足不同目的部署要求,例如,环境或系统配置参数改变后,无需安装包,只需做清理和激活的工作。最后,持续集成只是支持了和代码修改有关的部署。
  场景5:不一致的环境
  简单项目中,开发环境和运行环境都由开发人员搭建,当公司变大时,系统的运行环境将由运维人员搭建,而开发环境如果由运维人员搭建则工作量太大,由开发人员自己搭建则操作复杂又容易产生不一致的情况。
  场景6:热切换
  对于某些部署,需要尽量减少服务的停止时间,需要在服务的同时进行部署。
  这些场景只是以持续集成为中心的持续部署在面对大型企业时所遇到的部分问题。大型企业,人多,项目多,机器多,项目环境复杂,部署维护工作繁多。以持续集成为基础的部署可以解决各个项目的集成问题,却无法帮助企业应对复杂的项目环境和各种不同的部署要求。究其根本,大型企业中的部署不再是一个简单的问题,而是一个交付生态圈,基础设施和环境管理必须要纳入考虑之中。要实现真正意义上的持续部署,我们就必须把环境和项目同等对待,通通纳入管理之中。同时,部署本身要得到统一。一个好的部署机制,应该是易于建立,易于使用,易于维护。
  三、任脉——环境管理
  什么是环境?
  系统运行所依赖和包含的一切就是其环境:硬件、操作系统,网络资源(IP地址、域名),服务容器,服务器软件配置,环境亦是,运行时依赖的命令和包,项目本身的包和配置都是环境的一部分。对于部署而言,广义上,这些通通应该纳入环境管理的范畴,但狭义上,从软件系统的角度看,一个环境就是其运行需要的软件及其配置(我们先把操作系统和网络资源当做基础设施,其在部署时已处于就位的情况)。因此:
  项目A的生产环境 = 项目A本身的软件包 + 项目A运行时依赖的软件包 + 项目A运行时依赖的其它软件 + 项目A的配置信息
  由于,项目本身的软件包、项目运行时依赖的软件包,以及项目运行时依赖的其它软件在本质上没有区别——都是软件,上面的定义可以进一步抽象为:
  环境 = 软件包 + 配置信息
  在这个定义下,我们就必须将运行环境的软件解构,并以包的形式导入到公司的整个项目资源库中,比如 Apache 将作为一个包被导入,而 Apache 依赖的其它包也将依次被导入,并建立起正确的依赖关系。而且,在导入的过程中还必须做些相应的调整,如,环境变量的读取和设置,必须来自于环境配置模块,而不要修改系统的环境变量,防止不同环境在系统环境配置上相互影响和依赖。
  再回头审视我们的示例,项目A的生产环境可以部署在不同的区域,对于各个区域可能有定制化的设定。这就像面向对象中的类,可以通过继承使子类重用父类的公有属性和行为并添加自己特有的信息。因此,环境的概念模型如图:


  通过这样的关系,我们很容易为示例的复杂环境建立一种简单的结构,对于项目A:


  这里,环境依然是处于知识层面(Knowledge Level),它并未与具体的基础设施相关联。当我们将一个环境“具现化”成一个运行系统时,我们就产生了一个真正的环境实例。在这两者之间,我们还必须要考虑环境实例的使用目的(开发?测试?……)以及安装所依赖的其它信息(如机器),因此,我们需要增加一个环境目标来集中这些信息,而且由于不同目标的环境可能会有所差别,因此,环境目标也需要配置的能力。概念模型如图:


  图中的环境实例是如何产生的呢?部署,一次部署可能会产生一个环境实例。一系列部署将产生对应于环境目标的多个环境实例,除去当前起作用的环境实例外(最新的),其它的是历史环境实例。通过在历史环境实例中切换,我们自然而然的就可以使整个环境回滚,因为项目所依赖的一切都已经成为环境中的软件包,而且环境依赖的包的版本会随着部署具体确定下来。如此一来,我们便可以给每个环境实例分配一个版本号,再通过环境实例的版本号与软件包的版本对应起来,从而得知一次部署时应用的具体软件包,如图:
http://www.zhenqianpuke5.com/; http://www.1788am.com/; http://www.lswjsdu.com/; http://www.lswjsdubo.com/;http://www.lswjspingtai.com/;http://www.zhenmoney.com/;http://www.laohuji6677.com/;http://www.zxzrgame.com/
http://www.zhenqianqipai9.com/;http://www.zxqipaipingtai.com/;http://www.zjh5566.com/;http://www.onlineduchang.com/
http://www.aomenbo77.com/;http://www.zhenrenqipai6.com/。


  目前的环境管理结构,已经可以解决场景1、2和 5 的问题。那么对于场景2,运行时依赖,环境管理应该如何解决呢?
  细心的朋友,可能已经发现,在环境层面上我们确定了环境依赖的软件包,这里有两个隐藏的含义:
环境定义的是对软件包的运行时依赖
由于环境是一个逻辑上的概念,因此其所用的软件包也是一个逻辑上的概念(相对于版本控制系统中的软件包)
  我们也已经知道,在部署时,一个环境实例将具体的确定其依赖的软件包的版本。某个版本的软件包最终与代码库中的物理的软件包相关联。但软件包是运行时的安装包,因此,它应该是代码库中包编译的结果。在对代码库的包编译时,既要将结果打上版本保存起来,也好在两者的版本间建立关系,最后,编译结果应该是某种既定的安装包目录文件结构。
  另外,当环境包含的包比较多时,运行时版本树会非常大,手动的指定全部的包的版本将是一个非常大的体力劳动,这部分工作也要得到简化。由此,我们必须
建立逻辑软件包版本和版本库中软件包版本间的关系
为相互依赖的包编译并打上统一的标签
简化运行时包依赖关系的生产
简化运行时包依赖的指定(可参考 apt-get 和 RubyGem,环境只需指定直接依赖的包,间接依赖的包从运行时依赖树中自动导入)
  一个可能的简单结构如下:http://www.worldyule.com/    http://www.bocai1900.com/   http://www.xianjin1901.com/
http://www.macau1818.com/   http://www.dbinmacau.com/   http://www.118yule.com/    http://www.am1181.com/    http://www.aomen181.com/   http://www.bjgames.net/     
http://www.lswjs189.com/     http://www.18lasvegas.com/

  上述讨论还没有涉及操作系统,如果我们的运行机器要支持多个系统,我们又该怎么办???
  配置信息也是个大问题,大家可以思考
环境配置和应用配置如何区分?
如何简化环境配置工作?
如何使环境配置的效果只对具体环境有效,而不会泄露到环境外部?
  再者,
如何使应用支持多运行目标?
环境管理如何能方便开发环境的调试?
要如何简化版本的选择?
在多个包有编译和运行时依赖时,编译时如何检查以减少引入兼容性问题的风险?
  这些都留待大家思考。
  四、督脉——部署系统
  《持续集成》和《持续交付》中都对部署有详细的讨论,不在赘述。在我看来,部署其就是按照其目的执行一系列步骤将环境置于其目的所指向的状态中。我们一会再回过头来看这段文绉绉的话,先看看第一部分持续集成的环境下,我们部署的步骤可能会是下面这个样子:
登陆目标机(ssh)
停止服务
清理环境
准备安装环境(创建文件夹等)
安装项目包(rsync,解压,权限设置等)
配置环境变量
启动服务
……
  而在第二部分的情景4中,我们看到如果对不同的持续集成环境建立不同的部署脚本和环境维护脚本,这部署过程的维护会非常繁琐。基于第三部分的环境管理,我们可以将部署过程抽象为:


  现在回到开头那个文绉绉的描述:部署其就是按照其目的执行一系列步骤将环境置于其目的所指向的状态中。
  由于我们已经将部署作为环境管理的一部分,而环境又是对外提供服务的最小实体,因此,对环境的部署就是要根据部署的类型,在环境上按一定的步骤执行一系列操作,从而使环境置于部署类型所要的状态,这个过程中可能会生成对应的环境实例。举例来说,我们可能会修改环境相关的一些配置,然后重启环境,显然,这种情况下不需要下载安装软件包(没有改变),因此也就不需要生成环境实例。
  对于标准的部署——安装软件包并启动环境,可能的步骤将会是:
选择将要部署的软件包的版本
生成新的环境实例(确定环境实例的版本和其依赖包的版本,确定环境配置等)
清理和准备目标机环境
下载包
设置环境配置
环境实例切换
生成部署报告
……
  好,部署系统和环境管理各就各位,我们可以将各个项目环境纳入我们的环境管理之中,甚至是持续集成环境本身。再补充一句,要让部署系统和环境管理能很好的发挥作用,我们即需要一个简单一致的 UI 界面(为开发人员),也需要提供一个清晰明了的服务接口(供外部系统调用,如持续部署系统)。对于与环境管理相关的机器状态管理,网络资源的配置等等,本文不再涉及,大家可以自己思考。环境管理的实现、编译系统的改造以及持续部署的具体实现,另作文章探讨。
  就技术而言(不考虑围绕持续部署的过程实践),环境管理、部署系统以及我们没有提及的编译系统改造才是生产线的真正引擎,持续部署不过是水到渠成的传送带而已。
  五、没完
  打通了任督二脉后,事还还没有完,还有很多细节上的问题。你想,这个工具实在是太好用了,于是公司里成百上千的工程师们都在使用这个自动化部署系统,我们又会面对很多很多问题:
部署系统的性能问题。几百号人不停地在把他们的软件部署到自己的机器上,部署到测试环境,部署到生产环境,一天之内一个人可能会要部署N次,回滚N次,不但有大量部署请求,还有大量的文件在网络上传输。你得想想这套部署系统如何解决这些性能问题,还得考虑未来更大规模的性能水平扩展问题。
目标机环境的管理。在目标运行机上需要解决几个问题:1)两个环境间如果有一些一样的包,那就没有必要再下载了,这样可以节约时间。2)每次部署都需要把老的部署环境给保留下来,这样方便在新旧环境下的切换。这两点对于在生产环境下部署非常关键。(这需要环境内所有软件的绿色安装才能更容易达到这个目标,因些,Unix/Linux 会比 Windows 更容易做到这点)
部署一致性事务问题。有时候,我们需要同时部署若干台服务器,比如:包A到机器MA,包B到机器MB,包C到机器MC,……(Web Service 的 SOA 架构),这些包之间有运行依赖性和兼容性问题,要么一次性全部完成,要么就全部失败。回滚也是一样的,这是一个部署事务或部署一致性的问题。如何解决呢?
部署环境的版本控制问题。前面说过,我们的一个环境就会和若干个包的版本耦合,环境必须管理要部署的包的版本。于是,当你的部署越来越多的时候,各个环境的包的版本开始出现混乱,各种依赖间的版本也会出现不统一的情况,也就是说,就算你有这样的一个工具,在一个高速开发的环境下,我们的部署环境的管理还是会出现很多混乱的情况,需要你不断地统一大家的开发、测试环境。
部署计划。我们可能会有很多部署计划,比如:设定定时部署,提升或降低部署优先级,部署事务定义,部署策略(如:先部署 10% 的机器,如果没有问题,再把剩下的系统部署了),热切计划和策略…… 等等 ,等等 。
部署的监控和维护。任何软件和系统都会有这样的问题,当规模上去了以后,我们的自动化部署系统的监控和维护的复杂度并不亚于一个大型的互联网应用。
  这样的问题会有很多,基本上来说,这样一个持续集成持续部署的自动化系统并不是那么简单的事,其开发工作量和一个标准的大型互联网业务系统没什么两样。
  六、总结
  这里只谈一点自己的看法,从传统的持续集成到面向大型软件的持续部署,我们将系统所依赖的软件环境和软件包抽象为一致的实体纳入到管理之中,并将运维人员的工作真正的分摊到开发人员身上。而云计算的出现,使得计算机本身也可以自动化的创建和回收,这样环境管理的范畴将进一步扩充。相应的,部署的能力和灵活性也是一次质的飞跃,将再一次减轻运维人员的工作压力。
  说了这么多废话,总结一下自己的观点,对于向大型软件企业推销基于持续集成的持续部署(交付)的哥们:
你就是在耍流氓,如果你不解决环境管理!!!
你就是在耍流氓,如果你不建立部署系统!!!
你就是在耍流氓,如果你不扩展编译系统!!!
你就是在耍流氓,如果你只是推销小团队的实践而不考虑改造大环境!!!
你就是个流氓,如果你只是不断地告诉别人怎么做,自己却从来不动手写一个测试或建立一个持续集成环境!!!
  最后,用 Linus 最经典的话来结束本文——“ Talk is Cheap, Show me the Code!”


 Heidi Roizen女士一度是硅谷人人争相学习的典范。她曾创办自己的公司并管理了 14 年之久。后来,她担任苹果公司主管开发者关系的高级副总裁。现在,她是 DFJ Venture 的一位风投家,她还在斯坦福主讲一门名叫“企业家精神”的课程。她几乎认识硅谷的所有重要人物并且灵活地运用着自己的影响力。哈佛商学院甚至还有专门关于她的案例。
  以下是 Roizen 提出的八条原则,她正是利用这些原则来指导自己的工作、建立起广泛的人际网络并不断推动创新。这些过来人的经验对于新入行者弥足珍贵,可以作为职业生涯各个阶段发展重要的领航灯。
  1)如果你做的事情毫不费力,那就是在浪费时间
  梅琳达·盖茨曾有一次路过小女儿的房间,看着她在尝试着自己穿鞋,她女儿说:“这很难,但是我喜欢困难的事。”
  我喜欢这种态度。在你经历过很多困难时期后,你会发现渡过难关是你最美好的经历。
  成功的创业者追求一种永不止步的状态。你努力工作,超越能力的极限,不断地尝试、失败、再尝试;你每天、每周都问自己“我还能做什么更有难度的事情吗”,这时你才能理解这种劲头。
  有趣的是,很多怀有雄心壮志的人却力求消除工作中的困难。他们想平步青云,顺利到达梦想彼岸,这是不对的。”现实情况是,即使你真的轻松成功,你也会感到无聊。所以,找点困难的事情做吧。
  创业的美妙之处正在于其艰难。没有安全可言,没有稳定的收入,你必须完全靠自己。
  2)你的品德决定了你生活的基调
  做第一家公司 T/Maker 的 CEO 时,曾有一次防火洒水器故障毁掉了所有库存商品。幸运的是,大多数产品都不太值钱。更幸运的是(从另一个角度说),房东不知道货品不值钱,愿意用保险赔付一切损失。
  当时的条件确实很诱人,我们本可以收到 15 万美元的赔款。但是我们决定说出真相,因为不仅我们知道库存的价值,我们的员工也知道,如果我们决定作假,那我们怎么向员工交代。
  你要成为员工的榜样,清楚自己所做每件事的后果。如果公司领导层决定收了这笔钱,那就等于告诉员工,作假是被允许的,就好像是在说:“虚报费用是没问题的,如果想要的话把多余的设备带回家也行。”
  这看起来轻而易举,但是真正做到却不容易。你可能会想:“我可以怎么简单怎么来,我可以这么说,我可以对消费者撒谎来达成交易。”
  有时你能逃脱掉,有时却逃不掉,大多数情况你最终都是逃不掉的。
  3)你的内心比你掌握更多的信息
  你的行为决定了公司的文化基调。做有些事是为了晚上能睡个安稳觉,另一些是为了搭建良好的工作关系。当你把标准定得更高时,你会发现更容易把持自己。
  在斯坦福商学院,有一门“商业创新”课程,要求学生进行一周练习:睡前把你明天要做的一个决定写在纸上,第二天早上起来立即做决定。这个练习的目的是告诉学生直觉是如何做决定的,以及直觉能够有多么准确。
  但是科技圈的认知却朝向相反的方向发展,做决定越来越靠无尽的数据。人们认为掌握的数据越多就能作出正确的决定。对于有些事情来说,这种方法是有效的,但是并不是所有事。内心的直觉建立在多年的经验以及对于人类行为持续不断的观察上。我们甚至不知道它的具体形式。
  我在做一些艰难的决定时往往会听从直觉,尤其是涉及到人的时候——和谁工作,和谁保持联系,把谁炒鱿鱼等。每次数据指示和我想的不一样时,听从数据都会让我后悔不已。
  4)挑选团队是你要做的最重要的事情
  绝大多数公司的成败都取决于团队的质量。
  过去这些年里,Roizen 见过太多年轻的创业者犯同一个错误:他们有一个创意,开了一家公司,但是当需要聘用管理人员的时候,他们不想找一个比他们更懂的人来做。他们不想被威胁,所以就找跟他们同龄,和他们懂得一样多的,找自己信任的熟人。这种做法听起来不错,但是同时,创业者因为怕被压制或大权旁落而错失了许多专业人才。
  5)如果你希望成为团队内最聪明的人,那你会建立一支平庸的队伍。
  你真的希望你负责销售的副总比你还不懂销售?你想要你的 CFO 不如你懂财务?当然不是。你应该去冒险,找到正确的人,并且信任他们。你的工作是激励这些人,并确保他们和睦相处。
  我的目标永远是成为团队里最笨的人,我希望我的身边都是些真正有才华的人。这才是让人兴奋的事情,我们才能完成最艰难的挑战。
  6)生活真的是反复无常的
  倒霉事儿会发生在你头上,你会失败,失控的事情会发生,你需要接受现实。在这种境遇下,你如何挺过去,坚持到成功呢?一条建议:把事情都想成一团糟。
  快乐的关键是降低你的预期。这并不是说你不应该追求自己的目标,这意味着你应该对前进路上的不完美做好准备。比如说,Roizen 出国旅行时会设想行李丢失、航班晚点或是租的车没有按时到达等各种情况。我想到了各种事情最坏的结果,那么当坏事真的发生时,我也不会感到难过。我在随身行李中放了换洗衣服,我在落地两小时内没有安排任何会议。我预期很低,如果坏事没有发生,那我就会很欣喜。95%的压力都是自找的。
  Roizen 想起她认识的一位总是严谨制定计划的创业者,每一件事都计划得滴水不漏,但是实际上事情从没有完全按计划施行过。
  如果你期待每件事都顺利进行,坏事就可能会落到你身上。生活有时候可能很遭,当这种情况真的发生时,整顿行装,继续前行。
  如果你跌倒了却爬不起来,那么你的余生也将一事无成。
  记住,就像硬币的两面一样,生活的跌宕也可能带来好事。当机会来临时,不要错过,你不知道接下来会发生什么。如果你得到 3 个不错的工作 offer,不要总想着选个最正确的。
  可能你选了一个不太好的工作,业绩不好,你被炒了,但以后可能还有更好的工作机会。而且在这份工作中学到的经验教训在另一份更稳定的工作中是得不到的。
  Roizen 回忆起自己不久前看的一本书,书中说在问到过去 5 年发生过的最好和最坏的事情是什么时,大部人说出的都是同一件事,甚至包括离婚、得癌症或是失业等。
  但当你接着问他什么是促使生活向好的方向发展的事情时,往往就是这些坏事。有时,接受生活的起伏,你会发现一些伪装起来的好事。
  7)充分利用时间
  你所拥有的最重要的东西就是你的时间,因为你不能创造更多时间。
  你可以用钱或他人的帮助来节约你的时间,但是,最终你还是会用光自己的时间。所以,你需要对自己如何利用时间了如指掌。很多人不知道每件事情花了多少时间,他们有 1000 封未回复的邮件,却还说不知道怎么处理。解决方法就是每天安排的工作不要超过 5 个小时,留出 3 个小时回邮件,打电话,阅读,获取最新消息。当别人说没时间时,我会说,你当然有时间,但你用来做别的事情了。
  想想所有需要花时间的事情,开始时对它们一视同仁。你要明白,睡觉是花时间的,阅读也是花时间的。搞清楚你喜欢做什么,什么能够最大限度的拓展你的能力,然后重新规划时间,把时间花在正确的事情上。理想的情况是,你能留出一些时间用来思考和睡觉,但是 Roizen 说有时候也确实很难实现。
  在工作上花更多的时间就意味着陪家人和朋友的时间少了。人们有一种幻觉认为关系和交流不需要用时间来维系,但是实际上不是这样的。你可能没法完全平衡你的时间,但是至少试着来。
  如果你不给你自己留时间,那就没时间做些正确的事,总会有各种突发情况。
  8)20-40-60 法则
  演员 Shirley MacLaine 最早提出了这个法则,主要内容是:20 岁时,你总在担心别人是怎么看你的;40 岁时你觉醒了,我才不管别人是怎么想的。60 岁时你才发现,根本没人管你。这个法则的核心理念就是:从一开始就没有人想着你。
  当然,这既是好事儿,也是坏事。坏处在于没有人在一直关心你好不好,挣多少钱,你对工作和人际关系是否满意。“你需要为自己着想,如果你在做一件不喜欢的工作,你需要自己做出决定是否换个工作,你不能在办公室等着别人帮你做决定。
  你的老板不会想着你,你的同事没有想着你,你需要替自己着想。
  这听起来令人难以接受。有些人花很多时间思忖别人是怎么看待自己的,深受折磨,其实完全没必要这样。
  我曾经也总是顾虑长途飞行后穿着不合时宜的鞋和褶皱的套装时开会是什么状态。我会很担心人们看到我连自己都收拾不利索会怎么看我。但是,有一次开会时,我发现,并没有人认为“虽然这个家伙很聪明,但是他衣冠不整,这人肯定不行”。
  人们总是为一些犯过的小错误折磨自己,在会上说错话,叫错人名等。你可能浪费几个星期的时间来懊恼,导致工作效率低下。如果你发现自己是这样的,那么请记住:没有人像你自己一样关注你。所以就不要担心太多了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值