关于microservice:密码学系列之在线证书状态协议OCSP详解

简介咱们在进行网页拜访的时候会跟各种各样的证书打交道,比方在拜访https网页的时候,须要检测https网站的证书有效性。 OCSP就是一种校验协定,用于获取X.509数字证书的撤销状态。它是为了替换CRL而呈现的。 本文将会具体介绍OCSP的实现和长处。 PKI中的CRL咱们晓得在PKI架构中,CA证书是十分重要的组件,客户端通过CA证书来验证服务的可靠性。对于CA证书自身来说在创立的时候是能够指定过期工夫的。这样证书在过期之后就不能够应用,须要申请新的证书。 然而只给证书指定过期工夫是不够的,比方咱们因为业务的需要,须要撤销证书怎么办呢? PKI中提供了一个叫做CRL(certificate revocation list)的机制,用来维持被破除的证书列表。 这个CRL是由CA来颁发的,个别是在证书过期之前生成的。因为如果证书曾经过期了,那么这个CRL是无意义的。 对于CRL自身来说,它是一个证书列表,外面证书的格局通常也应用的是X.509。 CRL个别是由公布证书的CA来保护和公布的,公布CRL的组件叫做CRL issuer,通常来说CRL issuer和CA是同一个服务,然而你也能够依据须要将CRL issuer和CA进行拆分。 CRL是由CA定时来公布的,当然你也能够依照须要在须要撤销某个CA证书的时候从新公布CRL。所有的CRL都有过期工夫,在这个过期工夫之内,客户端能够依据CRL中的签名,去CA验证CRL的有效性,从而避免CRL的伪造。 CRL的毛病那么CRL有什么毛病呢? 首先CRL维持的是一个撤销的证书列表,为了保证系统的有效性,客户端在每次校验CA证书有效性的时候,都须要从CA服务器中获取这个CRL。而后通过CRL来校验对应的CA证书状态。 如果每次都去拿这个CRL,就有可能会有上面几个问题。 第一个问题是,如果CRL不可用,那么客户端就拿不到这个CRL,也就无奈校验CA证书的状态,从而造成服务不可用。 另外一个问题是,如果要撤销的证书比拟多的话,这个CRL可能会比拟大,从而造成网络资源的节约。 最初一个问题是PKI证书体系自身的目标是建设一个能够自我校验的,不依赖于在线服务的平安体系,如果每次都要在线获取CRL的话,就是去了PKI的这一劣势。 CRL的状态尽管CRL维持的是一个撤销证书列表,然而这个列表中证书的状态还是有所不同的。 CRL中证书的状态有两种,第一种就是证书曾经被撤销了,比方证书的颁发机构CA发现之前的颁布的证书是谬误的,或者因为其余的起因如私钥泄露导致原来的证书不够平安,须要将证书撤回。或者证书机构因为未恪守某些策略导致证书被撤消等,都须要将之前的证书设置为撤销状态。 还有一种状态是一个长期撤销的状态,这里叫做Hold状态,它示意证书临时是有效的,比方在用户没有确定私钥是否失落的状况下。当用户最终找回了私钥,则这个证书还是能够被复原的。 OCSP的工作流程既然CRL有这么多毛病,所以一个用来代替CRL的OCSP协定呈现了。 咱们先来看一下OCSP的工作流程。 如果A和B要进行应用PKI进行通信。为了保障通信的安全性,A将本人的公钥发给B,并通知B,这是我的公钥,你能够用这个公钥来校验我发送给你的音讯。 B在收到A的公钥之后,并不能确定A的公钥就是正确的,没有被篡改的。于是从A的公钥中提取出serial number,并将其封装到一个'OCSP request'中发给CA服务器。 CA服务器中的OCSP responder读取到了'OCSP request'申请,并从中提取出A的公钥的serial number。OCSP responder从CA服务器的数据库中查问这个serial number是否在这个数据库被撤销的列表中。 如果发现不在,那么意味着A的公钥依然是无效的,OCSP responder将会发送一个签名后的OCSP response给B。 B通过应用CA服务器的公钥验证OCSP response的有效性,从而确认A的公钥依然无效 。 最初B应用A的公钥和A进行通信。 OCSP的长处从下面的OCSP的工作流程咱们能够大略总结出上面几个OCSP绝对于CRL的长处。 首先OCSP响应的数据量要比CRL要小,所以对网络的要求和压力更少。 另外因为OCSP响应要解析的数据更少,所以OCSP客户端的实现要比CRL更加简略。 尽管因为CRL的各种毛病,在web环境中曾经不再被应用,而是被更加高效的OCSP替换,然而CRL依然被运行在CA的其余环境中。 OCSP协定的细节OCSP协定是在RFC 6960中定义的。 OCSP协定能够分为申请协定和响应协定两局部,接下来别离来进行介绍。 OCSP申请一个OCSP申请须要蕴含协定版本号,申请服务,要校验的证书identifier和可选的扩大局部。 OCSP responder在接管到OCSP的申请之后,会去校验OCSP音讯的有效性,如果音讯有问题则会返回异样,否则的话会依据申请的服务进行解决。 OCSP申请如果用ASN.1(Abstract Syntax Notation One)形象语法标记这能够如下示意: OCSPRequest ::= SEQUENCE { tbsRequest TBSRequest, optionalSignature [0] EXPLICIT Signature OPTIONAL } TBSRequest ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, requestorName [1] EXPLICIT GeneralName OPTIONAL, requestList SEQUENCE OF Request, requestExtensions [2] EXPLICIT Extensions OPTIONAL } Signature ::= SEQUENCE { signatureAlgorithm AlgorithmIdentifier, signature BIT STRING, certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL} Version ::= INTEGER { v1(0) } Request ::= SEQUENCE { reqCert CertID, singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } CertID ::= SEQUENCE { hashAlgorithm AlgorithmIdentifier, issuerNameHash OCTET STRING, -- Hash of issuer's DN issuerKeyHash OCTET STRING, -- Hash of issuer's public key serialNumber CertificateSerialNumber }ASN.1是一个接口描述语言,通过ASN.1,咱们能够很清晰的形容数据的格局信息。 ...

July 6, 2022 · 2 min · jiezi

关于microservice:密码学-09-AES

AES表一:算法秘钥长度秘钥长度默认值工作模式填充模式备注AES128,192,256128ECB,CBC,PCBC,CTR,CTS,CFB,CFB8至CFB128,OFB,OFB8至OFB128NoPadding,PKCS5Padding,ISO10126PaddingJava6实现若应用256位秘钥须要取得无政策限度权限文件(Unlimited Strength Jurisdiction Policy Files)AES同上同上同上PKCS7Padding,ZeroBytePaddingBouncy Castle实现表二:AES秘钥长度(比特)分组长度(比特)向量长度(比特)加密轮数AES-12812812812810AES-19219212812812AES-256256128128141 依据密钥长度不同,分为AES128、AES192、AES2561.特点ECB模式和CBC模式的区别对称加密算法里,应用NOPadding,加密的明文必须等于分组长度倍数,否则报错如果应用PKCS5Padding,会对加密的明文填充1字节-1个分组的长度没有指明加密模式和填充形式,示意应用默认的AES/ECB/PKCS5Padding加密后的字节数组能够编码成Hex、Base64AES算法明文按128位进行分组加密,能够调用cipher.getBlockSize()来获取要复现一个对称加密算法,须要失去明文、key、iv、mode、padding明文、key、iv须要留神解析形式,而且不肯定是字符串模式如果加密模式是ECB,则不须要加iv,加了的话会报错如果明文中有两个分组的内容雷同,ECB会失去齐全一样的密文,CBC不会加密算法的后果通常与明文等长或者更长,如果变短了,那可能是gzip、protobuf2.代码实现 public static String encryptAES(String plaintext) throws Exception { // 初始化秘钥 和加密算法 秘钥为16位 SecretKeySpec keySpec = new SecretKeySpec("0123456789abcdef".getBytes(StandardCharsets.UTF_8),"AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec("hengdinghengding".getBytes(StandardCharsets.UTF_8)); // 失去Cipher的实例 026fcbe02f76529d0a5bb3904aa6efdc C5sV2ktEoPUVHc/EwB811b8xuRnjiS3cO1khLWp7EeY= Cipher des = Cipher.getInstance("AES/CBC/PKCS5Padding"); // 对Cipher 实例进行初始化, des.init(Cipher.ENCRYPT_MODE,keySpec,ivParameterSpec); // update并不会每次都减少要加密的字符串的长度,并不牢靠。现实中的状态是 xiaojianbang +hengdi 解密发现只有banghengdi// des.update("xiaojianbang".getBytes(StandardCharsets.UTF_8)); // 加密 由字符串 失去的byte[] byte[] res=des.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); Log.d("hengdi","AES byte test" + Arrays.toString(res)); // 将 byte[] 实例化为 ByteString 对象 ByteString bty= ByteString.of(res); // hex 编码 String str_hex= bty.hex(); // base64 编码 String str_base64 = bty.base64(); return str_hex + " || " + str_base64; } public static String decryptAES(String cipherText) throws Exception { // 将加密后base64编码的字符串 解码,并还原成 byte[]// byte[] cipherTextBytes = ByteString.decodeHex(cipherText).toByteArray(); byte[] cipherTextBytes = ByteString.decodeBase64(cipherText).toByteArray(); SecretKeySpec keySpec = new SecretKeySpec("0123456789abcdef".getBytes(StandardCharsets.UTF_8),"AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec("hengdinghengding".getBytes(StandardCharsets.UTF_8)); // 失去Cipher的实例 026fcbe02f76529d0a5bb3904aa6efdc Am/L4C92Up0KW7OQSqbv3A== Cipher des = Cipher.getInstance("AES/CBC/PKCS5Padding"); des.init(Cipher.DECRYPT_MODE,keySpec,ivParameterSpec); byte[] res=des.doFinal(cipherTextBytes); return new String(res); }

December 25, 2021 · 1 min · jiezi

Dapr一个可让每个开发人员更轻松地构建微服务应用程序的开源项目

令人惊讶的是,在过去几年中,越来越多的开发人员转向利用托管服务来部署和运行可扩展的云原生应用程序。通过这种转变,微服务架构已成为构建云原生应用程序的标准,并且可以预见,到2022年,将有90%的新应用程序采用微服务架构。微服务架构提供了令人信服的好处,包括可伸缩性,松散的服务耦合和独立部署,但是这种方法的成本很高,需要了解和熟练掌握分布式系统。 开发人员希望专注于业务逻辑,频繁且增量地迁移遗留代码,同时依靠平台为应用程序提供所需的规模,弹性,可维护性,以及云原生架构的其他属性。但是,开发人员发现,云和边缘之间的可移植性受到限制,并且他们最终解决了相同的分布式系统问题,例如状态管理,弹性方法调用和事件处理。另外,许多编程运行时通常具有狭窄的语言支持和严格控制的功能集,这使得构建微服务体系结构具有挑战性。 为了使所有开发人员能够使用任何语言和框架轻松地构建便携式微服务应用程序,无论是编写新代码还是迁移现有代码,我们很高兴开源了Dapr。 构建事件驱动,无状态和有状态的应用程序 例如,在构建包含多个服务的电子商务应用程序时,您可能希望使用有状态的actor来抽象购物车服务,并为支付和物流服务调用无状态函数。编写此应用程序可能需要使用多种语言,开发人员框架和基础架构平台,以及与外部服务集成。了解和管理如此复杂的技术堆栈会使开发人员无法专注到核心业务上。 Dapr:云和边缘计算的微服务构件 Dapr是一个开源,可移植的,事件驱动的运行时,使开发人员可以轻松构建在云和边缘上运行的弹性,微服务架构的无状态和有状态应用程序。 Dapr包含所有编程语言和开发人员框架,并简化了构建应用程序(例如电子商务示例)的过程。 Dapr包含了一些构建,这些构件通过标准HTTP或gRPC API访问,所以支持各种编程语言。这些构件为所有开发人员提供了行之有效的行业最佳实践,并且每个构件都是独立的。您可以在应用程序中使用其中的一个或多个。此外,通过开源项目,我们欢迎社区添加新的构建基块,并将新的组件贡献到现有的组件中。 Dapr完全与平台无关,这意味着您可以在任何Kubernetes集群以及与Dapr集成的其他托管环境中本地运行应用程序。这使开发人员能够构建无需更改代码即可在云和边缘上运行的微服务应用程序。 Dapr构件目前处于Alpha状态 架构和构建微服务应用程序时需要许多功能。在Dapr的第一个开源alpha版本中,我们专注于提供一些最常用的构建块。 服务调用 - 弹性的服务到服务调用使方法调用(包括重试)可以在支持的托管环境中运行的任何远程服务上进行。状态管理 - 通过对键/值对的状态管理,可以轻松地编写长期运行,高可用的有状态服务以及同一应用程序中的无状态服务。状态存储是可插拔的,并且可以包括Azure Cosmos或Redis,以及组件路线图上的其他内容(例如AWS DynamoDB)。在服务之间发布和订阅消息传递 - 采用事件驱动的体系结构解决服务之间发布事件和订阅主题,以简化水平可伸缩性并使它们能够应对故障。事件驱动的资源绑定 - 资源绑定和触发器通过在事件驱动的体系结构上进一步构建规模,从而通过从任何外部资源(例如数据库,队列,文件系统,blob存储,webhooks等)接收事件或向其发送事件来实现规模和弹性。例如,可以触发代码通过Azure EventHub服务上的消息,然后将数据写入Azure CosmosDB。虚拟atcor - 种无状态和有状态对象的模式,通过方法和状态封装使并发变得简单。 Dapr在其虚拟actor运行时中提供了许多功能,包括并发,状态,用于actor激活/停用的生命周期管理以及计时器和提醒以唤醒actor。服务间的分布式追踪 - 使用W3C Trace Context标准轻松诊断和观察生产中的服务间调用,并将事件推送到跟踪和监视系统。用于可移植性和可扩展性的标准API 那么,您如何使用这些Dapr构建块?例如,假设您正在已部署到Kubernetes群集中的微服务应用程序中使用Azure Functions运行时,并且您希望利用pub / sub模式在服务之间发送消息。如今,Azure Functions运行时尚未内置此功能,但是通过在http上使用Dapr pub / sub构建块,可以轻松添加此新功能。您拥有新的开发人员力量! 此外,Dapr发布/订阅构建块具有可插入的组件模型,这意味着您可以动态选择不同的实现方式来发送消息,而无需更改任何代码。例如,您可以根据自己的喜好选择Redis,Kafka或Azure Service Bus发布/订阅Dapr组件。而且在两种情况下,代码都保持不变,包括使用标准API在不同支持的基础架构之间可移植。 为了同时实现可移植性和与现有代码的轻松集成,Dapr通过http或gRPC提供了标准API。与pub / sub示例保持一致,下面的节点代码显示如何使用“ http:// <myappaddress> / dapr / subscribe”端点订阅名为“ A”和“ B”的主题,然后在何时通知您的应用程序消息将发布到这些主题。 为了进行比较,这是使用从ASP.NET Core CreateWebHostBuilder()调用的UseStartup()处理程序以C#编写的相同代码。 向订阅了这些主题的服务发布事件就像使用主题名称和有效负载调用Dapr本地http publish API一样简单。下面的示例节点代码显示了如何使用Dapr发布API(在本地端口3500上),也可以使用curl命令来完成此操作: 如这些示例所示,在您的服务中使用Dapr不需要获取编译时间依赖性,仅需简单地使用消息主体编写URL即可。 ...

October 17, 2019 · 1 min · jiezi

????-Hyperf-多个组件-v104-更新-企业级的-PHP-微服务协程框架

v1.0.4 更新内容本次更新涉及以下组件,主要增加了 Swoole 4.4 的支持及部分组件的功能强化,以及修复了一些 Bug hyperf/async-queue hyperf/command hyperf/config hyperf/constants hyperf/consul hyperf/contract hyperf/database hyperf/db-connection hyperf/di hyperf/dispatcher hyperf/framework hyperf/http-server hyperf/pool hyperf/redis hyperf/rpc-client hyperf/service-governance hyperf/utils hyperf/websocket-server 新增#140 支持 Swoole v4.4.0.#152 数据库连接在低使用率时连接池会自动释放连接#163 constants 组件的AbstractConstants::__callStatic 支持自定义参数变更#124 DriverInterface::push 增加 $delay 参数用于设置延迟时间, 同时 DriverInterface::delay 将标记为弃用的,将于 1.1 版本移除#125 更改 config() 函数的 $default 参数的默认值为 null.修复#110 #111 修复 Redis::select 无法正常切换数据库的问题#131 修复 middlewares 配置在 Router::addGroup 下无法正常设置的问题#132 修复 request->hasFile 判断条件错误的问题#135 修复 response->redirect 在调整外链时无法正确生成链接的问题#139 修复 ConsulAgent 的 URI 无法自定义设置的问题#148 修复当 migrates 文件夹不存在时无法生成迁移模板的问题#169 修复处理请求时没法正确处理数组类型的参数#170 修复当路由不存在时 WebSocket Server 无法正确捕获异常的问题移除#131 移除 Router options 里的 server 参数关于 HyperfHyperf 是基于 Swoole 4.3+ 实现的高性能、高灵活性的 PHP 协程框架,内置协程服务器及大量常用的组件,性能较传统基于 PHP-FPM 的框架有质的提升,提供超高性能的同时,也保持着极其灵活的可扩展性,标准组件均均基于 PSR 标准 实现,基于强大的依赖注入设计,保证了绝大部分组件或类都是 可替换 与 可复用 的。   框架组件库除了常见的协程版的 MySQL 客户端、Redis 客户端,还为您准备了协程版的 Eloquent ORM、JSON RPC 服务的及客户端、GRPC 服务端及客户端、Zipkin (OpenTracing) 客户端、Guzzle HTTP 客户端、Elasticsearch 客户端、Consul 客户端、ETCD 客户端、AMQP 组件、Apollo 配置中心、阿里云 ACM 应用配置管理、基于令牌桶算法的限流器、通用连接池、熔断器、Swagger 文档生成 等组件,省去了自己实现对应协程版本的麻烦,Hyperf 还提供了 基于 PSR-11 的依赖注入容器、注解、AOP 面向切面编程、基于 PSR-15 的中间件、自定义进程、基于 PSR-14 的事件管理器、Redis/RabbitMQ 消息队列、自动模型缓存、基于 PSR-16 的缓存 等非常便捷的功能,满足丰富的技术场景和业务场景,开箱即用。 ...

July 9, 2019 · 1 min · jiezi

fong-纯typescript的node-gRPC微服务框架

简介fong: A service framework of node gRPC. github: https://github.com/xiaozhongliu/fong fong是一个完全用typescript编写的node gRPC框架, 可以基于它很方便地编写gRPC微服务应用. 一般是用来编写service层应用, 以供bff层或前端层等调用. 优点1.纯typescript编写, typescript的好处不用多说了. 并且用户使用这个框架框架时, 查看定义都是ts源码, 用户使用框架感受不到type definition文件. 2.效仿egg.js的『约定优于配置』原则, 按照统一的约定进行应用开发, 项目风格一致, 开发模式简单, 上手速度极快. 如果用过egg, 就会发现一切都是那么熟悉. 对比目前能找到的开源node gRPC框架很少, 跟其中star稍微多点的mali简单对比一下: 对比方面malifong项目风格约定 √定义查看跳转definition源代码编写语言javascripttypescriptproto文件加载仅能加载一个按目录加载多个代码生成 √中间件√√配置 √日志 √controller加载 √service加载 即将支持, 目前可以自己import即可util加载 即将支持, 目前可以自己import即可入参校验 即将支持插件机制 打算支持更多功能 TBD示例示例项目github: https://github.com/xiaozhongliu/ts-rpc-seed 运行服务使用vscode的话直接进F5调试typescript. 或者: npm start测试请求ts-node tester# 或者:npm run tscnode dist/tester.js使用目录约定不同类型文件只要按以下目录放到相应的文件夹即可自动加载. root├── proto| └── greeter.proto├── config| ├── config.default.ts| ├── config.dev.ts| ├── config.test.ts| ├── config.stage.ts| └── config.prod.ts├── midware| └── logger.ts├── controller| └── greeter.ts├── service| └── sample.ts├── util| └── sample.ts└── typings| ├── enum.ts| └── indexed.d.ts├── log| ├── common.20190512.log| ├── common.20190513.log| ├── request.20190512.log| └── request.20190513.log├── app├── packagen├── tsconfign└── tslintn入口文件import App from 'fong'new App().start()配置示例默认配置config.default.ts与环境配置config.<NODE_ENV>.ts是必须的, 运行时会合并. 配置可从ctx.config和app.config获取. ...

May 13, 2019 · 2 min · jiezi

在Mac上安装Minikube-10

在Mac上安装Minikube 1.0最近这几年,软件开发翻天覆地的变化,当个软件行业从业者,不学习新东西肯定是不行的。从微服务到容器化服务开发,其实并没有多长时间,随着Docker和Kubenetes的大热,还必须要跟上脚步才行,做一个程序员真不容易,做一个老程序员更难。 Docker和Kubenetes是什么,我这里就不介绍了,比我了解这玩意的的人,大有人在,如果你想了解,请自我学习,本文结尾也推荐了《IBM微讲堂 Kubenetes》系列,一共十个视频,看一遍基本也就都懂了。如果你开发微服务想控制和容器编排工具有互动,比如调用K8s的API之类,或者你想本Mac地装一个单机版本的K8s,我也走了一些弯路,没少浪费时间。K8s安装是一个不小的工程,但是我并不是一个很好的运维,也仅仅在开发层面了解K8s,所以装一个单机版本非常有必要,这里推荐你去安装Minikube,这就是一个单机版本的单节点K8s。其实本来就想一个安装记录,但是估计也有不少人会遇到安装的问题,那我就稍微写详细一点,帮助大家稍微少走一点弯路。 安装Minikube第一步,你先要越过GFW,至于什么是GFW怎么越过去这里就不详细说了。Minikube需要你本地装有VirtualBox,推荐你下载一个比较新的版本,因为要在上面运行一个虚拟机来跑K8s的节点。 修改网络配置我用的软件是ShadowsocksX-NG这个软件,早期版本并不支持代理,后期版本使用了privoxy实现了HTTP和Socks,但是本文只需要使用HTTP代理就好了。 首先修改进入Performance中,把Advance中的Socks5地址和HTTP中的监听地址都改为0.0,0,0就Ok了,这样你就能接收非本地的请求代理访问ss了。 安装Mac下安装太容易了,别告诉我你没有brew。 brew cask install minikube大功告成。 下载安装kubectl ,需要手工该权限,这是K8s的命令行控制工具 curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.14.0/bin/darwin/amd64/kubectlsudo mv kubectl /usr/local/bin/chmod +x /usr/local/bin/kubectl安装完Minikube 先测试下网络环境,下面命令正常说明代理服务没问题 curl -x 192.168.99.1:1087 http://baidu.com启动用下面命令,让K8s节点的docker,使用下面代理访问,insecure-registry详解见本文末尾扩展阅读 minikube start --docker-env HTTP_PROXY=http://192.168.99.1:1087 --docker-env HTTPS_PROXY=http://192.168.99.1:1087 --docker-env NO_PROXY=127.0.0.1/24 --insecure-registry=192.168.99.1:5000见到下面log为启动成功。 ???? minikube v1.0.0 on darwin (amd64)???? Downloading Kubernetes v1.14.0 images in the background ...???? Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...???? "minikube" IP address is 192.168.99.105???? Configuring Docker as the container runtime ... ▪ env HTTP_PROXY=http://192.168.99.1:1087 ▪ env HTTPS_PROXY=http://192.168.99.1:1087 ▪ env NO_PROXY=127.0.0.1/24???? Version of container runtime is 18.06.2-ce⌛ Waiting for image downloads to complete ...E0503 17:26:45.170139 5798 start.go:209] Error caching images: Caching images for kubeadm: caching images: caching image /Users/freewolf/.minikube/cache/images/k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64_1.14.13: fetching remote image: Get https://k8s.gcr.io/v2/: dial tcp 74.125.203.82:443: i/o timeout✨ Preparing Kubernetes environment ...❌ Unable to load cached images: loading cached images: loading image /Users/freewolf/.minikube/cache/images/gcr.io/k8s-minikube/storage-provisioner_v1.8.1: stat /Users/freewolf/.minikube/cache/images/gcr.io/k8s-minikube/storage-provisioner_v1.8.1: no such file or directory???? Pulling images required by Kubernetes v1.14.0 ...???? Launching Kubernetes v1.14.0 using kubeadm ... ⌛ Waiting for pods: apiserver proxy etcd scheduler controller dns???? Configuring cluster permissions ...???? Verifying component health .....???? kubectl is now configured to use "minikube"???? Done! Thank you for using minikube!中间的错误信息说明本地的cache中没有所需文件都要连接互联网拉取。中间时间很长需要20分钟,因为要下载1g的内容。 ...

May 4, 2019 · 2 min · jiezi

容错性好、易于管理和便于观察:浅谈如何利用K8s全面拥抱微服务架构

KubeCon + CloudNativeCon 论坛,作为 CNCF 的旗舰会议,自2016年以来已经在北美和欧洲两地的旧金山、伦敦、硅丘(奥斯汀)、哥本哈根等知名城市举办。2018年11月15日,KubeCon + CloudNativeCon 论坛首次来到中国,在上海跨国采购会展中心召开并获得了圆满成功。在去年的论坛上,CNCF不仅邀请到了Liz Rice、Janet Kuo等开源技术大牛到场为KubeCon + CloudNativeCon 在中国举行的首秀呐喊助威,更吸引到了包括美国、日本、印度在内的五大洲48个国家的开源精英前来参与。期间,有954家公司派代表到场展示自己的理念或者聆听精彩的技术分享。据统计,2018年盛会的参会者超过2500人,CNCF 为参会者提供了13场次的主题演讲、97场次的分组会议、55场次的维护者会议和15场次的快闪演讲。华为云、阿里云、腾讯云、微软、GitLab、Lyft等众多知名企业纷纷登台为大家分享相关的产品和技术架构,并为在场观众解答了相关问题。在上届论坛上,大家询问最多的,就是在 K8s(Kubernetes)架构上的使用精髓,而其中,比较有代表性的问题,则是企业如何利用 K8s 作为微服务架构,并且如何通过这样的部署来提升企业的自身价值。那么,什么是微服务架构呢?其实,微服务架构是与当前常用的单体架构相比较而言的。单体架构虽然方便管理,易于规划,但是灵活性和稳定性还是有所欠缺的,甚至一旦局部架构受损则可能面临全盘崩溃的危险;而且单体架构的迭代操作,比较复杂,部署速度慢不说,还会出现阻塞持续集成的现象,这对于要求时效性且相对复杂的生产环境来说,是不言而喻的灾难。基于此,便出现了小的模块化的自治服务架构,即我们常说的微服务架构。因为它所有的节点都被连接到了API网关,所以API网关的用户都会自动连接到这个完整的系统来调用或者聚合所需资源,来完成整个工作。所以,微服务架构在目前来看,基本解决了单体架构的弊端,这如同使用并联的灯泡组,即使一个灯泡损坏,亦不会影响全局的稳定和整体的生产进度,更不会出现整个局部系统的损坏而导致整体系统全面崩塌的灾难性后果。众所周知的是,任何一种架构的运用都会面临一些问题,我们采用的微服务架构也不例外。虽然微服务架构本身具有稳定、轻量、高速的特性,但是在现实的企业生产环境部署过程中,也会出现诸如调度、负载均衡、集群管理、有状态数据的管理等问题。而作为一切以服务为中心的K8s,则为我们提供了解决上述问题的最佳方式。K8s拥抱微服务就成为大势所趋。作为上届大会的焦点 - K8s如何更好的拥抱微服务?主题演讲有这些分享:Zhenqin (Alan) Liao(华为云 PaaS 服务产品部部长)的“垂直扩展,Kubernetes 如何加速各行业的云原生移动”Vicki Cheung(Lyft 工程经理)的“Kubernetes 是架构的基础层”Brendan Burns(杰出工程师及Microsoft K8s 联合创始人)的“Kubernetes 无服务器架构的现在和未来”专题演讲也分享了不少:Tony Erwin和Jonathan Schweikhart(IBM)的“将企业微服务从Cloud Foundry迁移到Kubernetes”Xiang Li(阿里巴巴)的“日新月异的 Sigma:在阿里巴巴使用 Kubernetes”Dan Romlein和Spencer Sugarman(Google)的“用户介面:利用 Kubernetes Dashboard 并决定其未来”Peter Zhao和Yuan Ji(ZTE)的“Kubernetes:使用、贡献并享受它!“Land Lu和Zhang Lei Mao(Canonical)的“利用 MicroK8s 和 Kubeflow 达成的 Kubernetes CICD 小技巧”Hui Chi(PetroChina)和Kai Chen(Alauda)的“石油巨头与Kubernetes, Microservice & DevOps共舞”Shikha Srivastava和Erica Brown(IBM)的“通过 Kubernetes 实现从容器化应用到安全和缩放”YIN SUN(小米)的“从 Mesos 到 Kubernetes”那么,在2019年,这些议题又会有哪些大咖加以完善,并与您分享更新的实战观点呢?敬请关注,今年2019年,CNCF和LF为您即将呈现的开源技术盛宴 - KubeCon + CloudNativeCon 和 Open SourceSummit(原LC3)。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票! ...

March 7, 2019 · 1 min · jiezi

微服务

微服务架构提供了将大型应用拆分为多个可相互作用的更小服务的一种手段.每个服务独立交付,因此每个服务可以脱离主体,独立部署升级拓展替换.服务间通信通常依赖HTTP调用网络连接.Web sockets, message queuespub/subRPC也可以用于连接独立组件.每个独立服务专注单一任务,通常按内务单元区分,受 RESTful 规范制约.课程目标是详述在微服务潮流下开发一款应用. 这里侧重怎么做而较少讨论为什么这么做. 微服务很难. 他们有很多挑战和问题难以解决. 开始拆分你的大块应用前牢记这一点.利Separation of concerns 关注分离服务间清晰的分离, 开发可以更容易专注他们的专长领域,比如 语言,框架, 依赖, 工具, 还有 构建管道. 例如, 一个 前端 JavaScript 工程师可以开发面向客户的视图,不需要理解后端 API 之下的代码.他可以自由选择语言框架, 只需要和后端交流通过异步请求消费 RESTful API.换句话说, 鉴于服务凭借 APIs 通讯开发可以将服务看做一个黑盒, 将实现和复杂隐藏.也就是说, 这是一个很好的理念来创建全机构的标准来确保每一团队可以一起工作运行–比如代码质检和风格检查, 代码检查, API 设计.清晰的分离意味着错误最大限度的锁定在开发工作的服务内. 因此,你可以分配给初级程序员非关键服务,即使服务挂掉,整个应用也不受影响.因为每个服务独立部署,更少的耦合也是的扩展更容易. 对消除团队等待另一个所依赖的团队完成工作现象有一定帮助.更小的代码库更少代码库对更容易理解有益,因为不需要掌握整个系统. 只需要 固化 API 设计, 这意味着微服务栈中通常可以更快开发更容易测试重构和拓展. 记住, 在所有服务站维护一致的代码标准很重要,因此对于开发中从一个服务转到另一个服务很容易.加速反馈闭环微服务中,开发掌握应用的整个生命周期,从立项到交付.替换团队调整使用特定的技术集–比如客户端UI, 服务端, 等等. 因为这样他们可以更清晰的看到应用在真是环境中如何使用. 这加速了反馈闭环, 更容易修复 bugs 和迭代.弊设计复杂决定分离你应用的一块到微服务不是一个容易的任务. 通常重构为一个独立的模块在全部大块中更容易, 而不是分出去.一旦你分出去没有回头路.网络复杂在一个大块应用,通常所有事在一个单独的线程,所以不需要很多次调用其它服务. 由于你拆分你的应用为微服务, 你会发现你现在不得不将函数调用改为网络调用.这会导致很多问题特别是如果多个应用需要和其他服务通信, 结果在网络请求方面产生乒乓效应. 你也不得不考虑服务的整体下降.基础设施 infrastructure多服务下,复杂转化从数据库到平台和基础设施. 消耗很大. 而且,不得不使用正确的工具和适当的人力资源来管理.数据持久化多数应用有类似状态层,像数据库任务队列. 微服务栈也需要跟踪服务在哪里销毁和全部被摧毁的实例,这样,当一个特定服务的新实例启动时, 通信量可以适当的调整. 这通常称为服务发现.由于我们将处理容器, 我们需要特别关注如何处理状态容器因为他们不应下降.隔离一个特定服务的状态使得他不被分享或复制是一个难以描述的困难. 你不得不经常处理各种不同来源的事实,不得不频繁的调解. 再说一次, 归结为设计.集成测试通常, 开发微服务架构, 你不能完整测试所有服务直到你部署到预发或生产服务器. 获取反馈的时间花费太长. 幸运的是, docker 通过更容易的连接小的独立的本地服务有助于加速这一过程.日志, 监听, 和调试同样困难.跟多微服务测试, 参考Testing Strategies in a Microservice Architecture ...

February 27, 2019 · 1 min · jiezi

使用Envoy 作Sidecar Proxy的微服务模式-1.熔断

本博客是深入研究Envoy Proxy和Istio.io 以及它如何实现更优雅的方式来连接和管理微服务系列文章的一部分。这是接下来几个部分的想法(将在发布时更新链接):断路器(第一部分)重试/超时(第二部分)分布式跟踪(第三部分)Prometheus的指标收集(第四部分)服务发现(第五部分)第一部分 - 使用envoy proxy 熔断这篇第一篇博文向您介绍了Envoy Proxy实现的熔断功能。有意进行一些简单的演示,因此我可以单独说明模式和用法。请下载此演示的源代码并按照说明进行操作!该演示由一个客户端和一个服务组成。客户端是一个Java http应用程序,模拟对“上游”服务进行http调用(注意,我们在这里使用Envoys术语,并贯穿整个repo)。客户端打包在docker.io/ceposta/http-envoy-client:latest的Docker镜像中。除了http-client Java应用程序之外,还有Envoy Proxy的一个实例。在此部署模型中,Envoy被部署为服务的sidercar(在本例中为http客户端)。当http-client进行出站调用(到“上游”服务)时,所有调用都通过Envoy Proxy sidercar。这些示例的“上游”服务是httpbin.org。 httpbin.org允许我们轻松模拟HTTP服务行为。它很棒,所以如果你没有看到它,请查看它。这个熔断器演示有自己的envoy.json配置文件。我绝对建议您查看配置文件每个部分的参考文档,以帮助理解完整配置。 datawire.io的优秀人员也为Envoy及其配置提供了一个很好的介绍,你也应该检查一下。运行 circuit-breaker demo运行熔断器演示,请熟悉演示框架,然后运行:./docker-run.sh -d circuit-breaker熔断器的Envoy配置如下所示(请参阅此处的完整配置):“circuit_breakers”: { “default”: { “max_connections”: 1, “max_pending_requests”: 1, “max_retries”: 3 }}该配置文件允许我们实现下面的功能:限制我们对上游集群的HTTP / 1连接的数量,如果我们超过设定限制则将它们短路。限制排队/等待连接可用的请求数量,如果我们超过设定限制则将它们短路。限制在任何给定时间的总并发重试次数(假设重试策略已到位)有效地实施重试配额。我们来看看每个配置。我们现在将忽略最大重试次数设置有两个原因:我们的设置并没有多大意义;我们不能有3个并发重试,因为我们只允许1个HTTP连接和1个排队请求。我们实际上没有为此演示制定任何重试政策;我们可以在重试演示中看到重试。无论如何,此处的重试设置允许我们避免大型重试风暴 - 在大多数情况下,这可能会在处理与群集中所有实例的连接时出现问题。这是一个重要的设置,我们将回到重试演示。max_connections让我们看看当应用程序中有太多线程试图与上游集群建立太多并发连接时,envoy会做什么。回想一下我们的上游httbin集群的熔断设置如下所示(请参阅此处的完整配置):“circuit_breakers”: { “default”: { “max_connections”: 1, “max_pending_requests”: 1, “max_retries”: 3 }}如果我们查看./circuit-breaker/http-client.env设置文件,我们将看到最初我们将开始运行单个线程,该线程创建一个连接并进行五次调用并关闭。NUM_THREADS=1DELAY_BETWEEN_CALLS=0NUM_CALLS_PER_CLIENT=5URL_UNDER_TEST=http://localhost:15001/getMIX_RESPONSE_TIMES=false我们来验证一下。运行演示:./docker-run.sh -d circuit-breaker这将启动了客户端应用程序,并启动了Envoy Proxy。我们将直接向Envoy Proxy发送流量,以使其帮帮助处理熔断。让我们调用我们的服务:docker exec -it client bash -c ‘java -jar http-client.jar’我们将看到以下的输出:using num threads: 1Starting pool-1-thread-1 with numCalls=5 delayBetweenCalls=0 url=http://localhost:15001/get mixedRespTimes=falsepool-1-thread-1: successes=[5], failures=[0], duration=[545ms]我们也能看到我们五次的调用成功了。让我们看一下,Envoy为我们收集的metrics指标:./get-envoy-stats.shEnvoy为我们采集了很多的追踪指标!让我们通过以下方式查看:/get-envoy-stats.sh | grep cluster.httpbin_service这将显示我们配置的名为httpbin_service的上游群集的度量标准。快速浏览一下这些统计数据,并在Envoy文档中查找它们的含义。需要注意的重要事项在这里提到:cluster.httpbin_service.upstream_cx_http1_total: 1cluster.httpbin_service.upstream_rq_total: 5cluster.httpbin_service.upstream_rq_200: 5cluster.httpbin_service.upstream_rq_2xx: 5cluster.httpbin_service.upstream_rq_pending_overflow: 0cluster.httpbin_service.upstream_rq_retry: 0这告诉我们我们有1个http / 1连接,有5个请求(总数),其中5个以HTTP 2xx(甚至200个)结束。大!但是如果我们尝试使用两个并发连接会发生什么?首先,让我们重置统计数据:./reset-envoy-stats.shOK让我们用2个线程发起这些调用:docker exec -it client bash -c ‘NUM_THREADS=2; java -jar http-client.jar’我们应该可以看到如下的输出:using num threads: 2Starting pool-1-thread-1 with numCalls=5 delayBetweenCalls=0 url=http://localhost:15001/get mixedRespTimes=falseStarting pool-1-thread-2 with numCalls=5 delayBetweenCalls=0 url=http://localhost:15001/get mixedRespTimes=falsepool-1-thread-1: successes=[0], failures=[5], duration=[123ms]pool-1-thread-2: successes=[5], failures=[0], duration=[513ms]我们启动的一个线程中有5个成功,但其中另外一个线程一个都没有成功!该线程的所有5个请求都失败了!让我们再看看envoy的统计数据:./get-envoy-stats.sh | grep cluster.httpbin_service我们将看到如下的输出:cluster.httpbin_service.upstream_cx_http1_total: 1cluster.httpbin_service.upstream_rq_total: 5cluster.httpbin_service.upstream_rq_200: 5cluster.httpbin_service.upstream_rq_2xx: 5cluster.httpbin_service.upstream_rq_503: 5cluster.httpbin_service.upstream_rq_5xx: 5cluster.httpbin_service.upstream_rq_pending_overflow: 5cluster.httpbin_service.upstream_rq_retry: 0从这个输出中我们可以看到只有一个连接成功!我们最终得到5个请求,导致HTTP 200和5个请求以HTTP 503结束。我们还看到upstream_rq_pending_overflow已经增加到5.这表明断路器在这里完成了它的工作。它会使任何与我们的配置设置不匹配的调用短路。我们将max_connections人为设置为一个小点的数字,在这种情况下为1,为了说明Envoy的断路功能。这不是一个现实的设置,但希望有助于说明这一点。max_pending_requests让我们运行一些类似的测试来运行max_pending_requests设置。回想一下我们的上游httbin集群的熔断设置如下所示(请参阅此处的完整配置):“circuit_breakers”: { “default”: { “max_connections”: 1, “max_pending_requests”: 1, “max_retries”: 3 }}我们想要做的是模拟在单个HTTP连接上同时发生的多个请求(因为我们只允许max_connections为1)。我们期望请求排队,但是Envoy应该拒绝排队的消息,因为我们将max_pending_requests设置为1。我们想要设置队列深度的上限,目的不允许重试风暴,恶意下游请求,DoS和我们系统中的bug。继续上一节,让我们重置特使的统计数据:./reset-envoy-stats.shOK让我们启动1个线程(即1个HTTP连接)调用客户端,但是并行发送我们的请求(默认情况下是5个批次)。我们还希望随机化我们发送的延迟,以便事情可以排队:docker exec -it client bash -c ‘NUM_THREADS=1 && PARALLEL_SENDS=true && MIX_RESPONSE_TIMES=true; java -jar http-client.jar’我们应该看到如下的输出:Starting pool-1-thread-1 with numCalls=5 parallelSends=true delayBetweenCalls=0 url=http://localhost:15001/get mixedRespTimes=truepool-2-thread-3: using delay of : 3pool-2-thread-2: using delay of : 0pool-2-thread-1: using delay of : 2pool-2-thread-4: using delay of : 4pool-2-thread-5: using delay of : 0finished batch 0pool-1-thread-1: successes=[1], failures=[4], duration=[4242ms]我们的四个要求失败了……让我们查看envoy的统计数据:./get-envoy-stats.sh | grep cluster.httpbin_service | grep pending果然,我们看到我们的4个请求被短路了:cluster.httpbin_service.upstream_rq_pending_active: 0cluster.httpbin_service.upstream_rq_pending_failure_eject: 0cluster.httpbin_service.upstream_rq_pending_overflow: 4cluster.httpbin_service.upstream_rq_pending_total: 1什么时候服务完全停止?我们已经看到了Envoy对集群的短路和批量处理线程有什么断路设施,但是如果集群中的节点完全崩溃(或者似乎下降)怎么办?Envoy具有“离群值检测”设置,可以检测群集中的主机何时不可靠,并且可以完全从群集摘掉它们(一段时间)。需要了解的一个有趣现象是,默认情况下,Envoy会根据负载平衡算法,最多摘除某一数量的不可靠的主机。如果太多(即> 50%)的主机被认为是不健康的,那么Envoy的负载均衡器算法将检测到一个恐慌阈值,并且只会对所有主机进行负载均衡。此恐慌阈值是可配置的,并且为了获得断电功能,可以在严重中断期间为所有主机提供负载(一段时间),您可以配置异常值检测设置。在我们的示例断路器)envoy.json配置中,您可以看到以下内容:outlier_detection" : { “consecutive_5xx”: 5, “max_ejection_percent”: 100, “interval_ms”: 3 } 让我们测试一下这个案例,看看会发生什么。首先,重置统计数据:./reset-envoy-stats.shOK接下来,让我们使用一个URL来调用我们的客户端,该URL将返回HTTP 500结果。我们将发起十次调用,因为我们的异常检测将检查5个连续的5xx响应,因此我们将要发起多于5次的调用。docker exec -it client bash -c ‘URL_UNDER_TEST=http://localhost:15001/status/500 && NUM_CALLS_PER_CLIENT=10; java -jar http-client.jar’我们应该看到这样的响应,其中所有调用都失败了(正如我们所期望的那样:其中至少有5个会返回HTTP 500):using num threads: 1Starting pool-1-thread-1 with numCalls=10 parallelSends=false delayBetweenCalls=0 url=http://localhost:15001/status/500 mixedRespTimes=falsepool-1-thread-1: successes=[0], failures=[10], duration=[929ms]现在让我们检查一下Envoy的统计数据,看看究竟发生了什么:./get-envoy-stats.sh | grep cluster.httpbin_service | grep outliercluster.httpbin_service.outlier_detection.ejections_active: 0cluster.httpbin_service.outlier_detection.ejections_consecutive_5xx: 1cluster.httpbin_service.outlier_detection.ejections_overflow: 0cluster.httpbin_service.outlier_detection.ejections_success_rate: 0cluster.httpbin_service.outlier_detection.ejections_total: 1我们可以看到我们断电了连续5xx检测!我们还从负载均衡组中删除了该主机。 ...

February 22, 2019 · 2 min · jiezi

猫头鹰的深夜翻译:微服务概述

前言在过去几年中,出现了微服务架构的理念,它提倡将应用程序设计为可独立部署到额服务套件。虽然对于这种架构风格没有明确的定义,但是它在业务能力,自动部署,智能终端以及语言和数据的分散控制方面有共同的特征。微服务是软件架构中的一个新名词。在过去几年中,可以看到很多项目都采用了这种风格的架构,以至于他已经成为了构建企业应用程序的默认样式。然而,并没有太多的信息可以描述微服务架构的风格以及如何实现这种风格。简而言之,微服务架构是将单应用开发成为一套分别运行在独立的线程并通过轻量级的机制如HTTP进行访问的方法。这些服务围绕业务功能构建,并且可以独立的全自动部署。这些服务无需集中管理,可以用不同的编程语言编写,并使用不同的数据存储技术。在开始介绍微服务风格之前,可以先将其和单机应用做一个对比:单机应用是指将一个应用作为一个单元进行开发。企业应用通常包含三个部分:客户端UI(包含在用户浏览器上的HTML页面和JS脚本),一个数据库(关系型数据库)和服务端应用。服务端应用会处理HTTP请求,执行业务逻辑,从数据库获取和更新数据,并选择和生成HTML页面返回给浏览器。系统的任何变更都需要重新构建和部署新版本的服务端应用。单机应用是构建系统的一种通用方法。处理请求的所有业务逻辑都运行在单线程中,你可以根据开发语言将应用份极为类,方法和命名域。你可以在笔记本上运行和测试应用,并使用部署流水线来确保变更已经进行过测试并部署到生产环境。你可以通过在负载均衡器后面运行许多实例来水平扩展单机应用。单机应用在初期相当成功,但渐渐的人们会感到挫败–尤其当应用被部署到云商之后。变更周期被绑定在一起:应用的一个小变更需要整个应用重新构建和部署。随着时间的推移,通常很难保持一个良好的模块化结构,使得更难以将对模块的变更维持在单个模块内。扩展需要扩展整个应用程序,而不是应用中需要更多资源的部分。这种挫败感引向了微服务架构风格:将应用构架为一组服务。每个服务不仅能够独立的部署和扩展,还能够提供一个稳定的模块边界,并且每个服务用不同的语言开发。他们还能交由不同的团队开发。我们并没有表示微服务风格是创新的发明,它可以追溯回Unix的设计理念。但是我们认为有人还没能认真的考虑微服务架构,如果使用这种架构,软件开发将会更方便。微服务架构的特点微服务架构虽然没有正式的定义,但是我们可以尝试描述这种架构的共同特点。就如别的试图描述共同特征的定义一样,不是所有的微服务架构都具有所有的共同特征,即便我们期望大多数的微服务架构能够拥有这种特征。因此我们不会规定一定要遵循的微服务定义。通过服务组件化从参与软件行业以来,我们就一直期望通过组装组件的方式构建系统,就像现实世界那样。在过去几十年中,我们已经看到了各种语言的共有库的大量发展。说到组件,我们遇到了何为组件的挑战。我们认为,组件是可独立替换和升级的软件单元。微服务架构也会使用共有库,但是组件化软件的主要方法是将其拆分为服务。我们将库定义为链接到程序并使用内函数调用的组件,而服务则是进程外的组件,他们通过Web服务或是远程调用之类的机制进行调用(这与OO程序中的服务的概念是不同的)将服务用作组件(而不是库)的一个主要原因是服务可以独立部署。如果单进程中有一个包含多个库的应用程序,任何一个库的变更都需要重新部署整个应用。但是如果应用被分解为多个服务,那么单个服务的变更只需要重新部署单个服务就可以了。这也不是绝对的,某些变更需要同时变更服务接口,从而导致多个服务的调整。但是一个好的微服务架构需要最小化这种变更,通过内聚服务边界和遵循规范的演化机制。将服务用作组件的另一个结果是更明确的组件接口。大多数的语言都没有用于显式定义接口的良好机制。通常就是文档化接口,防止客户端破坏了组件的封装,从而导致组件之间的过紧的耦合。通过服务之间的远程调用避免了这个问题。使用服务化也是有缺点的。远程调用比进程内方法调用代价更高,因此远程API使用起来更加笨拙。如果需要变更组件之间的职责分配,这种跨进程的变更将会更加麻烦。在第一次类比中,我们将服务与运行进程进行比较,但那只是一个粗略的对比。一个服务往往包含多个进程,这些进程会并行的开发和部署,比如该服务会包含应用进程和数据库进程。围绕业务进行组织当试图将大应用拆分成各个部分时,通常管理者会从技术层面出发,将其拆分为UI团队,服务端逻辑开发团队和数据库团队。当团队按照这些方式分开时,即使是简单的更改也可能导致跨团队项目需要时间和预算批准。设计系统的任何组织都将产生一种设计,其结构体现了组织内的沟通结构。– Melvyn Conway, 1967而微服务风格的拆分方法是不同的,它是围绕着业务能力进行拆分的。划分出的团队往往是扩领域的成员所组成的,即一个服务的开发团队包含了开发完整应用的所有能力。跨职能团队负责构建和运营每个产品,每个产品之间通过消息总线进行通信。大型单机应用程序也可以围绕业务功能进行模块化,尽管这种情况不是很常见。当然,我们会敦促一个开发庞大的单机应用程序的团队沿着业务线划分自己。我们在这里看到的主要问题是,它们往往围绕太多的背景进行组织。此外,我们看到模块化生产线需要大量的规则来维护。更明确的服务组件的分离使得更容易保持团队边界清晰。产品而非项目我们看到的大多数应用程序开发工作都使用项目模型:其目的是提供一个将被完成的软件。完成后,软件将移交给维护组织,构建它的项目团队将被解散。微服务支持者倾向于避免使用这种模式,而更倾向于认为团队应该在产品的整个生命周期内拥有产品。对此的一个共同认知来源于亚马逊的“你构建,你维护”的里面,开发团队对生产中的软件负全部责任。这使开发人员能够看到他们的软件在生产中的行为,并增加与用户的联系,因为他们必须提供软件的支持工作。产品的内核与业务要求紧密的联系在一起。不再仅仅将软件视为一组要完成的功能,它还有一个持续的使命,即如何帮助其用户增强业务能力。并不是说单机应用程序无法使用这种思想,更是因为较小的服务粒度可以使得开发人员和用户之间更容易建立和维持联系。智能端点和非智能管道在不同进程之间建立通信结构时,我们已经看到许多产品和方法都强调将智能放入沟通机制本身。一个很好的例子是企业服务总线(ESB),ESB产品通常包括用于消息路由,编排,转换和应用业务规则的复杂工具。微服务社区倾向于另一种方案:智能终端和非智能管道。从微服务构建的应用程序旨在尽可能低耦合和高内聚:拥有自己的领域逻辑,在经典的Unix意义上更像是管道中的过滤器,接收请求,在其之上执行领域逻辑,然后输出响应。使用最多的两个协议是HTTP请求响应协议和消息队列。HTTP协议是整个互联网架构的基础。通过HTTP协议,经常使用的资源可以通过缓存来减少程序员的工作。第二种方法是轻量级的消息总线之上的消息队列。选择的基础设施通常是非智能的(仅进行消息路由)。像RabbitMQ或ZeroMQ这样的简单实现仅仅提供可靠的异步结构。智能的部分交给服务终端来完成。在单机应用中,组件在同一个进程中执行,彼此间的通信是通过方法调用来实现。将单机应用变更为微服务结构最大的挑战之一就是决定组件之间的通信方式。从内存方法调用到RPC的简单转换会导致复杂的通信软件无法正常执行。相反,你需要用粗粒度的方法替换细粒度的通信。去中心化管理集中治理的后果之一是在单一技术平台上实现标准化的趋势。经验表明,这种方法是有限的 - 并非所有问题和解决方案都是一一对应的。我们更喜欢使用正确的工具来完成工作,虽然单机应用程序可以在一定程度上利用不同的语言,但这并不常见。将单机应用拆分为服务后,我们可以在构建每个组件时拥有选择权。您想使用Node.js构建一个简单的报告页面吗?完全可以。C++来开发实时组件?没有问题。您想要换数据库,以更好地适应一个组件的读取行为?放手去尝试吧。当然了,有这种选择权并不意味着你必须这么做。但是用这种方式分割系统才使得我们拥有了这种选择权。构建微服务的团队也更喜欢采用不同的标准方法。相比于使用在文档上某处记录的一套规则,他们更倾向于构建有用的工具,使得开发者在面对问题时可以使用这种工具来解决。这些工具往往会在多个团队中广泛使用。现在git和github已成为主流的版本控制系统,开源实践在内部变得越来越普遍。Netflix是遵循这一理念的组织的一个很好的例子。以库的形式共享有用的,尤其是经过实战考验的代码,可以鼓励其他开发人员以类似的方式解决类似的问题,并且可以选择不同的方法。共享库往往侧重于解决数据存储,进程间通信的常见问题。去中心化的数据管理去中心化的数据管理表现为几种形式。在最抽象的层面上,它意味着概念模型在不同系统之间会有所不同。这是在大型企业中集成时的常见问题,客户的销售视图将与运维视图不同。销售视图中称为客户的某些内容可能根本不会出现在支持视图中。而二者共有的内容可能具有不同的属性或者(更糟糕)共同的但是语义不同的属性。此问题在应用程序之间很常见,但也可能在应用程序中发生,特别是当该应用程序分为单独的组件时。一个有用的思考方式是领域驱动设计。领域驱动设计将复杂域划分为多个有界上下文,并映射出它们之间的关系。这个过程对单体应用和微服务架构都很有用,但是微服务本身的关联和自身的服务边界就帮助明确了这种关联。除了分散概念模型决策之外,微服务还分散了数据存储决策。虽然单个应用程序更喜欢单个逻辑数据库来存储持久性数据,但企业通常更喜欢跨越一系列应用程序的单个数据库。微服务更喜欢让每个服务管理自己的数据库,可以是同一数据库技术的不同实例,也可以是完全不同的数据库系统。跨微服务分散数据责任对更新操作有影响。处理更新的常用方法是在更新多个资源时使用事务来保证一致性。这种方法通常用于单机结构中。用这样的事务有助于保持一致性,但会产生显着的时间耦合,这在多个服务中是有问题的。众所周知,分布式事务很难实现,因此微服务架构强调服务之间的无事务协调。明确提出一致性可能只是最终的一致性,而问题则通过补偿操作来处理。选择以这种方式管理不一致是许多开发团队面临的新挑战,但是它往往符合大多数的业务要求。企业通常会接收一定程度的不一致,以便快速响应需求,同时采取某种反向流程来应对错误。要修复错误的成本低于在更大的一致性下丢失业务的成本,那么权衡是值得的。自动化基础设施在过去几年中,基础设施自动化技术发生了巨大变化:云的发展降低了构建,部署和运行微服务的操作复杂性。许多使用微服务构建的产品或系统都是由具有丰富的持续交付经验的团队构建的。以这种方式构建软件的团队广泛使用基础设施自动化技术。这在下面显示的构建管道中说明:

January 2, 2019 · 1 min · jiezi

猫头鹰的深夜翻译:集成方式是如何影响微服务架构的

前言当万维网首次出现时,集成不同类型的操作系统是一项主要的挑战。HTTP的出现使得不同的操作系统之间可以通过超文本使用统一的协议进行通信。当微服务的架构出现后,系统的集成带来的挑战没有太大的分别:多种实现技术在物理网络上彼此分离,需要相互通信。从最终用户的角度来看,微服务的集成在系统的无缝体验方面起着至关重要的作用。正确集成的系统还有助于实现分布式系统的优势:它们可以在service级实现扩容提高效率,并且能够在满足业务需求的同时降低架构成本。另一方面,错误集成的系统可能会彻底破坏微服务架构的好处:它可能会导致数据丢失和继承问题。这些问题通常很难追踪,同时用户会受到不良的影响。无缝集成有许多因素需要考虑。我们需要针对不同的场景选择最合适的集成方式。接下来,我们会介绍不同集成方式的优缺点。数据库集成在这种模式下,两个或多个服务都读写自同一个中心数据库。所有的服务连接到同一个中心数据库上。我们可以用一个银行系统来解释这种架构。数据库集成的显著优点之一是简单。事务的管理和别的模式相比更加直观。这可能是使用最广泛的一种模式,同时也可能是最被滥用的。这个模式下服务耦合度较高,使得微服务较难以变更和扩展。定义数据的所属权以及更新schema会很麻烦,因为需要重新编译和部署所有相关的服务。它导致大爆炸形式的集成。这种类型的集成可能在维护微服务的自治性方面存在问题。在大规模应用的场景下,唯一的选择是在数据库中投入更多硬件,即使这样,也很难避免数据库和行级争用中的死锁。想情况下,我们不建议将此模式用于服务间通信。它可以用于分阶段微服务部署的早期阶段。换句话说:如果你使用它,很快就会抛弃它。同步API调用在这种集成模式下,服务之间通过API同步的通信。所有的数据访问都是通过API以请求响应的方式实现,调用方等待API的返回数据做进一步处理。在上面的例子中,如果事务服务需要读取用户信息,可以通过调用用户服务的API来实现。这种方式在直接数据库的调用之上进行了良好的抽象,并在调用技术选择方面提供了极好的灵活性。它隐藏了实现的细节:使得我们可以在不影响客户的前提下自由的变更。比如,用户模块可能使用的是Java和MySQL,而事务模块可能使用的是SQL Server和.NET,但是它们彼此之间还是可以通过API进行通信。但是,这个和直接的数据库集成模式没有本质的区别。在数据库调用之上添加另一个网络调用也会j降低可扩展性:增加了负载,降低了性能。这种集成模式也使事务管理变得困难并且影响了服务自治,因为服务依赖于彼此的正常运行。在微服务中,如果必须在系统边界之外同步读取数据,那就是SOA架构的感觉了。在某些场景下,这种集成模式是最佳的甚至是不可避免的。API集成模式中安全令牌是一个主要的应用场景,因为这些token生命周期短,而且在使用之前才生成。如果可能的话,应谨慎使用同步API调用。如果使用这种模式,它们应该版本化并且应该与熔断机制一起使用。ETL (Extract, Transform, and Load)ETL需要按预定义的时间表通过后台进程同步数据。这些数据可以是推模式或者拉模式。它是异步的,这意味着服务可以在不等待“回调”的情况下执行。这种集成模式也很好地隐藏了实现细节。它提供了合理的解耦,因为服务不依赖于彼此的正常运行。实时用户不会受到正常运行时间或处理时间的影响。ETL过程需要改变源和目标数据库。通过ETL集成,数据一致性取决于计划和持续时间。弄清楚变化的可能会使应用变得太复杂。在这种场景下,团队不得不导出全部的数据。这使得流程运行时间非常长,严重影响了它们的实用性。报告性的服务非常适用于这种集成。这些ETL的过程通常会有些耗时,只有在系统中可接受旧数据时才应使用它们。消息在这种模式下,服务彼此之间通过指令和事件交换信息它们通过消息中介如RabbitMQ,MSMQ等。在上面的例子中,事务服务建立了一个账号余额变更的时间并且放到消息中间件中。奖励服务,积分服务和消息服务分别订阅这个事件,并且进行处理。这是发布订阅模式,还有很多别的消息模式。只要正确的实现,消息提供了非常好的解耦。它提供了非常高的灵活性,只要能够正确的通信。将数据推送给订阅者使得数据发送的部分非常容易完成。而且发送方完全不会受订阅端处理细节的影响。不正确的服务或事务边界可能使消息传递实现复杂化。而且,这种模式提供的松耦合影响一致性为。它需要高度的规范化才能正确实现消息传递,而没有经验的团队可能会很挣扎。两种类型的消息典型的消息传递解决方案建立在传输属性的基础之上。在较高的层面上,这些传输可以分为两类:消息队列和消息流。排队解决方案涉及处理实时数据。一旦消息被成功消费,则这条消息会从队列中出队。只要处理能够跟上,队列就不会累积,也不会占用太多空间。但是,在扩展订户的情况下,无法保证消息的顺序性。在流式传输解决方案中,消息按顺序存储在流中。它发生在消息传输本身。订户在流上的位置保留在传输上。它可以根据需要在流上倒置。这对于故障和新的订阅方案非常有利。但是,这取决于流的长度。从存储角度来看,它需要更多配置,因此需要对流进行归档。这里的典型用例假设系统能够处理有些陈旧的数据。如果情况并非如此,我们需要更多地分析业务领域并理解原因。在我们的示例中,当事务更新发生时,信用分数更新不一定需要实时发生。消息在这个场景下非常适合。我们可以相应地设置用户的期望,并允许服务管理自己的负载。总结每一种微服务架构都不同,没有绝对完美的方案。当我们使用它们时,我们需要结合故障情景,驱动这些集成模式的组合。比如,Netflix使用消息传递来移动数据,如果消息不可用或数据仍在传输中,它们会回退同步API。在每种情况下,理想的是实现最灵活和可扩展的微服务架构,但是必须首先考虑实施细节和自己的能力。这里的关键是在需要扩展和自治时使用异步模式。要实现这一目标,您需要可靠的服务边界和明确的数据所有权。否则,您最终会遇到复杂且不可持续的集成方案。对业务流程建模很重要。这将让您知道哪些用例和进程本质上是异步的并且适合于消息传递。

December 2, 2018 · 1 min · jiezi