转自:http://hellojava.info/?p=458

在上篇《架构师画像》的文章中提到了自己在系统设计上犯过的一些错,觉得还挺有意义的,这篇文章就来回顾下自己近八年来所做的一些系统设计,看看犯的一些比较大的血淋淋的错误(很多都是推倒重来),这八年来主要做了三个基础技术产品,三个横跨三年的大的技术项目(其中有两个还在进行中),发现大的错误基本集中在前面几年,从这个点看起来能比较自豪的说在最近的几年在系统设计的掌控上确实比以前成熟了很多。

第1个错
在设计服务框架时,我期望服务框架对使用者完全不侵入,于是做了一个在外部放一个.xml文件来描述spring里的哪些bean发布为服务的设计,这个版本发布后,第一个小白鼠的用户勉强在用,但觉得用的很别扭,不过还是忍着用下去了,到了发布的时候,发现出现了两个问题,一是这个xml文件研发也不知道放哪好,所以到了发布的时候都不知道去哪拿这个xml文件。
这个设计的关键错误就在于在设计时没考虑过这个设计方式对研发阶段、运维阶段的影响,后来纠正这个错误的方法是去掉了这个xml文件,改为写了一个Spring FactoryBean,用户在spring的bean配置文件中配置下就可以。
因此对于一个架构师来说,设计时在全面性上要充分考虑。

第2个错
服务框架在核心应用上线时,出现了前端web应用负载高,处理线程数不够用的现象,当时处理这个故障的方式是回滚了服务框架的上线,这个故障排查了比较长的时间后,查到的原因是服务框架用的JBoss Remoting在通信时默认时间是60s,导致一些处理速度慢的请求占据了前端web应用的处理线程池。
上面这里故障的原因简单来说是分布式调用中超时时间太长的问题,但更深层次来思考,问题是犯在了设计服务框架时的技术选型,在选择JBoss-Remoting时没有充分的掌握它的运行细节,这个设计的错误导致的是后来决定放弃JBoss-Remoting,改为基于Mina重写了服务框架的通信部分,这里造成了服务框架的可用版本发布推迟了两个多月。
因此对于一个架构师来说,在技术选型上对技术细节是要有很强的掌控力的。

第3个错
在服务框架大概演进到第4个版本时,通信协议上需要做一些改造,突然发现一个问题是以前的通信协议上是没有版本号的,于是悲催的只能在代码上做一个很龌蹉的处理来判断是新版本还是老版本。
这个设计的错误非常明显,这个其实只要在最早设计通信协议时参考下现有的很多的通信协议就可以避免了,因此这个错误纠正也非常简单,就是参考一些经典的协议重新设计了下。
因此对于一个架构师来说,知识面的广是非常重要的,或者是在设计时对未来有一定的考虑也是非常重要的。

说到协议,就顺带说下,当时在设计通信协议和选择序列化/反序列化上没充分考虑到将来多语言的问题,导致了后来在多语言场景非常的被动,这也是由于设计时前瞻性的缺失,所谓的前瞻性不是说一定要一开始就把未来可能会出现的问题就解掉,而是应该留下不需要整个改造就可以解掉的方法,这点对于架构师来说也是非常重要的。

第4个错
在服务框架切换为Mina的版本上线后,发布服务的应用重启时出现一个问题,就是发现重启后集群中的机器负载严重不均,排查发现是由于这个版本采用是服务的调用方会通过硬件负载均衡去建立到服务发布方的连接,而且是单个的长连接,由于是通过硬件负载均衡建连,意味着服务调用方其实看到的都是同一个地址,这也就导致了当服务发布方重启时,服务调用方重连就会集中的连到存活的机器上,连接还是长连,因此就导致了负载的不均衡现象。
这个设计的错误主要在于没有考虑生产环境中走硬件负载均衡后,这种单个长连接方式带来的问题,这个错误呢还真不太好纠正,当时临时用的一个方法是服务调用方的连接每发送了1w个请求后,就把连接自动断开重建,最终的解决方法是去掉了负载均衡设备这个中间点。
因此对于一个架构师来说,设计时的全面性要非常的好,我现在一般更多采用的方式是推演上线后的状况,一般来说在脑海里过一遍会比较容易考虑到这些问题。

第5个错
服务框架在做了一年多以后,某个版本中出现了一个严重bug,然后我们就希望能通知到用了这个版本的应用紧急升级,在这个时候悲催的发现一个问题是我们压根就不知道生产环境中哪些应用和机器部署了这个版本,当时只好用一个临时的扫全网机器的方法来解决。
这个问题后来纠正的方法是在服务发布和调用者在连接我们的一个点时,顺带把用的服务框架的版本号带上,于是就可以很简单的知道全网的服务框架目前在运行的版本号了。
因此对于一个架构师来说,设计时的全面性是非常重要的,推演能起到很大的帮助作用。

第6个错
服务框架这种基础类型的产品,在发布时会碰到个很大的问题,就是需要通知到使用者去发布,导致了整个发布周期会相当的长,当时做了一个决定,投入资源去实现完全动态化的发布,就是不需要重启,等到做的时候才发现这完全就是个超级大坑,最终这件事在投入两个人做了接近半年后,才终于决定放弃,而且最终来看其实升级的问题也没那么大。
这个问题最大的错误在于对细节把握不力,而且决策太慢。
因此对于一个架构师来说,技术细节的掌控非常重要,同时决策力也是非常重要的。

第7个错
服务发布方经常会碰到一个问题,就是一个服务里的某些方法是比较耗资源的,另外的一些可能是不太耗资源,但对业务非常重要的方法,有些场景下会出现由于耗资源的方法被请求的多了些导致不太耗资源的方法受影响,这种场景下如果要去拆成多个服务,会导致开发阶段还是挺痛苦的,因此服务框架这边决定提供一个按方法做七层路由的功能,服务的发布方可以在一个地方编写一个规则文件,这个规则文件允许按照方法将生产环境的机器划分为不同组,这样当服务调用方调用时就可以做到不同方法调用到不同的机器。
这个功能对有些场景来说用的很爽,但随着时间的演进和人员的更换,能维护那个文件的人越来越少了,也成为了问题。
这个功能到现在为止我自己其实觉得也是一直处于争议中,我也不知道到底是好还是不好…
因此对于一个架构师来说,设计时的全面性是非常重要的。

第8个错
服务框架在用的越来越广后,碰到了一个比较突出的问题,服务框架依赖的jar版本和应用依赖的jar版本冲突,服务框架作为一个通用技术产品,基本上没办法为了一个应用改变服务框架自己依赖的jar版本,这个问题到底怎么去解,当时思考了比较久。
可能是由于我以前OSGi这块背景的原因,在设计上我做了一个决定,引入OSGi,将服务框架的一堆jar处于一个独立的classloader,和应用本身的分开,这样就可以避免掉jar冲突的问题,在我做了引入OSGi这个决定后,团队的1个资深的同学就去做了,结果是折腾了近两个月整个匹配OSGi的maven开发环境都没完全搭好,后来我自己决定进去搞这件事,即使是我对OSGi比较熟,也折腾了差不多1个多月才把整个开发的环境,工程的结构,以及之前的代码基本迁移为OSGi结构,这件事当时折腾好上线后,效果看起来是不错的,达到了预期。
但这件事后来随着加入服务框架的新的研发人员越来越多,发现多数的新人都在学习OSGi模式的开发这件事上投入了不少的时间,就是比较难适应,所以后来有其他业务问是不是要引入OSGi的时候,我基本都会建议不要引入,主要的原因是OSGi模式对大家熟悉的开发模式、排查问题的冲击,除非是明确需要classloader隔离、动态化这两个点。
让我重新做一个决策的话,我会去掉对OSGi的引入,自己做一个简单的classloader隔离策略来解决jar版本冲突的问题,保持大家都很熟悉的开发模式。
因此对于一个架构师来说,设计时的全面性是非常重要的。

第9个错
服务框架在用的非常广了后,团队经常会被一个问题困扰和折腾,就是业务经常会碰到调用服务出错或超时的现象,这种情况通常会让服务框架这边的研发来帮助排查,这个现象之所以查起来会比较复杂,是因为服务调用通常是多层的关系,并不是简单的A–>B的问题,很多时候都会出现A–>B–>C–>D或者更多层的调用,超时或者出错都有可能是在其中某个环节,因此排查起来非常麻烦。
在这个问题越来越麻烦后,这个时候才想起在09年左右团队里有同学看过G家的一篇叫dapper的论文,并且做了一个类似的东西,只是当时上线后我们一直想不明白这东西拿来做什么,到了排查问题这个暴露的越来越严重后,终于逐渐想起这东西貌似可以对排查问题会产生很大的帮助。
到了这个阶段才开始做这件事后,碰到的主要不是技术问题,而是怎么把新版本升级上去的问题,这个折腾了挺长时间,然后上线后又发现了一个新的问题是,即使服务框架具备了Trace能力,但服务里又会调外部的例如数据库、缓存等,那些地方如果有问题也会看不到,排查起来还是麻烦,于是这件事要真正展现效果就必须让Trace完全贯穿所有系统,为了做成这件事,N个团队付出了好几年的代价。
因此对于一个架构师来说,设计时的全面性、前瞻性非常重要,例如Trace这个的重要性,如果在最初就考虑到,那么在一开始就可以留好口子埋好伏笔,后面再要做完整就不会太复杂。

第10个错
服务的发布方有些时候会碰到一个现象是,服务还没完全ready,就被调用了;还有第二个现象是服务发布方出现问题时,要保留现场排查问题,但服务又一直在被调用,这种情况下就没有办法很好的完全保留现场来慢慢排查问题了。
这两个现象会出现的原因是服务框架的设计是通过启动后和某个中心建立连接,心跳成功后其他调用方就可以调用到,心跳失败后就不会被调到,这样看起来很自动化,但事实上会导致的另外一个问题是外部控制上下线这件事的能力就很弱。
这个设计的错误主要还是在设计时考虑的不够全面。
因此对于一个架构师来说,设计时的全面性非常重要。

第11个错
在某年我和几个小伙伴决定改变当时用xen的模式,换成用一种轻量级的“虚拟机”方式来做,从而提升单机跑的应用数量的密度,在做这件事时,我们决定自己做一个轻量级的类虚拟机的方案,当时决定的做法是在一个机器上直接跑进程,然后碰到一堆的问题,例如从运维体系上来讲,希望ssh到“机器”、独立的ip、看到自己的系统指标等等,为了解决这些问题,用了N多的黑科技,搞得很悲催,更悲催的是当时觉得这个问题不多,于是用一些机器跑了这个模式,结果最后发现这里面要黑科技解决的问题实在太多了,后来突然有个小伙伴提出我们试用lxc吧,才发现我们之前用黑科技解的很多问题都没了,哎,然后就是决定切换到这个模式,结果就是线上的那堆机器重来。
这个设计的主要错误在于知识面不够广,导致做了个不正确的决定,而且推倒重来。
因此对于一个架构师来说,知识面的广非常重要,在技术选型这点上非常明显。

第12个错
还是上面这个技术产品,这个东西有一个需求是磁盘空间的限额,并且要支持磁盘空间一定程度的超卖,当时的做法是用image的方式来占磁盘空间限额,这个方式跑了一段时间觉得没什么问题,于是就更大程度的铺开了,但铺开跑了一段时间后,出现了一个问题,就是经常出现物理机磁盘空间不足的报警,而且删掉了lxc容器里的文件也还是不行,因为image方式只要占用了就会一直占着这个大小,只会扩大不会缩小。
当时对这个问题极度的头疼,只能是删掉文件后,重建image,但这个会有个要求是物理机上有足够的空间,即使有足够的空间,这个操作也是很折腾人的,因为得先停掉容器,cp文件到新创建的容器,这个如果东西多的话,还是要耗掉一定时间的。
后来觉得这个模式实在是没法玩,于是寻找新的解决方法,来满足磁盘空间限额,允许超卖的这两需求,最后我们也是折腾了比较长一段时间后终于找到了更靠谱的解决方案。
这个设计的主要错误还是在选择技术方案时没考虑清楚,对细节掌握不够,考虑的面不够全,导致了后面为了换掉image这个方案,用了极大的代价,我印象中是一堆的人熬了多次通宵来解决。
因此对于一个架构师来说,知识面的广、对技术细节的掌控和设计的全面性都非常重要。

第13个错
仍然是上面的这个技术产品,在运行的过程中,突然碰到了一个虚拟机中线程数创建太多,导致其他的虚拟机也创建不了线程的现象(不是因为物理资源不够的问题),排查发现是由于尽管lxc支持各个容器里跑相同名字的账号,但相同名字的账号的uid是相同的,而max processes是限制在UID上的,所以当一个虚拟机创建的线程数超过时,就同样影响到了其他相同账号的容器。
这个问题我觉得一定程度也可以算是设计问题,设计的时候确实由于对细节掌握的不够,考虑的不全导致忽略了这个点。
因此对于一个架构师来说,对技术细节的掌控和设计的全面性都非常重要。

第14个错
在三年前做一个非常大的项目时,项目即将到上线时间时,突然发现一个问题是,有一个关键的点遗漏掉了,只好赶紧临时讨论方案决定怎么做,这个的改动动作是非常大的,于是项目的上线时间只能推迟,我记得那个时候紧急周末加班等搞这件事,最后带着比较高的风险上了。
这个问题主要原因是在做整体设计时遗漏掉了这个关键点的考虑,当时倒不是完全忽略了这个点,而是在技术细节上判断错误,导致以为不太要做改动。
因此对于一个架构师来说,对技术细节的掌控是非常重要的,这里要注意的是,其实不代表架构师自己要完全什么都很懂,但架构师应该清楚在某个点上靠谱的人是谁。

转载自:http://mp.weixin.qq.com/s?__biz=MzA5OTAyNzQ2OA==&mid=401368207&idx=1&sn=6bb2b3fe6ece8f41e7f2e2a54f52e46c&scene=1&srcid=0113d03chnJkdvhm86dmBSyW#rd
2016-01-13 杨润青 译  Docker

在这篇文章中我们将会探讨2个主流的Docker编排框架:AWS的ECS(Elastic Container Service)和Google的Kubernetes。

3个月前,我们在nanit.com希望选择一个合适的Docker编排框架,ECS成为了我们的首选,毕竟,我们对AWS的服务较为熟悉,并且我们的基础设施都是建立在AWS的。经过一段时间的测试,我们发现ECS并不成熟,缺少一些我们需要的关键功能,因此我们开始尝试其他的框架:Kubernetes。令人意外的是,Kubernetes非常成熟,几乎支持我们需要的所有功能。对于我们来说,Kubernetes在ECS的主场完胜了ECS。接下来,就让我们一起来看看Kubernetes赢在哪些方面。

注意:ECS一直在更新,我们会尽可能的跟进这些内容,但部分内容可能被忽略了,希望读者不要介意。

构建集群(Cluster Setup)

ECS:为了启动一个ECS集群,用户需要设置一个Auto Scaling Group。用户可以编辑user-data来将EC2实例添加到指定的ECS集群上。当ASG被设置,实例启动之后,用户可以在ECS控制台看到这部分内容。现在,用户可以开始进行task-definition,方式类似于Docker-compose。

Kubernetes:想要在AWS上启动一个Kubernetes,用户需要先启动一个具有一定权限的EC2实例(通过IAM)。这将会创建多个AWS constructs来支持你的集群:VPC、ASG、一些安全组(Security Groups)和一个Kubernetes主实例。集群需要几分钟来启动,之后用户就能够在上面运行自己的容器。

比较结果:使用这两种框架来启动一个集群都非常的简单和友好。

启动基础服务(Basic Service Setup)

我们的任务是启动一个Nginx 镜像,并且让其他人能够访问这个Web服务。

ECS:首先,我们需要创建一个ELB(Elastic Load Balancer),它负责80端口的转发。然后,我们需要创建一个task-definition,它负责在80端口上启动一个Docker镜像。最后,需要创建一个Service,它会显示出有多少实例会同时运行。我们需要将它绑定到我们之前创建的ELB上。

Kubernetes:首先需要创建一个Replication Controller,它会显示出我们希望运行的Docker镜像和有多少镜像会同时运行。之后,我们需要创建一个Service object,这会启动一个ELB并且将ELB的流量转发到对应的容器上。

比较结果:Kubernetes的方式更舒服一些,更简洁。用户并不需要手工启动或者管理ELB。Kubernetes会完全负责管理:当用户创建了一个service,一个ELB会自动创建;当用户删除了一个service,它会自动从AWS上删除。

服务发现(Service Discovery)

当你使用了微服务架构和Docker,一个好的服务发现解决方案是至关重要的。Docker容器总是在不同虚拟机中迁移,用户必须有一个可靠的方法来发现在集群内和集群外的服务。

ECS:ECS并没有提供任何服务发现的解决方案。我能想到的最好方法就是构建一个内部加载平衡器(internal load balancer),并且将每一个service附加到一个平衡器上。平衡器的host name不会被改变,然后你就能够利用这个host name来作为服务的端点。其他的方法还有集成一个外部的程序,比如Consul。

Kubernetes:我认为这是Kubernetes的亮点之一。Kubernetes内置了一个完全的解决方案。它是一个插件,因此用户可以选择是否使用,但我强烈建议使用。它能够和namespace一起很好的工作。简单来说,当你创建了一个Kubernetes服务,比如说叫做redis,你就能够在集群的任何地方引用redis这个名字,即便是跨虚拟机。这就像是让docker网络跨越了特定的虚拟机,连通了整个集群。Namespaces允许你将多个服务归纳到一个具有逻辑的组中。现在假设我们有两个命名空间,分别是production和staging,他们都包含有一个redis的服务。一个在production命名空间下的容器可以通过redis来引用在production命名空间下的redis服务,同样的,在stagin命名空间下的容器也能通过redis来引用到位于stagine命名空间下的redis服务。这种自动化识别使得用户不需要花费时间去配置信息就能够构建一个隔离的环境,并且你可以随意在所有的命名空间中使用redis来引用对应的服务,接下来kunernetes会为你自动解析它们。

比较结果:毫无疑问,Kubernetes小胜一局。使用Kubernetes,用户完全不用关心服务发现的事情,全部交给Kubernetes来做就好了:)

部署(Deployments)

当我们升级一个服务的时候,即便还在部署,我们也想要确保它百分之百能用。我们的测试包括一个简单的NginX服务和一些简单的静态网页。我们启动了一个并发为30个请求的负载测试,并且在负载测试期间,我们会对该服务进行升级。

在部署期间,我们发现ECS丢失了比Kubernetes更多的请求。其中,Kubernetes丢失了0-2个请求,而ECS丢失了9-14个。

比较结果:说实话,我对ECS非常的失望。同样,我也对Kubernetes表示失望,但是它至少比ECS好多了。值得注意的是,Kubernetes 1.1.1版本应该会对轮询升级机制(rollong update mechanism)进行改善,还有一些其他的系统系能提升,这些改进都会使得这些数字变得更好看。

持久卷(Persistent Volumes)

我们经常需要挂载一些持久性的文件系统到一个指定的容器上,MySQL就是一个典型的例子。

ECS:ECS支持Docker原生的解决方案——用户可以启动一个数据容器,然后使用volumes-from命令来挂载它到其他容器上。就拿MySQL来看,你首先需要设置一个mysql-data容器,这个容器仅仅拥有一个数据卷。然后设置另外一个mysql-db容器,这个容器使用volumes-from命令来挂载之前创建的数据卷容器。这个方法看起来不错,但是它是host-sepicific的,这意味着你的mysql-db容器不能够在主机之间移动。你必须指定mysql-db容器在哪一个主机上运行,以此来防止容器被重新分配到其他主机上,最终失去了持久性。

Kubernetes:除了从一个指定的主机上挂载数据卷,Kubernetes还提供了一个选项:挂载一个EBS(Elastic Book Store)数据卷。这意味着一个容器的持久性存储可以在多个不同的虚拟机之间保留。你再也不需要强制你的MySQL容器必须运行在哪一个具体的虚拟机上。

注意:EBS同一时间只能被一个虚拟机挂载,这意味着如果有一个服务,它有两个运行在不同虚拟机的容器,他们将不能够挂载和共享这个EBS。

比较结果:即便Kubernetes的EBS挂载有一定的限制,但它依旧非常的独特和有用。

健康检查(Health-Checks)

确保拥有足够的服务容量是高可用性和冗余性的核心思想。健康检查就是用来确保服务不仅仅是运行的,并且它们还是健康和可操作的。

ECS:ECS使用ELB(Elastic Load Balancer)健康检查,这种方式有三个主要的缺点:

  1. ELB健康检查仅仅限于HTTP/TCP检查
  2. 如果你想要对一个不开放TCP端口的服务进行检查,这是不行的。仅仅是为了能够进行健康检查,你就必须运行一个HTTP/TCP服务器。
  3. 即便你拥有一个支持HTTP/TCP的服务,你还需要创建一个ELB,并将它绑定到这个服务上,这样才能进行健康检查。

Kubernetes:除了基于HTTP/TCP的健康检查,Kubernetes还提供了一种叫做Exec的方式。Exec可以让用户在容器中运行命令。如果命令结束,并且返回0则表示这个服务是健康的,否则这个服务很可能是不健康的,它会被其他的实例所替换。

比较结果:Kubernetes的方式更灵活,更简单配置。用户并不需要去启动一个冗余的HTTP/TCP服务器仅仅为了进行健康检查,并且即便服务没有绑定ELB,你也可以对它们进行健康检查。

端口管理(Port Management)

从我们的上篇文章中可以看出,端口管理在Docker中是比较困难的。我们想通过一个简单的例子来说明Kubernetes如何比ECS更优雅的解决了这个问题。我们拥有一台虚拟机和两个监听80端口的网站。我们不能够在同一个虚拟机上开2个80端口,因此我们需要寻找一个方法来解决这个问题。

ECS:用户必须手工确定两个服务没有使用同一个端口。我们只有一台虚拟机,因此只能运行一个开放80端口的容器。当我们想要开启第二个开放80端口的容器时,这是不行的,因为我们没有多余的虚拟机了。也就是说,能够开放多少个x端口的服务取决于拥有多少个虚拟机。在小型集群中,这是非常容易满足的条件,但是当你的服务数量变得越来越多时,这将成为一个头疼的问题,因为当你想要扩充容器时,你必须确认你还有足够的端口。

Kubernetes:Kubernetes非常优雅的解决了这个问题。它为每一个虚拟机上的容器都分配了一个随机的端口。然后它创建了2个ELB,一个将80端口转发到容器A的随机端口上,另外一个转发到容器B的随机端口上。一个内部的路由机制会负责将数据包转发到对应容器端口。

比较结果:Kubernetes使用虚拟端口的方式代替绑定原始端口的方法,很好的解决了这个头疼的问题。

记录(Logging)

没有什么系统不需要记录功能。

我从没有想过记录会成为一个大问题,但能够为你解决问题令我非常的高兴,即便这个问题非常简单。我们之前提到Kubernetes提供了一个服务发现的扩展功能,在这里,我想说的是记录的扩展功能。它含有两个不同的记录和度量收集(metric collection)的机制。第一种是著名的ELK方法,ELK会收集容器的所有记录,并且能够让用户通过Kibana接口来查询和可视化这些记录。第二种是InfluxDB,它使用Grafana作为可视化工具来查询系统信息,如CPU和内存使用情况。

比较结果:Kubernetes的扩展功能更胜一筹。当然,你会说我并不需要这些扩展,系统也能很好工作,但是,它们效果如此之好,并且能适用于99%的用例,为什么不使用呢?ECS并没有提供内置的记录功能,用户想要集成一个进去并不是很困难,但是这些并不能和Kubernetes提供的功能相提并论。

未知的云平台(Cloud Agnostic)

其实,Kubernetes和ECS之间并不存在竞争:)

ECS会专注于AWS平台,如果你已经在ECS上构建了你的基础架构,当你想要转移到其他云平台时,你将会遇到很多困难。

Kubernetes适用于多个云平台。你可以在AWS,Google Cloud,微软的ZURE,Rackspace等等上运行你的集群,并且运行效果或多或少都是相同的。在这里,或多或少指的是有一些功能只有部分云供应商提供。你必须确认你选择的新供应商能够支持Kubernetes中使用的功能,至少确保迁移是可能的。

开源软件(OSS)

Kubernetes是开源的项目,而ECS不是。这意味着,所有的一切,从源代码到未来的发展路线都是对你开放的。发现了漏洞?你可以创建一个issue或者直接提交一个pull 请求来修复它。新的功能会被添加到每一个新版本,其中的贡献人数和pull请求是惊人的。

ECS有着不同的性质,我不能够在网上找到关于它未来发展路线的规划。你不能够获得一个漏洞和issue的列表,你必须深入到论坛上去寻找想要的答案。并且你寻找的答案往往都是缺乏实际的,并不能够提供任何帮助(https://forums.aws.amazon.com/message.jspa?messageID=664865#664865)。也许这仅仅是因为我个人的糟糕经历,但是不管怎么说,这都是令人烦躁和失望的。

比较结果:就我个人而言,我更喜欢开源软件。我喜欢Kubernetes的开放性,每个人都能够参与讨论和贡献代码。我相信社区的力量会给我们带来一个更好的产品。

多可用区域(Multi-AZ)

当谈论到Kubernetes时,有一件事情困扰着我:它不支持AWS上的多可用区域集群(multiple availability-zones cluters)。这意味着所有EC2实例都集中在一个AZ上,这使得你的集群很可能会遭受到中断问题。

ECS有对Multi-AZ有很好的支持。

比较结果:在Kubernetes的issue上,已经有一些工作正在进行。我十分确定下个版本会很好的得到改善。因此ECS在这一点上的胜利并不会长久。

总结

很多公司都开始使用Doker作为他们的主要基础设置,传递机制(delivery mechanism)和编排框架(orchestration frameworks)成为了系统的核心,并且影响着我们开发,迁移,运行,升级的方式。当我想要比较ECS和Kubernetes时,我找不到类似的文章。所以我认为把我们的经验公布出来非常的重要,这样其他人能够站在我们的肩膀上看的更远。

对于nanit.com来说,Kubernetes毫无疑问获得了胜利。如果你有任何的异议,请告诉我理由,我非常想要知道这些内容:)

声明:本文没有任何褒贬或者对比各种编程语言的意思,请不要做无谓的语言之争。

我们这些80后程序员大部分人都是从delphi,C,C++开始接触编程的,然后等到了大学或者工作,因为生计或者其他种种原因,大家从事的行业开始有了变化,从而导致开发语言也有了一些变化,一些做后端的,开始使用Java,C++等等,一些做前端的开始用php,js等等。

然而,当我们用一门语言很久之后,就会对这门语言有了更多更深刻的了解,优点缺点、解决方案等等,而且大部分人会有一中喜新厌旧的心里,再加上市面上的新语言、新特性层出不绝,特别是看到那些你曾经花了很大精力想了各种奇淫技巧解决了一个问题,而在某些新语言中这只是一个普通特性,所以大家难免会心里痒痒,“我要不要学这个新语言,我要不要在工作环境中使用这个语言?”

这篇文章我就两方面讲下什么时候需要学一门编程语言,一个是学新语言是否真的对你的开发工作有帮助,一个是你的生活工作环境中是否允许你用新的语言。因为我是从事游戏服务器开发,主要语言是C++,而我打算学习C#,以下的内容就用这两门语言做例子。

学新语言是否真的对你的开发工作有帮助?

我们学习任何东西都是建立在有需要的情况下,如果知识不能转化成财富,估计很少有人会去上学。所以学一门新的编程语言是否对我们有帮助是很重要的,不过如果你只是单纯的兴趣,那倒是无所谓。学习新语言的原因基本分为下面几种:

  • 现在的语言太复杂,很多特性非常老,实现功能起来很纠结,需要一门简单实用的新语言快速解决问题,新语言简洁高效,特性强大
  • 现在的语言需要大量的第三方库,而新语言自带平常开发的大部分库
  • 现在的语言开发效率太低,新语言分分钟撸一个功能模块出来

上面的几点,总结起来就是现在的语言用起来很不爽,需要新语言来帮助我提高效率。

简单高效一直是现代编程语言的核心思想,通过C++ 11,14,17标准我们很明显的看出来,C++当初为了兼容C(挖C程序员的墙角),做了很多现在看来很纠结的东西,而新标准就是在改善这块东西。我们团队维护的NFrame C++版本,到了现在又开始用C#语言做一个,核心思想没变,只是单纯的换个语言,现在核心功能已经换完了,只花了两周多的时间,一个库都没依赖,只依赖了.Net Framework,杂七杂八架起来只有10M多,而C++版本库解压后有近1G,从开发和维护成本上来说,都是C#更胜一筹。再加上现在MS本身已经开始支持跨平台了,或者mono,跨平台根本不是问题。

这个例子可以看出,新的语言C#确实提高了我们的开发效率,而C#的Task等等特性和内容,已经将我们再C++上纠结的Actor模式完全替代了,让我们可以安心做功能设计,而不是纠结语言层面的实现问题。

而且新语言一般都是通杀的,web,UI,back-end等,基本都支持,C#,js,Java都是前后端通杀,适合大部分领域和行业。

//TODO

 

生活工作环境中是否允许你用新的语言?

俗话说兴趣是最好的老师,当你对某个事物有了兴趣之后,自然就有学习的动力了。但是我们都不是一个人在战斗,多多少少都会有合作的同事、朋友,小到自己的简单开源项目,大到公司的大项目,所以工作生活中都是多个人在合作,做任何事情都不能一意孤行,自己喜欢某种编程语言就大用特用,毕竟团队整体的效率才是执行力,现在已经不是个人英雄主义的时代了,保持合作交流才能有更大的进步。团队做出来的东西才是外面比较看重的,技术不是决定性因素,而项目产品才是提升自己价值的东西,离开团队这个平台,一身是铁打几根钉子?面面俱到方能做到完美。

 

暂时想到的就是这么多了,大家可以继续补充讨论。