为什么微服务从未被技术雷达“采纳”?

如今,微服务在许多组织中发挥着重要作用。自从James Lewis和Martin Fowler发表了那篇开创性的文章后,微服务也随之声名鹊起。此后,Sam Newman也撰写了相关著作并举办了许多讲座,ThoughtWorks、Netflix和Google的人,还有许多其他组织和个人也纷纷发表文章,进一步推动了微服务的发展势头。微服务很快就进入了ThoughtWorks技术雷达的Trial(试验)环,但一直以来,微服务都未进入Adopt(采纳)环。这篇文章便是想探讨一下,为什么微服务一直没有为技术雷达所“采纳”。

Adopt环有意把标准设置得很高

首先,一起回想一下雷达上“试验”环和“采纳”环的定义。“试验”意味着相应技术已经可以供企业在自己的系统中进行尝试。表示我们在已经或多或少地将该技术投入生产,而且相信该技术是稳定的,知道如何以及在何处使用该技术。而进入雷达“采纳”环意味着,我们认为在适用的情况下这种技术是首选解决方案。例如,对于数据库,Neo4J就是一种进入了“采纳”环的图形数据库。这并不意味着所有数据都应该放入图形数据库中,而是意味着当你想使用图形数据库,Neo4J就是理想之选。

考虑到上述定义,我们为何不将微服务或微服务架构放入“采纳”环?毕竟,微服务经常作为各种会议和文章热议的话题,也有越来越多的组织正在转向采用这种架构风格,ThoughtWorks团队已经成功地将微服务用于许多项目。

我们未将微服务放入Adopt环,有多种原因。一部分原因在于“采纳”环的定义,另一部分原因则在于微服务本身。我们先从技术雷达的特定问题谈起。

将某种技术放入“采纳”环是一种非常强烈的表态。我们不希望在考虑做出这种建议时,存在太多让我们举棋不定的因素。将某种技术放入“采纳”环意味着,我们确信对于一些显而易见的情况来说,采用这种技术是正确的选择。在考虑微服务时,虽然它有一些明显的优点,但同时存在成本问题。对成本与效益的权衡因组织而异;组织的成熟度、领域和其他因素可能会影响可用的开发资源。从这个方面来讲,我们不能做出采用微服务的建议,技术雷达对于“采纳”的定义不应当模棱两可。

更重要的是,另一方面,将某种技术放入“采纳”环就要求,这项技术应该可以在各种成熟度范围内的客户和一般企业之中普遍采用。例如,如果某种技术适用于初创企业,但不适用于大型企业,就不应该放入“采纳”环,一个突出的例子是技术公司广泛应用的分布式版本控制系统。我们没有将这种系统纳入到“采纳”环,因为当时许多企业仍在努力采用基本的源控制。我们认为从一无所有到分布式版本控制的飞跃太大了,不能做出采用该系统的强烈建议。我们最终还是将Github放入了Adopt环中,但那是几年之后了。

并非所有组织都适合采用微服务

最后,正如Martin Fowler在一篇关于微服务的文章中所指出的,在考虑采用微服务之前,需要在持续交付和基础设施自动化实践等方面达到一定的成熟度(也许不需要太高)。然而,对于许多组织而言,要达到这种成熟度仍然力所难及。微服务会增加操作负担,因为有更多东西需要监控和生成警报,还有更多东西需要部署。在这方面,全面的自动化和持续交付实践至关重要。

此外,微服务架构还具有一些在单体式应用程序中完全不可能出现的错误模式。微服务系统本质上是分布式的,业务流程通常通过多项微服务的交互来完成。在单体式应用程序中,这些业务流程通常在同一流程边界内执行,从而可以执行传统事务并能确保全部执行或全部不执行。虽然我们可以为所有这些问题提供解决方案,但不可忽视的是,微服务方法确实会引入这些问题并需要处理。因此,需要在微服务方法增加的灵活性和单体式方法的简单性之间进行权衡(这种权衡很常见),尤其是在单体式应用程序结构完善的情况下,从灵活性中获益不多的应用程序不适宜采用微服务架构。

微服务架构的关键设计决策是在服务之间设置边界。虽然有界上下文肯定能为设置适当边界位置提供有效指导,但是仍然存在选择,而选择错误会使系统变得更复杂。对于某个新领域而言,边界的设定会比较模糊,因此在未进一步明确领域和适当上下文之前,有理由暂不开始采用微服务架构。

微服务对企业来说仍然非常重要!

现在,你可能想知道我们为什么推荐微服务架构,或者我们是否仍然推荐此架构。灵活性、独立的可扩展性、不断演进的特性、强大的封装仍然是微服务不可不说的优点。这些优点已经在其他文章中进行了详尽的阐述。我们仍然坚定使用微服务架构,以扩展我们对这种架构的理解,并继续探索解决本文所提到问题的工具和方法。实际上,来自ThoughtWorks的Zhamak Dehghani最近发表了一篇关于将单体式应用程序分解为微服务的文章。但是,该方法的成本和缺点以及执行该方法所需达到的组织成熟度水平正是微服务很可能永远无法进入“采纳”环的原因。

本文翻译自ThoughtWorks全球首席技术官Rebecca Pasrsons的《Microservices in Adopt?》一文。Rebecca将在3月15日来到技术雷达十周年峰会现场,与众位国际软件巨匠一同讲述技术领域的十年趋势变革。现在购买可享受限时七折票!

 

Share

细说API – 重新认识RESTful

如果你是一个客户端、前端开发者,你可能会在某个时间吐槽过后端工程师的API设计,原因可能是文档不完善、返回数据丢字段、错误码不清晰等。如果你是一个后端API开发者,你一定在某些时候感到困惑,怎么让接口URL设计的合理,数据格式怎么定,错误码怎么处理,然后怎么才能合适的描述我的API,API怎么认证用户的请求。

在前后端分离和微服务成为现代软件开发的大趋势下,API设计也应该变得越来越规范和高效。本篇希望把API相关的概念最朴素的方式梳理,对API设计有一个更全面和细致的认识,构建出更规范、设计清晰和文档完善的API。

重新认识API

广义的API(Application Programming Interface)是指应用程序编程接口,包括在操作系统中的动态链接库文件例如dll\so,或者基于TCP层的socket连接,用来提供预定义的方法和函数,调用者无需访问源码和理解内部原理便可实现相应功能。而当前通常指通过HTTP协议传输的web service技术。

API在概念上和语言无关,理论上具有网络操作能力的所有编程语言都可以提供API服务。Java、PHP、Node甚至C都可以实现web API,都是通过响应HTTP请求并构造HTTP包来完成的,但是内部实现原理不同。例如QQ邮箱就是通过使用了C构建CGI服务器实现的。

API在概念上和JSON和XML等媒体类型无关,JSON和XML只是一种传输或媒体格式,便于计算机解析和读取数据,因此都有一个共同特点就是具有几个基本数据类型,同时提供了嵌套和列表的数据表达方式。JSON因为更加轻量、容易解析、和JavaScript天生集成,因此成为现在主流传输格式。在特殊的场景下可以构造自己的传输格式,例如JSONP传输的实际上是一段JavaScript代码来实现跨域。

基于以上,API设计的目的是为了让程序可读,应当遵从简单、易用、无状态等特性,这也是为什么Restful风格流行的原因。

RESTful

REST(英文:Representational State Transfer,简称REST),RESTful是一种对基于HTTP的应用设计风格,只是提供了一组设计原则和约束条件,而不是一种标准。网络上有大量对RESTful风格的解读,简单来说Restful定义URI和HTTP状态码,让你的API设计变得更简洁、清晰和富有层次,对缓存等实现更有帮助。RESTful不是灵丹妙药,也不是银弹。

RESTful第一次被提出是在2000Roy Fielding的博士论文中,他也是HTTP协议标准制定者之一。从本质上理解RESTful,它其实是尽可能复用HTTP特性来规范软件设计,甚至提高传输效率。HTTP包处于网络应用层,因此HTTP包为平台无关的字符串表示,如果尽可能的使用HTTP的包特征而不是大量在body定义自己的规则,可以用更简洁、清晰、高效的方式实现同样的需求。

用我几年前一个真实的例子,我们为了提供一个订单信息API,为了更方便传递信息全部使用了POST请求,使用了定义了method表明调用方法:

返回定义了自己的状态:

大家现在来看例子会觉得设计上很糟糕,但是在当时大量的API是这样设计的。操作资源的动作全部在数据体里面重新定义了一遍,URL上不能体现出任何有价值的信息,为缓存机制带来麻烦。对前端来说,在组装请求的时候显得麻烦不说,另外返回到数据的时候需要检查HTTP的状态是不是200,还需要检查status字段。

那么使用RESTful的例子是什么样呢:

例子中使用路径参数构建URL和HTTP动词来区分我们需要对服务所做出的操作,而不是使用URL上的接口名称,例如 getProducts等;使用HTTP状态码,而不是在body中自定义一个状态码字段;URL需要有层次的设计,例如/catetory/{category_id}/products 便于获取path参数,在以后例如负载均衡和缓存的路由非常有好处。

RESTful的本质是基于HTTP协议对资源的增删改查操作做出定义。理解HTTP协议非常简单,HTTP是通过网络socket发送一段字符串,这个字符串由键值对组成的header部分和纯文本的body部分组成。Url、Cookie、Method都在header中。

几个典型的RESTful API场景:

虽然HTTP协议定义了其他的Method,但是就普通场景来说,用好上面的几项已经足够了

RESTful的几个注意点:

  • URL只是表达被操作的资源位置,因此不应该使用动词,且注意单复数区分
  • 除了POST和DELETE之外,其他的操作需要冥等的,例如对数据多次更新应该返回同样的内容
  • 设计风格没有对错之分,RESTful一种设计风格,与此对应的还有RPC甚至自定义的风格
  • RESTful和语言、传输格式无关
  • 无状态,HTTP设计本来就是没有状态的,之所以看起来有状态因为我们浏览器使用了Cookies,每次请求都会把Session ID(可以看做身份标识)传递到headers中。关于RESTful风格下怎么做用户身份认证我们会在后面讲到。
  • RESTful没有定义body中内容传输的格式,有另外的规范来描述怎么设计body的数据结构,网络上有些文章对RESTful的范围理解有差异

JSON API

因为RESTful风格仅仅规定了URL和HTTP Method的使用,并没有定义body中数据格式的。我们怎么定义请求或者返回对象的结构,以及该如何针对不同的情况返回不同的HTTP 状态码?

同样的,这个世界上已经有人注意到这个问题,有一份叫做JSON API开源规范文档描述了如何传递数据的格式,JSON API最早来源于Ember Data(Ember是一个JavaScript前端框架,在框架中定义了一个通用的数据格式,后来被广泛认可)。

JSON已经是最主流的网络传输格式,因此本文默认JSON作为传输格式来讨论后面的话题。JSONAPI尝试去提供一个非常通用的描述数据资源的格式,关于记录的创建、更新和删除,因此要求在前后端均容易实现,并包含了基本的关系类型。个人理解,它的设计非常接近数据库ORM输出的数据类型,和一些Nosql(例如MongoDB)的数据结构也很像,从而对前端开发者来说拥有操作数据库或数据集合的体验。另外一个使用这个规范的好处是,已经有大量的库和框架做了相关实现,例如,backbone-jsonapi ,json-patch。

没有必要把JSON API文档全部搬过来,这里重点介绍常用部分内容。

MIME 类型

JSON API数据格式已经被IANA机构接受了注册,因此必须使用application/vnd.api+json类型。客户端请求头中Content-Type应该为application/vnd.api+json,并且在Accept中也必须包含application/vnd.api+json。如果指定错误服务器应该返回415或406状态码。

JSON文档结构

在顶级节点使用data、errors、meta,来描述数据、错误信息、元信息,注意data和errors应该互斥,不能再一个文档中同时存在,meta在项目实际上用的很少,只有特别情况才需要用到,比如返回服务器的一些信息。

data属性

一个典型的data的对象格式,我们的有效信息一般都放在attributes中。

  • id显而易见为唯一标识,可以为数字也可以为hash字符串,取决于后端实现
  • type 描述数据的类型,可以对应为数据模型的类名
  • attributes 代表资源的具体数据
  • relationships、links为可选属性,用来放置关联数据和资源地址等数据

errors属性

这里的errors和data有一点不同,一般来说返回值中errors作为列表存在,因为针对每个资源可能出现多个错误信息。最典型的例子为,我们请求的对象中某些字段不符合验证要求,这里需要返回验证信息,但是HTTP状态码会使用一个通用的401,然后把具体的验证信息在errors给出来。

在title字段中给出错误信息,如果我们在本地或者开发环境想打出更多的调试堆栈信息,我们可以增加一个detail字段让调试更加方便。需要注意的一点是,我们应该在生产环境屏蔽部分敏感信息,detail字段最好在生产环境不可见。

常用的返回码

返回码这部分是我开始设计API最感到迷惑的地方,如果你去查看HTTP协议文档,文档上有几十个状态码让你无从下手。实际上我们能在真实环境中用到的并不多,这里会介绍几个典型的场景。

200 OK

200是一个最常用的状态码用来表示请求成功,例如GET请求到某一个资源,或者更新、删除某资源。 需要注意的是使用POST创建资源应该返回201表示数据被创建。

201 Created

如果客户端发起一个POST请求,在RESTful部分我们提到,POST为创建资源,如果服务器处理成功应该返回一个创建成功的标志,在HTTP协议中,201为新建成功的状态。文档规定,服务器必须在data中返回id和type。 下面是一个HTTP的返回例子:

在HTTP协议中,2XX的状态码都表示成功,还有202、204等用的较少,就不做过多介绍了,4XX返回客户端错误,会重点介绍。

401 Unauthorized

如果服务器在检查用户输入的时候,需要传入的参数不能满足条件,服务器可以给出401错误,标记客户端错误,需要客户端自查。

415 Unsupported Media Type

当服务器媒体类型Content-Type和Accept指定错误的时候,应该返回415。

403 Forbidden

当客户端访问未授权的资源时,服务器应该返回403要求用户授权信息。

404 Not Found

这个太常见了,当指定资源找不到时服务器应当返回404。

500 Internal Server Error

当服务器发生任何内部错误时,应当返回500,并给出errors字段,必要的时候需要返回错误的code,便于查错。一般来说,500错误是为了区分4XX错误,包括任何服务器内部技术或者业务异常都应该返回500。

HATEOAS

这个时候有些了解过HATEOAS同学会觉得上面的links和HATEOAS思想很像,那么HATEOAS是个什么呢,为什么又有一个陌生的名词要学。 实际上HATEOAS算作被JSON API定义了的一部分,HATEOAS思想是既然Restful是利用HTTP协议来进行增删改查,那我们怎么在没有文档的情况下找到这些资源的地址呢,一种可行的办法就是在API的返回体里面加入导航信息,也就是links。这样就像HTML中的A标签实现了超文本文档一样,实现了超链接JSON文档。

超链接JSON文档是我造的一个词,它的真是名字是Hypermedia As The Engine Of Application State,中文叫做超媒体应用程序状态的引擎,网上很多讲它。但是它并不是一个很高大上的概念,在RESTful和JSONAPI部分我们都贯穿了HATEOAS思想。下面给出一个典型的例子进一步说明:

如果在某个系统中产品和订单是一对多的关系,那我们给产品的返回值可以定义为:

从返回中我们能得到links中product的的资源地址,同时也能得到orders的地址,这样我们不需要客户端自己拼装地址,就能够得到请求orders的地址。如果我们严格按照HATEOAS开发,客户端只需要在配置文件中定义一个入口地址就能够完成所有操作,在资源地址发生变化的时候也能自动适配。

当然,在实际项目中要使用HATEOAS也要付出额外的工作量(包括开发和前后端联调),HATEOAS只是一种思想,怎么在项目中使用也需要灵活应对了。

参考链接

在文档中还定义了分页、过滤、包含等更多内容,请移步文档:

英文版:http://jsonapi.org/format/

中文版:http://jsonapi.org.cn/format/ (PS:中文版更新不及时,请以英文文档为准)


更多精彩洞见,请关注微信公众号:ThoughtWorks洞见

Share

ThougtWorks中国的Tech Strategy 2.0初探

转眼已近年底,本来正在思考ThoughtWorks中国区技术和业务的未来。正好几周前在墨尔本参加了ThoughtWorks Council的会议,其中一个重要的环节是讨论推进中的Tech Strategy 2.0的规划,对我帮助很大。

Tech Strategy是要定义一个愿景,这个愿景将指引技术在支撑商业和社会进程中所承担的角色。 (The Technology Strategy defines a vision for the role technology plays in support of business and society.)如下图ThoughtWorks的价值创造理论(Theory of Value Creation)所示, 我们的价值在于从技术驱动的商业变革中发现创造商业和社会价值的机会,而这些机会的捕获和实现,则依赖于围绕我们技术战略所建立的各项能力。

(Source: ThoughtWorks)

ThoughtWorks的Tech Strategy的出发点是识别技术、商业和社会板块的移动趋势(Seismic Shift)。在这些宏大的故事主线底下,是一系列的技术发展,推动着这样的宏观板块的移动。ThoughtWorks需要根据这些现象的观察和判断,制定相应行动,包括培育相应能力,孵化和推出新的服务。

ThoughtWorks识别了五个宏观板块的变化:

  • Evolving interactions
  • Humanity, augmented
  • Rise of the platforms
  • Security, privacy, transparency
  • Rise of the robots

这里每个变化趋势后面都有着大量的技术进步产生的推动力。以“Humanity, augmented”为例,人们将发挥机器日益增强的优势,机器将有能力无处不在地部署触点以收集数据,同时发挥其处理海量数据能力,提供相应的决策推荐,并以自动或半自动的方式,凭借功能强大的执行设备,将决策反馈影响到现实的物理世界。 人类将更加关注发挥经验、直觉、创造力等独特的优势。人和机器的合作将发挥更大的力量。

凯文凯利在《必然》里提到,自从深蓝在1997年多次击败顶级象棋棋手后,卡斯帕罗夫提出了“人加机器”(Man-plus-Machine)的概念。在平时训练中,人工智能的陪练让人类自身的能力得到大幅提高,而在比赛中,人类棋手和人工智的协作则能显著增强技战水平。在2014年的自由式国际象棋对抗锦标赛上,纯粹使用人工智能的选手赢得了42场比赛,而人机一起参加的选手赢得了53场。

讲了这么多,这些跟我们有什么关系呢?这些宏观板块的范围都很广,产生商业价值的方式很多,涉及的技术也是种类繁杂,我们不可能什么都做。那么ThoughtWorks应该把注意力关注在什么上呢?

在公司Council会议上给出第一个关注点是Intelligent Empowerment,我们希望通过机器学习等数据技术帮助企业的业务转型,实现数字化企业向算法化企业的跨越。这其中覆盖的技术包括机器学习,数据平台&实时分析,智能助理,声音和视频识别,语音作为普遍存在的交互界面,智能系统和生态等等。如果我们大致分类,这些技术大多可以归到基于人工智能或其它智能分析技术,以及基于IoT的数据收集、交互和执行能力。

那么我们跟其它做AI的公司有什么区别呢?ThoughtWorks更加关注数据使用中的伦理道德,对个人隐私的尊重,对数据和算法中潜在的偏见保持警醒,我们更多地把着眼点放在企业的业务敏捷和管理透明度上。

在分析了中国区面对的市场,以及我们的定位和核心优势之后,我们认为数据和IoT是突破方向,加上这两项技术依托的平台技术,特别是各个层面的云(包括公有云和私有云)平台技术,这三个领域将会是我们Intelligent Empowerment的工作重点。

IoT领域纷繁复杂,ThoughWorks既不会去做传感器,也不会把重心放在芯片、组件等电子工程方面,朱晨在最近的一次分享中说过,“ThoughtWorks是作为IoT系统方案的供应商或传统产品的升级合作伙伴”。而在制造Intelligent Things with Service和跟我们的客户一起建设Intelligent Services with Things两个方向之间,我们更倾向后者。面对客户的时候,我们想的不是给客户做个什么有趣的设备,而是要思考——“互联的设备和服务在客户的服务化战略上下文中能够发挥什么样的重要作用?”

技术层面上,我们的注意力可以放在三个领域:整合各种sensor和actuator的IoT技术栈,IoT Product System Design,IoT数据分析技术。同时,我们在深圳的IoT中心将承担起建立跟材料和组件供应商、硬件设计公司、生产制造商等供应链上游公司的联盟合作关系。

(source: ThoughtWorks IoT团队负责人朱晨)

说到人工智能,大家看到Google、微软、BAT投入的美刀都至少是以亿计,我们作为一家中等规模的专业服务公司又有什么优势,能做什么呢?这个问题其实就好像在问,亚马逊和微软提供了云计算的平台,我们还要不要提云计算战略,是否还要寻求更好的相关架构、开发思想和实践,是否还要改善工具和提升能力。

就像一位前同事在一个讨论中说的,我们并“不去发明算法,我们要用工程技术上的优势,降低开发者和企业运用机器学习等技术创造价值的难度”。杨博正在开发DeepLearning.scala,试图构建具备更强业务场景表达能力的深度学习框架,让软件开发人员在使用深度学习算法时,用自己熟悉的复杂数据结构,让开发相关的应用在工程上变得更加容易可行。数据团队已经开源的DeepDarkFantasy,也是在这个方向上的努力。

有人说我们没有互联网公司的海量数据,怎么做大数据?我们并不需要跟互联网公司比数据规模。大型平台公司要么用围棋这样的问题做前沿性探索,要么投入到实际应用的大多是解决语音、图像识别等通用型问题。跟他们不同,我们要让AI进入到企业特定商业场景的问题域。

而云计算作为未来IoT、Data战略和其它应用系统的的缺省推荐的基础设施,早在Tech Strategy1.0版本里就已经被重点提及。在那个版本里,我们希望把改变游戏规则的云计算思维和能力带给我们的战略客户。这个策略在海外发达国家市场进展的不错,但在国内,由于众所周知外部因素,也可能因为我们没有足够的努力和能力推动客户采用新技术,总体进展并不理想。

我们的大多数应用还部署在客户的数据中心,即使是云上,也较少发挥云计算能够提供的全面潜力。今天,在Tech Strategy2.0里,平台成了关注的焦点。端到端DevOps能力的Pass,基于Microservice和Serviceless的架构,提供Data Analytics/AI as Service的数据平台,集成支持各种senor和actuator的网关并提供数据分析和响应的IoT平台,这些将是我们的推动的方向。当然,同时我们还得继续补Tech Strategy1.0的课。

不过,如果我们不想让积累的能力只是沦为个人爱好,就要意识到,单纯的技术和能力距离创造商业价值之间还有巨大的差距。如果我们不想简单拷贝市场上其他人的做法,就得形成自己独特的价值定位,要依靠我们自己的学习、观察、思考和验证,所谓格物致知。市场、销售和项目团队都是我们面对市场的触点,只有大家都有意识地识别有价值的业务场景,才有可能让我们捕捉到商业机会。能力和业务场景之间的持续反馈和验证,就有可能让我们孵化出新的业务。

MD心声

市场需求和我们能力建设之间的鸡蛋的问题,如何破?


更多精彩洞见,请关注微信公众号:ThoughtWorks洞见

Share

Quorum-企业级分布式账本和智能合约平台

位置

2018年11月第19期技术雷达(可点击下载)平台象限,建议评估

标签

Blockchain, DLT, Ethereum, Quorum

目标受众

区块链架构师与开发者

关注问题

以Ethereum为代表的公有链平台工作于信任度较低的public internet,一般采用PoW/PoS等效率较低的共识机制。而企业业务环境下一般有更高的信任度,对网络许可管理、交易的隐私性以及吞吐量/延迟也有更高的要求。因此联盟链和公有链相比有完全不同的设计关注点。

解决方案

Quorum是由摩根大通开发的企业级区块链平台,它从以太坊的官方客户端fork出代码并对部分模块重新设计实现。通过添加交易隐私、节点许可管理等特性,将Ethereum原有的共识算法替换成可选的Raft/IBFT协议,Quorum可以在适配Ethereum开发工具链的同时,更好地服务于企业联盟链场景。

解读

在区块链行业中,Ethereum有较高的知名度和生态成熟度,被很多人当成区块链/去中心化应用开发的首选平台。然而Ethereum是针对公有链进行设计,虽然可以单独部署私有网络,但很多特点不适合企业联盟链场景。因此一些团队选择基于Ethereum开发适合企业的区块链平台,从而充分利用Ethereum在社区和工具链等方面的优势。

Quorum的代码fork自Ethereum官方EVM(Ethereum Virtual Machine)之一go-ethereum,并跟进主要release的更新。而Quorum对Ethereum主要在以下方面进行了改进:

  • 交易隐私性

在公有链中,所有交易都是公开可见的,任何人都可以查看Ethereum主网络历史某个区块的交易。这种透明性也是公有链的特性之一,很多团队基于区块链的这一特性开发出公证/鉴证等服务。然而在企业对企业的交易环境中,很多时候需要保证交易的隐私性。即使在一个企业联盟内部,交易也只对发起的双方可见。Quorum对此添加了私有交易的支持。

Quorum会将需要保证隐私性的交易标记为私有事务,其事务管理器会将交易内容载荷加密后进行替换。其他的Quorum节点接受到交易时只能看到被加密过后的内容,而只有这次交易的参与者才能用自己的秘钥解密私有事务,并将其存储在本地的私有状态数据库中。

  • 节点许可管理

在公有链中,任何人都可以运行全节点进行挖矿,成为公有链网络的一部分。这种基于完全去中心化的设计方式跟企业业务有较大差异。在企业联盟中,所有成员的身份都是已知的,节点的分布往往基于实际的商业规则进行考量。此外联盟链需要相应的机制,对成员节点的加入、维护、退出等进行许可管理。

每个Quorum节点可以通过维护一份permissioned-nodes列表来组件一个许可网络。该列表中维护了传入/传出节点的白名单,并配置相应的IP/端口/公钥地址。

  • 共识协议

公有链处于信任度较低的公有因特网中,且成员加入不需许可,往往面临女巫攻击的风险;此外公有链往往会设计相应的经济机制用于激励参与挖矿记账的矿工。基于博弈的共识类协议(PoW/PoS等)应运而生。此类协议可以很好的解决公有链的问题,但在性能、效率方面有很多限制。

在联盟链中所有成员身份已知节点数量有限,一般不会受到女巫攻击威胁;且成员间通过商业达成合作,不需要设置挖矿激励。因此可以采用更高效率的共识协议。Quorum替换掉了Ethereum原有的共识协议,并支持可选的Raft/ Istanbul BFT协议,更具灵活性。

总结

Quorum为以太坊开发者提供了一个平台,可以用Solidity/Truffle等熟悉的工具链构建一个企业联盟链。虽然在我们的实践中,该平台仍存在一些缺陷,成熟度有待提升。但我们建议区块链架构师和开发者将该平台放到自己的评估备选中,持续观察。

相关Blip

Share

QA与Ops通力合作打造反脆弱的软件系统

软件系统的脆弱性

伴随着不断演进的软件技术和架构,日趋复杂的软件系统基础设施,以及大量增加的业务和数据,开发和运行环境中不稳定的因素也在增加,系统行为变得不可预测,同时软件系统的不确定性日益严重。

人们无法通过预先设定的测试场景和测试脚本去测试软件,预生产环境已经不够用,软件系统的质量保障工作受到挑战,软件系统变得脆弱。

面对复杂的环境和脆弱的软件系统,该如何保障软件的质量呢?借用反脆弱[1]的概念,我们可以把软件的质量保障工作延伸到生产环境,利用这些不确定因素,从中受益,构建反脆弱的软件系统。

生产环境下的QA就是利用系统在生产环境的不可预测性,通过监控预警等方式收集生产环境的信息,总结分析以指导软件开发和测试过程,从而提高软件系统的健壮性、优化业务价值。其中,日志处理是最为关键的一个部分。

日志处理的常见误区与改进思考

提到日志处理,通常都会想到Ops(可能有Ops和开发人员组成,下面简称Ops)团队,认为日志处理是Ops该做的事情,往往关注的都是利用什么工具、什么技术来监控和分析,很少听到有对仅仅Ops人员处理日志的质疑。

作为QA,想从QA的角度来考虑一下,如果QA能够参与日志处理,跟Ops人员合作会有什么惊喜发生呢?

当然,并不是质疑Ops人员的能力,我们相信Ops人员在监控分析方面的专业技术能力是完全没有问题的,但是受限于不同的思维模式,Ops人员处理日志还是会有局限性的:

  1. Ops人员主要关注的是系统运行的稳定性和系统资源使用情况,做日志监控也会着重关注这些方面,比如内存、CPU利用率等等,缺乏对系统整体质量的关注。
  2. Ops也会对业务有所了解,但肯定比不上业务分析和QA人员,在做日志监控和分析的时候容易漏掉高业务风险的日志,没有及时止损,导致给业务带来损失。
  3. Ops人员很难把生产环境日志信息做详尽的分析,并把结果共享给开发团队来指导上线前的开发和测试工作,难以做到最优化利用日志信息。

凭着对业务的了解、对系统的熟悉以及对整体质量的关注,QA参与日志处理有着独特的优势。

  • 质量反馈

敏捷QA有一项非常重要的职责就是在每个环节做好质量分析、掌握质量状态,并把质量信息反馈给团队。QA利用生产环境的日志信息,能够更好的了解产品的质量状况,更好的掌握系统易出错的薄弱功能点,对于后续的开发和测试工作有很好的指导意义。

  • 分析优化

QA作为质量的倡导者,不会放过任何有利于做好质量保障的环节。当QA参与日志处理,发现日志处理过程中存在的可改进空间,定会促使优化日志处理,最大化利用日志信息。

  • 业务敏感度

QA是团队里对系统最了解的角色里边业务敏感度最高的,QA参与任何活动都会以用户角度出发,考虑业务价值和业务风险。

QA参与日志处理,对于业务优先级较高的日志会比较敏感,能够更有的放矢的关注日志信息,让日志处理更有效。

同时,QA分析生产环境的日志信息,了解到真实业务的运行状况,从而可以更好的帮助优化业务价值。

下面通过一个项目上日志处理的故事来分享QA与Ops合作做好日志处理的实践。

项目的故事

项目背景

蓝鲸项目是一个历时九年多的离岸交付项目,团队不同阶段有50-80人不等,有三个系统同时并行开发,包括企业系统、客户系统和用户系统。随着业务的不断扩展、微服务的规模化,系统的不确定因素也开始暴露出来,生产环境下的缺陷增多、错误日志增长迅速,日均新增错误日志数达到几千条。

加强日志监控和处理迫在眉睫。

被动日志分析

刚开始项目上的一个Ops人员专职处理生产环境的日志,分析的方法是在Splunk里按Punct[2]查询错误日志重复出现的数量排序,每天处理重复出现数量比较多的一部分日志。这个阶段没有QA介入。

这是一个被动分析日志的过程,处理过程本身存在很多的问题:

  • 时间和精力原因,每天新增的日志并没有办法全部覆盖到;
  • 分析日志的同事的业务敏感度不够,没法基于风险优先级来处理,可能导致某些关键业务的错误信息漏掉;
  • 没有可能进行详细的总结分析,对后续的处理没有指导意义;
  • 虽然参与处理日志的同事越来越专业,但没有很好的将日志信息共享给团队,形成信息孤岛。

在这个过程中发现了很多当时日志记录本身存在的问题:级别定义不清晰、记录信息不够用、记录格式不一致等。

这个时候,QA也想参与,可是心有余力不足,主要是因为以下几个方面的痛点:

  • QA没有权限接触生产环境;
  • 由于没有接触过,对生产环境的基础设施并不了解;
  • 日志记录的信息QA理解起来很有难度。

主动出击内建日志

意识到前一阶段日志处理的问题,团队决定投入更多的精力来加强日志处理。

首先,利用结构化日志技术,优化日志记录本身的问题。同时,QA从流程上把关做好日志内建,控制好每个环节,确保该有的日志能够正确的记录下来。

同时,QA、Tech lead跟Ops人员一起讨论识别出业务风险较高的特性,在监控面板设置对这些特性相关的前端和API的监控,并设置好一些定时Alert,每天通过邮件的方式告知性能和故障情况。每个特性团队的再派出开发人员加入Ops团队,兼职负责对监控得到的信息进行诊断,QA则负责跟踪通过日志信息定位出来的缺陷问题的修复。

另外,也对测试环境的日志进行监控,QA开始分析测试环境的日志信息,尽早发现问题。

这一阶段团队开始主动出击,有了业务优先级,不再是从茫茫日志大海去分析,这一举措给忙季带来很好的效果,顺利度过了忙季。

但是随着忙季的过去,也开始暴露出问题:错误日志在不断减少,团队对此的关注也越来越少,原来加入Ops团队的开发人员主要关注点也是在新的特性开发上,邮件收到的定时Alert也渐渐地被忽视…对于突然出现的错误日志并不能第一时间发现处理。

QA主导进一步优化

错误日志不能及时发现,导致用户报过来的生产环境缺陷也在增加。

QA作为生产环境支持的主要负责人,承担起处理生产环境缺陷和加强日志监控两项职责。

  1. QA组织跟参与日志处理的Ops人员的访谈,收集痛点,针对性的优化Alert机制,改为错误触发,不再是定时的,减少噪音;
  2. QA从流程上督促各特性团队Ops人员分析和查看自己组内负责的监控信息,关注Ops处理日志的进度状态更新;
  3. 对于Ops人员比较抓狂难以定位的问题,QA也会参与一起pair分析,或者根据Ops人员提供的信息去在测试环境尝试重现;
  4. QA对于一些特别重要的特性,定期查看是否有相关错误出现,以免漏掉相关错误信息。 比如,系统有个专供大老板发邮件的功能,某天突然挂掉了,这个错误日志信息在监控里边也有,但是并没有引起重视,QA查看的时候发现了才把优先级提上来赶紧处理;
  5. 优化整个生产环境支持流程,把日志处理纳入其中。周期性的对日志处理结果进行分析和回顾,把日志信息跟业务关联起来,识别出易出错的业务功能点,在后续的开发和测试过程中重点关注,同时也进一步优化现有的监控预警设置。

这个阶段QA不管是流程上还是实际日志分析上都有参与,日志处理更高效、生产环境缺陷发现更及时,生产环境的支持收到客户的好评。

项目故事回顾

前面故事主要分享的是随着业务和架构的演进,生产环境缺陷和错误日志都在大量增加,项目团队如何一步步优化日志处理、利用日志信息加强质量保障工作。从QA不参与、QA参与到最后QA主导,QA在整个日志处理过程中承担着以下几个非常关键的作用:

  • 监督协调,流程把控
  • 基于业务风险的分析和优化
  • 日志处理与开发过程形成闭环,持续改进

写在最后

软件系统所处生态环境的复杂性、不确定性并不是毫无益处,生产环境下的QA技术就是利用这种不确定性,并从中受益,从而增强软件系统的反脆弱性。

QA参与日志处理,主要承担的是分析者和协调者的角色。QA参与,持续的分析、优化,利用生产环境的日志信息来指导和优化软件开发和测试过程,最大化业务价值,是生产环境下的QA最核心内容之一。

同时,QA利用开发和测试过程中对系统的了解,以及对业务的敏感度,可以进一步指导和协调日志处理过程的优化和改进。QA与Ops团队的合作,生产环境日志处理会更高效,也更能体现其价值。

这样,生产环境和预生产环境形成了良性循环,打造出一个反脆弱的软件系统。


注1:反脆弱

脆弱的反面是什么?是坚强?是坚韧?《反脆弱》这本书给出了这样的解释:

脆弱的反面并不是坚强或坚韧。坚强或坚韧只是保证一个事物在不确定性中不受伤,保持不变,却没有办法更进一步,让自己变得更好。而脆弱的反面应该完成这个步骤,不仅在风险中保全自我,而且变得更好、更有力量。

做一个类比的话,坚强或坚韧就像一个被扔到地上的纸团,不会摔坏,但是也只是维持了原貌,这还不够。

和纸团相反,乒乓球扔到地上非但不会摔坏,反而可以弹得更高。乒乓球拥有的就是脆弱反面的能力,也就是反脆弱。

注2:PUNCT

PUNCT是Splunk提供的一个功能,就是将日志信息的第一行的所有字母和数字去掉,剩下的标点符号,其中空格用下划线代替,最后结果为显示成类似正则表达式的形式。根据这个表达式来归类,同一类日志就会归到一起。

Share