怎样可以知道他有没有支付宝开通商家服务微服务

怎么加那些微信帮忙推广的微服务_百度知道
怎么加那些微信帮忙推广的微服务
我有更好的答案
帮忙微信推广的资源的话,比如微信的各个行业领域的KOL的话,就去汇优城上自己找呗
在百度上搜索相关字就可以了
进公众号搜索
为您推荐:
其他类似问题
您可能关注的内容
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。想知道微服务实践是怎样的吗?戳进来!想知道微服务实践是怎样的吗?戳进来!一个java码农百家号前言美丽好车的微服务实践是基于 Spring Cloud 体系来做的,在具体的开发过程中遇到了不少问题,踩了不少坑,对于微服务也有了实际的切身体会和理解,而不再是泛泛而谈。在整个 Spring Cloud 技术栈中,基于不同职责需要,我们选择了相应组件来支持我们的服务化,同时配合 Swagger 和 Feign 实现接口的文档化和声明式调用,在实际开发过程中极大地降低了沟通成本,提高了研发联调和测试的效率。.从应用架构来看,正是由于基于 Spring Cloud 来实现,整个系统完全秉承了微服务的原则,无论是 Spring Cloud 组件还是业务系统,都体现了服务即组件、独立部署、去中心化的特性,由此提供了快速交付和弹性伸缩的能力。.接下来我们基于各个组件具体介绍一下美利好车的微服务实践,首先最基本的就是 Eureka,其承载着微服务中的服务注册和服务发现的职责,是最基础的组件,必然有高可用的要求。基于高可用的 Eureka 集群实现服务发现.美利好车在生产实践中部署了一个三节点的 Eureka Server 的集群,每个节点自身也同时基于 Eureka Client 向其它 Server 注册,节点之间两两复制,实现了高可用。在配置时指定所有节点机器的 hostname 既可,即做到了配置部署的统一,又简单实现了 IP 解耦,不需要像官方示例那样用 profile 机制区分节点配置。这主要是由于 Eureka 节点在复制时会剔除自身节点,向其它节点复制实例信息,保证了单边同步原则:只要有一条边将节点连接,就可以进行信息传播和同步。在生产环境中并不要过多调整其它配置,遵循默认的配置既可。服务发现作为服务提供者的 Eureka Client 必须配置 register-with-eureka 为 true,即向 Eureka Server 注册服务,而作为服务消费者的 Eureka Client 必须配置 fetch-registry=true,意即从 Eureka Server 上获取服务信息。如果一个应用服务可能既对外提供服务,也使用其它领域提供的服务,则两者都配置为 true,同时支持服务注册和服务发现。由于 Ribbon 支持了负载均衡,所以作为服务提供者的应用一般都是采用基于 IP 的方式注册,这样更灵活。健康检查在开发测试环境中,常常都是 standlone 方式部署,但由于 Eureka 自我保护模式以及心跳周期长的原因,经常会遇到 Eureka Server 不剔除已关停的节点的问题,而应用在开发测试环境的启停又比较频繁,给联调测试造成了不小的困扰。为此我们调整了部分配置让 Eureka Server 能够迅速有效地踢出已关停的节点,主要包括在 Server 端配置关闭自我保护 (eureka.server.enableSelfPreservation=false),同时可以缩小 Eureka Server 清理无效节点的时间间隔(eureka.server.evictionIntervalTimerInMs=1000)等方式。另外在 Client 端开启健康检查,并同步缩小配置续约更新时间和到期时间 (eureka.instance.leaseRenewalIntervalInSeconds=10 和 eureka.instance.leaseExpirationDurationInSeconds=20)。健康检查机制也有助于帮助 Eureka 判断 Client 端应用的可用性。没有健康检查机制的 Client 端,其应用状态会一直是 UP,只能依赖于 Server 端的定期续约和清理机制判断节点可用性。配置了健康检查的 Client 端会定时向 Server 端发送状态心跳,同时内置支持了包括 JDBC、Redis 等第三方组件的健康检查,任何一个不可用,则应用会被标为 DOWN 状态,将不再提供服务。在生产环境下也是开启了客户端健康检查的机制,但没有调节配置参数。Eureka 的一致性在 CAP 原则中,Eureka 在设计时优先保证 AP。Eureka 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka 的客户端在向某个 Eureka 注册时如果发现连接失败,则会自动切换至其它节点,只要有一台 Eureka 还在,就能保证注册服务可用 (保证可用性),只不过查到的信息可能不是最新的 (不保证强一致性)。除此之外,Eureka 还有一种自我保护机制:如果在 15 分钟内超过 85% 的节点都没有正常的心跳,那么 Eureka 就认为客户端与注册中心出现了网络故障,开启自我保护,支持可读不可写。Eureka 为了保证高可用,在应用存活、服务实例信息、节点复制等都采用了缓存机制及定期同步的控制策略,比如客户端的定期获取(eureka.client.registryFetchIntervalSeconds),实例信息的定期复制(eureka.client.instanceInfoReplicationIntervalSeconds),Server 的定期心跳检查 (eureka.instance.leaseExpirationDurationInSeconds),客户端定期存活心跳(eureka.instance.leaseRenewalIntervalInSeconds)等等,加强了注册信息的不一致性。服务消费者应用可以选择重试或者快速失败的方式,但作为服务提供者在基于 Spirng Cloud 的微服务机制下应当保证服务的幂等性,支持重试。因此如果对一致性的要求较高,可以适当调整相应参数,但明显这样也增加了通信的频率,这种平衡性的考虑更多地需要根据生产环境实际情况来调整,并没有最优的设置。Config 的高可用及实时更新.高可用方案Config 的高可用方案比较简单,只需将 Config Server 作为一个服务发布到注册中心上,客户端基于 Eureka Client 完成服务发现,既可实现配置中心的高可用。这种方式要求客户端应用必须在 bootstrap 阶段完成发现配置服务并获取配置,因此关于 Eureka Client 的配置也必须在 bootstrap 的配置文件中存在。同时我们引入了 Spring Retry 支持重试,可多次从 Server 端拉取配置,提高了容错能力。另外,在启动阶段,我们配置了 failFast=true 来实现快速失败的方式检查应用启动状态,避免对于失败的无感知带来应用不可用的情况。配置实时同步在实际的生产中,我们同时基于 Spring Cloud Bus 机制和 Kafka 实现了实时更新,当通过 git 提交了更新的配置文件后,基于 webhook 或者手动向 Config Server 应用发送一个 /bus/refresh 请求,Config Server 则通过 Kafka 向应用节点发送了一个配置更新的事件,应用接收到配置更新的事件后,会判断该文件的 version 和 state,如果任一个发生变化,则从 Config Server 新拉取配置,内部基于 RefreshRemoteApplicationEvent 广播更新 RefreshScope 标注的配置。默认的 Kafka 的 Topic 为 springCloudbus,同时需要注意的是应用集群的节点不能采用 consumer group 的方式消费,应采用广播模式保证每个节点都消费配置更新消息。Spring CloudBus 又是基于 Spring Cloud Stream 机制实现的,因此配置需要按照 Steam 的方式设置。具体为:__Tue Jan 23 :25 GMT+0800 (CST)____Tue Jan 23 :25 GMT+0800 (CST)__spring.cloud.stream.kafka.binder.brokers=ip:portspring.cloud.stream.kafka.binder.zk-nodes=ip:portspring.cloud.stream.bindings.springCloudBusInput.destination=springCloudbus.dev__Tue Jan 23 :25 GMT+0800 (CST)____Tue Jan 23 :25 GMT+0800 (CST)__如果需要重定义 Topic 名称,则需要如上所示进行调整,由于多套开发环境的存在,而 Kafka 只有一套,我们对 Topic 进行了不同环境的重定义。但需要注意的一点是,这种实时刷新会导致拒绝任务的异常 (RejectedExecutionException),必现(当前 Edgware.RELEASE 版本)但不影响实际刷新配置,已被证实是个 Bug,具体参见 https://github.com/spring-cloud/spring-cloud-netflix/issues/2228,可简单理解为在刷新时会关闭 context 及关联的线程池重新加载,但刷新事件又同时提交了一个新的任务,导致拒绝执行异常。Zuul 的网关的安全及 session.安全处理针对外网请求,必然需要一个网关系统来进行统一的安全校验及路由请求,Zuul 很好地支持了这一点,在实际生产中,我们尽量让 gateway 系统不集成任何业务逻辑,基于 EnableZuulProxy 开启了服务发现模式实现了服务路由。且只做安全和路由,降低了网关系统的依赖和耦合,也因此使 gateway 系统可以线性扩展,无压力和无限制地应对流量和吞吐的扩张。需要注意的是,重定向的问题需要配置 add-host-header=true 支持;为了安全保障,默认忽略所有服务(ignored-services='*'),基于白名单进行路由,同时开启 endpoints 的安全校验,以避免泄露信息,还要通过 ignored-patterns 关闭后端服务的 endpoints 访问请求。Session 管理Zuul 支持自定义 Http Header,我们借助于该机制,实现了 Session 从网关层向后端服务的透传。主要是基于 pre 类型的 ZuulFilter,通过 RequestContex.addZuulRequestHeader 方法可实现请求转发时增加自定义 Header,后端基于 SpringMVC 的拦截器拦截处理即可。ZuulFilter 不像 SpringMVC 的拦截器那么强大,它是不支持请求路径的过滤的。Zuul 也没有集成 SpringMVC 的拦截器,这就需要我们自己开发实现类似的功能。如果需要支持 SpringMVC 拦截器,只需要继承 InstantiationAwareBeanPostProcessorAdapter 重写初始化方法 postProcessAfterInstantiation,向 ZuulHandlerMapping 添加拦截器既可。为了支持请求的过滤,还可以将拦截器包装为 MappedInterceptor,这就可以像 SpringMVC 的拦截器一样支持 include 和 exclude。具体代码示例如下:__Tue Jan 23 :25 GMT+0800 (CST)____Tue Jan 23 :25 GMT+0800 (CST)__1. public static class ZuulHandlerBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { 2. 3. @Value(&${login.patterns.include}&) 4. private String includeP 5. @Value(&${login.patterns.exclude}&) 6. private String excludeP 7. 8. @Autowired 9. private AuthenticateInterceptor authenticateI 10. 11. 12. public MappedInterceptor pattern(String[] includePatterns, String[] excludePatterns, HandlerInterceptor interceptor) { 13. return new MappedInterceptor(includePatterns, excludePatterns, interceptor); 14. } 15. 16. @Override 17. public boolean postProcessAfterInstantiation(final Object bean, final String beanName) throws BeansException { 18. if (bean instanceof ZuulHandlerMapping) { 19. ZuulHandlerMapping zuulHandlerMapping = (ZuulHandlerMapping) 20. String[] includePatterns = Iterables.toArray(Splitter.on(&,&).trimResults().omitEmptyStrings().split(includePattern), String.class); 21. String[] excludePatterns = Iterables.toArray(Splitter.on(&,&).trimResults().omitEmptyStrings().split(excludePattern), String.class); 22. zuulHandlerMapping.setInterceptors(pattern(includePatterns, excludePatterns, authenticateInterceptor)); 23. } 24. return super.postProcessAfterInstantiation(bean, beanName); 25. } 26. 27. }__Tue Jan 23 :25 GMT+0800 (CST)____Tue Jan 23 :25 GMT+0800 (CST)__关闭重试机制Zuul 底层是基于 Ribbon 和 Hystrix 实现的,因此超时配置需要注意,如果基于服务发现的方式,则超时主要受 Ribbon 控制。另外由于 Spring Config 引入了 Spring Retry 导致 Zuul 会至少进行一次失败请求的重试,各种开关配置都不生效,最后通过将 Ribbon 的 MaxAutoRetries 和 MaxAutoRetriesNextServer 同时设置为 0,避免了重试。在整个微服务调用中,由于不能严格保证服务的幂等性,我们是关闭了所有的重试机制的,包括 Feign 的重试,只能手动进行服务重试调用,以确保不会产生脏数据。基于 Sleuth 的服务追踪.Zipkin 是大规模分布式跟踪系统的开源实现,基于 2010 年 Google 发表的 Dapper 论文开发的,Spring Cloud Sleuth 提供了兼容 Zipkin 的实现,可以很方便地集成,提供了较为直观的可视化视图,便于人工排查问题。美利好车系统在实际的生产实践中,将日志同步改为适用于 Zipkin 格式的 pattern,这样后端 ELK 组件日志的收集查询也兼容,基于 traceId 实现了服务追踪和日志查询的联动。在日志的上报和收集上我们仍然基于 spring-cloud-starter-bus-kafka 来实现。Swagger 支持的接口文档化和可测性在前后端分离成为主流和现状的情况下,前后端就接口的定义和理解的不一致性成为开发过程中效率的制约因素,解决这个问题可以帮助前后端团队很好地协作,高质量地完成开发工作。我们在实际开发过程中使用了 Swagger 来生成在线 API 文档,让 API 管理和使用变得极其简单,同时提供了接口的简单测试能力。虽然这带来了一定的侵入性,但从实际生产效率来说远超出了预期,因此也特别予以强调和推荐。实际开发过程中,我们仍然提供了 API 的 SDK 让调用方接入,虽然这个方式是微服务架构下不被推崇的,但现阶段我们认为 SDK 可以让调用 API 更简单、更友好。版本问题基于 Maven 的 snapshot 机制实现实时更新,唯一需要注意的是要保证向后兼容。以上就是美利好车系统微服务实施的一些实践,有些地方可能不是特别恰当和正确,但在当前阶段也算基本满足了开发需要,而且我们秉承拥抱变化的态度,对整个体系结构也在持续进行改善和优化,积极推动美利好车架构的演进,希望能更好地支持美利好车的业务需求。作者介绍王文尧,曾在京东等多家知名互联网电商领域公司任职,也创业做过垂直电商平台,现任美利金融好车技术部架构师。对电商领域的业务比较了解,同时对敏捷、领域建模、高并发高可用的分布式系统设计及服务化等方面有较为深入的研究和实践。本文由百家号作者上传并发布,百家号仅提供信息发布平台。文章仅代表作者个人观点,不代表百度立场。未经作者许可,不得转载。一个java码农百家号最近更新:简介:方便大家学习交流java作者最新文章相关文章微服务概念解析(下)
您可以捐助,支持我们的公益事业。
每天15篇文章
不仅获得谋生技能
更可以追随信仰
微服务概念解析(下)
&来源:搜狐&发布于:&
519 次浏览
&&&&评价:
在上篇中我们讲到了微服务的几个架构特性,包括通过服务实现组件化、以业务功能为核心进行组织、产品而非项目、智能化端点与傻瓜式流程,在今天的微服务概念解析下篇中,我们将继续讲述微服务的特性,具体分析它的离散化治理、离散化数据管理、基础设施自动化、故障应对设计以及演进设计,并理性思考微服务作为一项新兴的技术成果,是否能够代表未来。
传送门:微服务概念解析(上)
离散化治理
聚合型治理的一大影响在于使得单一技术平台上出现标准化趋势。经验表明这类方案具备收缩特性――意味着各个实际问题并不能够轻松与解决方案对应起来。我们更倾向于使用正确的工具执行正确的任务,而且虽然部分整体应用程序能够发挥不同编程语言的独特优势,但这种情况并不常见。
微服务与SOA
当我们探讨微服务时,经常出现的问题就是其到底是不是我们十年前就听说过的面向服务架构(简称SOA)的另一种表现形式?二者之间确实存在一定联系,因为微服务风格拥有与SOA相似的逻辑主张。然而问题在于,SOA的实际含义太过广泛,而且当我们提到所谓“SOA”时,实际所指的对象往往跟这里提到的微服务概念差之千里――具体来讲,其通常代表那些专注于利用ESB实现的集成化整体应用程序。
值得强调的是,我们也见证了大量表现糟糕的面向服务实现手段――从将复杂性隐藏在ESB当中[7]的作法,到投入多年以及数百万资金却毫无成效的尝试,再到以聚合型治理模式抑制变更,我们几乎看不到面向服务架构能够带来什么显著的积极影响。
诚然,微服务社区当中使用的不少技术成果都源自开发人员在大型企业当中积累到的集成化服务成果。Tolerant
Reader模式正是其中的典型代表。对Web的运用确实带来可观回报,而使用简单协议正是经验积累的直接产物――这显然是为了解决标准汇聚所导致的高复杂性难题(无论何时,如果大家需要利用一种实体来管理其它实体,那么就意味着各位已经面临着大麻烦)。
SOA的这些弊端导致一部分微服务布道者很讨厌人们把SOA的标签加在微服务头上――尽管也有一些人认为微服务正是SOA的一种实现方式[8],或者说我们可以将微服务称为“面向服务的正确实现”。无论如何,事实上SOA含义的宽泛性意味着其更适合作为一种用于定义架构风格的术语,而非具体解决方案。
通过将整体应用程序的各组件拆分成服务,我们能够对各服务进行分别构建。各位可能希望利用Node.js建立一套简单报告页面?照此办理即可。打算利用C++构建特定的近实时组件?没问题。打算利用不同类型的数据库以匹配单一组件的读取行为?目前的技术方案已经能够实现这种独立重构需求。
当然,我们能够实现以上目标,并不代表我们必须这么做――但对系统进行拆分意味着大家能够拥有更多备用选项。
采用微服务架构的团队倾向于以不同的方式实现所谓标准。相较于以往编写一整套定义标准集的作法,他们更乐于开发实用工具并交付给其他开发人员,从而利用其解决自身面临的类似问题。这些工具通常能够在更为广泛的层面得到实现与共享,但同时又不至于转化为排他性内部开源模式。现在git与github都已经成为客观层面的版本控制系统选项,而开源实践也越来越多地成为内部环境中的常见组成部分。
Netflix公司就是个很好的例子,他们遵循的正是这样一种理念。将具备实用性且经过严格考验的代码作为库,并鼓励其他开发人员利用其以类似的方式解决的类似的问题,这就为各团队成员在必要时选择其它工具保留了空间。共享式库专注于数据存储、进程间通信以及我们在后文中将要探讨的基础设施自动化等问题的解决。
对于微服务社区而言,资源成本显然是种不受欢迎的因素。这并不是说该社区不承认服务协议的价值。恰恰相反,这是因为他们希望构建起大量服务协议。他们希望能够采用多种完全不同的方式对这些协议进行管理。像Tolerant
Reader以及Consumer-Driven Contacts这样的模式在微服务架构中非常常见。这些服务协议也各自以独立方式不断演进。将消费者驱动型协议作为构建工作组成部分的作法能够显著增强参与者信心,同时快速获取服务功能能否确切实现的反馈意见。事实上,澳大利亚的某个团队就在积极利用消费者驱动型协议进行新服务构建。他们使用的简单工具确保其能够针对单一服务实现协议定义。其甚至在面向新服务的代码被编写出来之前就已经成为自动化构建流程中的一部分。这意味着服务只有在切实满足该协议要求的前提下才能够实现构建――这就有效解决了构建新软件时经常出现的“YAGNI”[9]难题。这些技术与工具成果围绕协议而生,并通过降低不同服务间的耦合性限制了其对中央协议管理机制的依赖。
多种语言,多种选项
JVM作为平台的快速发展已经成为多种语言混成于单一通用平台内的最新明证。这种作法已经成为一类常见实践,旨在充分发挥高级语言在过去数十年中发展所实现的种种高级抽象优势。其甚至以涓滴效应影响到裸机以及通过低级语言编写的性能敏感型代码。然而,众多整体应用程序并不需要这种级别的性能优化效果,亦非常见的DSL与高级别抽象开发成果。相反,整体应用程序往往使用单一语言,这也严重限制了其能够使用的技术手段。[10]
也许离散化治理的人气正是源自Amazon方面提出的“谁构建,谁运行”原则。各团队需要为其构建的软件的各个方面承担责任,包括为软件提供24/7全天候运维支持。这种程度的责任下放当然还没有成为常态,不过我们已经看到越来越多的企业开始将责任交付至开发团队。Netflix公司亦是另一家采取这种理念[11]的企业。为了不至于在凌晨三点被紧急来电叫醒,开发人员们当然会全力以赴提升所编写代码的质量水平。这些思路与传统的集中化治理模式明显相去甚远。
离散化数据管理
数据管理离散化拥有多种不同的表现形式。从最为抽象的级别来看,这意味着全局概念模型将在不同系统之间有所区别。这种问题常见于解决方案在大型企业当中的部署,毕竟销售团队对于客户概念的理解方式必须不同于技术支持团队的理解方式。被销售人员视为客户的对象也许根本不会出现的技术支持团队的视野当中。不同属性甚至是相同属性的不同理解方式都可能在语义层面产生细微的差异。
实践性规范与执行标准
这种态度实际有点二分法的意味:微服务团队倾向于回避由企业架构部门制定的硬性执行标准,但却乐于使用甚至积极推广HTTP、ATOM以及其它微格式开放标准。
二者之间的本质区别在于标准的开发方式以及执行方式。由IETF等组织管理的标准只会在得到广泛采用之后才能真正成为业界规范,而且其往往脱胎自成功的开源项目。
这些标准拥有与商业世界完全不同的立场与定位――事实上,商业标准的制定工作往往由那些几乎不具备编程经验的团队所负责,或者受到具体厂商的过度影响。
这一问题通常出现在不同应用程序之间甚至是应用程序之内,特别是在将应用程序拆分为多个独立组件的情况下。解决问题的一类可行思路在于基于背景边界化的区域驱动型设计(简称DDD)方案。DDD机制将一个复杂的区域拆分成多个具备边界的背景单元,并对各单元之间的关系加以映射。这种方式同时适用于整体与微服务架构,但服务与背景边界间的自然关联性有助于声明我们曾在业务功能章节中提到过的区分效果。
除了对概念模式进行离散化处理,微服务同时也能够拆分数据存储决策。尽管整体性应用程序倾向于使用单一逻辑数据库保存持久性数据,但企业通常更乐于利用单一数据库涵盖一系列应用程序――而且大多数此类决策立足于具体供应商提供的授权商业模式。微服务机制则选择由每项服务管理其自身数据库的方式,而非不同实例基于同一数据库技术或者完全使用多种不同数据库系统――这种方式亦被称为混合持久化。大家可以利用混合持久化方案打理整体应用程序,但其在微服务架构中的亮相频率明显更高一些。
对微服务架构内数据责任关系的离散化处理也影响到了更新管理工作。常见的更新处理方案是在更新多种资源时,利用事务处理机制来保证其一致性。这种方式通常被用于整体性应用程序汉中。
这种事务处理使用方式确实有助于保障一致性,但却会带来显著的临时性耦合效果,而这在跨越多项服务时会带来新的难题。分布式事务处理非常难以实现,因此微服务架构更强调服务之间的事务处理协调性,同时明确强调只需保障最终一致性并通过补偿运算解决其中的冲突问题。
利用这种方式管理一致性问题已经成为众多开发团队的新困境,但其却能够切实匹配业务实践。一般来讲,企业需要保留一定程度的不一致性以实现某种程度的逆转能力,从而利用快速响应处理错误状况。这种权衡有其必要性,只要确定失误成本要低于高一致性条件下可能造成的业务损失成本即可。
基础设施自动化
基础设施自动化技术在过去几年中得到了长足发展――而云与AWS的演进则显著降低了构建、部署及运维微服务架构所带来的复杂性水平。
大部分利用微服务机制构建的产品或者系统都是由具备丰富的持续交付及其前者――持续集成――经验的团队所完成。通过这种方式构建软件的团队能够充分发挥基础设施自动化技术成果的潜在能力。我们可以将整个流程整理成以下图表:
图五:基本构建流程
让正确决定更易于执行
作为一项连带效应,我们发现实现持续交付与部署能够帮助开发人员及运维人员创造出高实用性工具。这类工具能够创建artifact、管理代码库、建立简单服务或者实现标准监控与记录等常见功能。这方面最典型的实例当数Netflix公司发布的一系列开源工具,险些之外Dropwizard等方案亦得到广泛使用。
整体应用程序的构建、测试与推送流程能够在此类环境下顺利完成。事实证明,一旦大家利用自动化流程进行整体应用开发,那么部署更多应用程序也将成为顺理成章的轻松任务。请记住,持续交付的目标之一就是令部署变得无脑化,这意味着无论是一款应用还是三款,其实际部署流程都不会有什么区别[12]。
我们还发现,不少团队在利用这种广泛的基础设施自动化能力管理生产环境下的微服务架构。相较于前面提到的整体与微服务应用在部署层面并没有太大区别,实际运维环境下的具体条件则存在着巨大差异。
图六:模块部署的具体方式往往差别巨大
故障应对设计
将服务作为组件加以使用的结果之一在于,应用程序需要经过针对性设计以确保其具备服务故障容错能力。任何服务调用都有可能因为供应程序不可用而发生问题。在这种情况下,客户端必须要尽可能做出适当的回应。相较于整体应用程序来说,服务即组件机制会增加额外的处理复杂性,这也是微服务架构的一大弊端。在这种情况下,微服务团队需要不断审视服务故障对用户体验造成的影响。Netflix公司的“猴子军团”项目就专门负责在正常运营期间对服务进行破坏,甚至利用数据中心故障来测试应用程序的弹性及监控能力。
断路器与可交代生产环境之代码
断路器模式出现在Amazon的Release It!当中,其中提到的其它模式还包括隔板模式与超时模式等。在加以结合之后,这些模式将在构建通信应用方面发挥巨大作用。Netflix公司发布的一系列博文就很好地解释了他们对这些模式选项的具体使用方式。
这类自动化测试机制往往会令正等待周末下班的运维团队们感到不寒而U獠⒉皇撬嫡寮芄狗绺窬臀薹ㄊ褂酶吒丛有约嗫鼗啤徊还庵智榭鋈肥挡惶<
由于服务随时可能发生故障,因此最重要的就是保持对故障的快速检测能力,并在可能的情况下对其进行自动恢复。微服务应用程序高度强调对应用程序的实时监控能力,同时不断对架构元素(数据库每秒钟接收到的请求数量)以及业务相关指标(例如每分钟收到的订单数量)进行记录。语义监控能够通过早期预警系统抢先一步做出警示,并引导开发团队对问题加以跟进与调查。
这一点对于微服务架构尤为重要,因为微服务更倾向于采用由编排及事件协作实现的应急处理方式。尽管很多专家都对应急处理方案偶尔带来的收益表示认同,但其实际上往往也是让事情变糟的罪魁祸首。为了及时阻断糟糕的应急处理并确保其拥有可恢复性,监控系统就变得极为重要。
同步调用殊不可取
无论何时时,一旦在不同服务之间进行多次同步调用,那么可能引发宕机的概率也会以乘法形式增长。简单来讲,系统的总体宕机时间为各单个部件宕机时间的乘积。这时我们就面临着具体选择,到底是以异步方式进行调用,还是以计划方式管理由同步调用带来的宕机时间。英国《卫报》网站在其全新平台上执行了一项简单的规则――每个用户请求对应一次同步调用,而Netflix公司所使用的API则经历重新设计,确保其结构内采用异步调用机制。
整体应用程序的构建方式可与微服务架构同样透明――事实上也本应如此。二者的区别在于,在面对整体应用时我们需要在确切了解其运行在不同进程中的服务何时发生断开。考虑到同一进程当中可能包含多套库,这种透明度水平实际上很难实现。
微服务团队需要利用复杂的监控与记录机制处理各项服务,例如通过仪表板显示上线/下线状态以及一系列运营与业务相关指标。另外,我们还需要面对断路器状态、当前数据吞吐量以及延迟等其它常见的衡量数据。
微服务从业者通常都具备演进设计工作背景,并将服务拆分视为一种深入型工具,旨在帮助应用程序开发人员在无需拖慢变更速度的前提下实现面向应用程序的变更控制。变更控制并不一定意味着变更数量削减――配合正确的态度与工具,大家完全可以帮助软件提供快速、频繁且经过良好控制的变更。
当尝试将一套软件系统拆分为多个组件时,我们往往面临着与具体拆分工作相关的决策任务――即我们应该遵循怎样的方针对应用程序进行拆分?而组件中的关键属性则在于其独立替换与可升级特性[13]――这意味着我们要找到确切的平衡点,保证自身能够在不影响其它协作对象的前提下对单一组件进行重写。事实上,很多微服务团队会更进一步,直接清退某些服务而非对其进行长期升级。
英国《卫报》网站就是个很好的例子,其应用程序在设计与构建方面作为整体应用存在,但却在逐步面向微服务架构演进。该网站的核心部分仍然属于整体性项目,但他们更倾向于通过构建微服务利用整体API实现新功能添加。这套方案对于临时性功能的实现非常重要,例如加设专题页面以显示体育赛事报道。网站中的这类组成部分能够通过快速开发语言在短时间内编写完成,并在对应事件结束后立即下线。我们还发现其它一些金融机构亦采取类似的方式公布突发性市场波动,并在数周或者数月之后将其下线。
这也强调了可替换性在模块化设计中的重要地位,其主旨正在于将模块机制贯彻整个变更模式[14]。大家希望只变更其中必须变更的部分,而其它模块则继续保持原样。系统当中那些几乎很少变动的部分应该立足于不同于高变更频率组件的服务。如果大家发现自己经常需要同时对两项服务做出变更,那么明显应该将二者加以合并。
将组件纳入服务也让我们能够以更高的细粒度水平进行规划制定。在整体应用程序当中,任何一项变更都需要对应用整体进行重构与重新部署。但在微服务架构方面,我们只需要重新部署包含对应变更的服务。这能够显著简化并加快发布流程。不过其弊端在于,我们必须考虑针对单一服务的变更是否会影响到其它服务。传统的整体性方案能够通过版本控制解决这类难题,但微服务领域则倾向于将版本控制作为最后一种应急办法。我们可以通过设计保证服务拥有强大的容错能力,从而应对其供应程序中出现的各类代码修改。
微服务是否代表着未来?
我们撰写这篇文章的主要目的在于解释微服务架构的基本思路与原则。而在撰写过程当中,我们明确意识到微服务架构风格确实是一项值得重视的关键成果――企业级应用程序开发人员应当对其加以了解。我们最近利用该架构构建了多套系统,而且了解到亦有其它多家企业将其纳入业务体系。
我们了解到的微服务架构先驱企业包括Amazon、Netflix、英国《卫报》、英国政府数字化服务局、realestate.com.au、Forward以及comparethemarket.com等等。2013年召开的相关会议则公布了更多参与其中的重要厂商。除此之外,另有相当一部分企业一直在使用类似的实现思路――但却并没有使用‘微服务’这样的称谓。(其通常将其冠以SOA标签――不过正如我们之前提到,SOA是一类存在大量矛盾取向的概念组合。[15])
尽管拥有这些积极的经验,但我们仍然无法完全肯定微服务架构就代表着软件未来的发展方向。虽然我们的实际经历证明微服务架构截至目前仍拥有优于整体性应用程序的积极优势,但必须承认只有充分的时间积累才能帮助我们做出真正完整则准确的判断结论。
我们的同事Sam Newman曾于2014年倾尽心力撰写出这本关于我们如何构建微服务架构类应用的论著。如果大家希望进一步探讨这个议题,请千万不要错过。
通常来说,架构决策的实际影响可能需要几年之后才能逐步显现出来。我们已经看到不少优秀的团队带着巨大的热情与愿景而投入工作,但最终却构建起一套陈旧不堪的整体性架构。很多人认为同样的情况不太可能发生在微服务架构身上,因为其服务边界非常明确因此不太可能发生相互影响。但由于时间尚短且系统程度不足,我们目前还无法真正评估微服务架构的成熟度水平。
人们对微服务成熟度抱持的怀疑态度也有其理由。在任何组件化尝试工作当中,最终结果的成功与否都取决于该软件与拆分后组件的契合效果。我们目前仍然很难说明组件边界的选择原则。演进设计导致边界划分变得非常困难,因此最重要的是保证其重构的简易性。但一旦将组件作为服务处理以实现远程通信,那么其重构难度将远远高于进程内库。在不同服务边界之间进行代码移动难度极大,而任何接口变更都需要在不同相关服务间实现,同时添加层的向下兼容能力,这无疑会令测试工作更加复杂。
另一大问题在于,如果相关组件间的关系不够简洁,那么我们就相当于把组件内部的复杂性转移到了不同组件间的连接当中。这样做不仅会导致复杂性扩散,同时亦会导致其明确性缺失且难以控制。立足于小型、简单组件审视问题总是更为直观,而在不同服务间进行纵览则往往会错失关注点。
最后,团队的技能水平也将起到决定性作用。新型技术成果往往要求高水平技术团队加以实施。不过高水平团队能够顺畅利用的技术方案并不一定能够在低水平人员手中发挥作用。我们已经见证了众多低水平团队构建起的如一团乱麻般的整体架构,但仍需要时间来了解微服务架构是否会在同样的情况下引发同样的状况。诚然,糟糕的团队创建出的始终只能是糟糕的系统――但我们不知道微服务架构到底是会缓解这种状况,还是令状况更中惨不忍睹。
目前有一种较为理性的论调,认为我们不应将微服务架构作为起步方案。相反,大家可以从整体性开发风格出发,保证其结合模块化机制,并在整体性特征引发实际问题后逐步将其拆分为微服务形式。(不过这样的建议并非完全理想,因为良好的进程内接口往往并不能成为良好的服务接口。)
因此我们对此抱持谨慎的乐观态度。到目前为止,我们已经了解到关于微服务架构的方方面面,而且其应该能够成为一种极具价值的开发手段。虽然还不能做出最终判断,但软件开发工作的固有挑战之一,正是我们只能根据目前掌握的远称不上完美的信息做出决策。
520 次浏览
更多课程...&&&
更多咨询...&&&
每天2个文档/视频
扫描微信二维码订阅
订阅技术月刊
获得每月300个技术资源
|&京ICP备号&京公海网安备号}

我要回帖

更多关于 163邮箱开通smtp服务 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信