微服务之数据同步Porter

Porter是一款数据同步中间件,主要用于解决同构/异构数据库之间的表级别数据同步问题。背景在微服务架构模式下深刻的影响了应用和数据库之间的关系,不像传统多个服务共享一个数据库,微服务架构下每个服务都要有自己的数据库。如果你想获得微服务带来的好处,每个服务独有一个数据库是必须的,因为微服务强调的就是松耦合。我们希望数据库就和服务一样,要有充分的独立性、可以和服务一起部署、一起扩展、一起重构。同时,还需要兼顾数据中心的数据聚合、DBA的多种数据库备份、报表中心的业务报表等等矛盾问题。因此便产生了「Porter」项目。微服务改造过程中,无法避免的一个坎,那就是垂直拆库,根据不同的子服务,把过去的「一库多服」拆分成「一库一服」。一库多服还是一库一服?不管是否是微服务架构,应用的各个模块之间都需要频繁的通信、协作、共享数据,实现系统的整体价值。区别点在于单体应用是通过本地方法调用来完成;在微服务中是通过远程API调用完成。而共享数据最贱的方式就是采用共享数据库模式,也就是单体应用中最常用的方式,一般只有一个数据库,如图一库多服和一库一服的方式:一库多服的架构模式通常会被认为是微服务架构下的反范式,它的问题在于:稳定性:单点故障,一个数据库挂掉,整批服务全部停止。服务独立性被扼杀?耦合性:数据在一起,会给贪图方便的开发或者DBA工程师编写很多数据间高度依赖的程序或者工具;扩展性:无法针对某一个服务进行精准优化或扩展,服务会大体分为两个读多写少、写多读少,数据库优化是根据服务而来的,不是一篇而论。所以随行付内部一般推荐的做法:是为每一个微服务准备一个单独的数据库,即一库一服模式。这种模式更加适合微服务架构,它满足每一个服务是独立开发、独立部署、独立扩展的特性。当需要对一个服务进行升级或者数据架构改动的时候,无须影响到其他的服务。需要对某个服务进行扩展的时候,也可以手术式的对某一个服务进行局部扩容。那么问题来了,在改造中我们发现,以下问题,诞生了该项目:报表中心和前端详细页都存在SQL Join方式,经历我们一库一服的拆分后,无法在继续使用SQL Join方式了…数据中心,做得是数据聚合,数据拆分后,给数据中心带来了很大的麻烦…微服务之后,各个应用模块对数据库的要求出现了分歧,数据库类型多元化自主选择还是统一…等等…Porter介绍Porter是一个集中式的数据处理通道,所有的数据都在这个数据处理平台汇聚、分发。Porter是一个无中心、插件友好型分布式数据同步中间件。默认注册中心插件实现为zookeeper, 当然,你也可以基于注册中心接口实现自定义注册中心模块。在Porter的主流程外分布着集群插件、源端消费插件、源端消息转换器插件、目标端写入插件、告警插件、自定义数据定义插件等插件模块,除了集群插件、告警插件是Porter任务节点全局作用域外,其余插件模块都随着同步任务的不同而相应组合。得益于良好的设计模式,Porter才能为大家呈现如此灵活的扩展性与易用性。功能Porter始于2017年,提供数据同步功能,但并不仅仅局限于数据同步,在随行付内部广泛使用。主要提供一下功能:原生支持Oracle|Mysql到Jdbc关系型数据库最终一致同步插件友好化,支持自定义源端消费插件、目标端载入插件、告警插件等插件二次开发。支持自定义源端、目标端表、字段映射支持节点基于配置文件的同步任务配置。支持管理后台同步任务推送,节点、任务管理。提供任务运行指标监控,节点运行日志、任务异常告警。支持节点资源限流、分配。基于Zookeeper集群插件的分布式架构。支持自定义集群插件。架构设计Porter节点通过注册中心实现分布式集群,并根据资源需求动态扩缩容。Portert与注册中心协商了一套任务、节点、统计接口,Porter节点通过监听注册中心接口数据的变化实现任务的分配管理。配置管理后台遵守并实现注册中心的接口规范,实现对Porter节点远程管理。注册中心同样有一套分布式锁机制,用于任务资源的分配。在这个机制外,Porter节点可以通过本地配置文件的方式实现任务的定义。原理介绍:1、基于Canal开源产品,获取MySql数据库增量日志数据。2、管理系统架构。管理节点(web manager)管理工作节点任务编排、数据工作节点(TaskWork)汇报工作进度3、基于Zookeeper集群插件的分布式架构。支持自定义集群插件4、基于Kafka消息组件,每张表对应一个Topic,数据节点分Topic消费工作处理流程为了保证数据的一致性,源端数据提取与目标端插入采用单线程顺序执行,中间阶段通过多线程执行提高数据处理速度。对照上图就是SelectJob与LoadJob单线程执行,ExtractJob、TransformJob线程并行执行,然后在LoadJob阶段对数据包进行排序,顺序写入目标端。正如文章开头所说,告警插件与注册中心插件在多个任务间共享,每个任务根据源端与目标端的类型、源端数据格式选择与之相匹配的处理插件。也就是说告警插件、注册中心插件与Porter节点配置相关,数据消费插件、目标端插件、自定义数据处理插件等插件与任务配置相关。插件化设计Porter通过SPI规范结合单例、工厂、监听者模式等设计模式,实现了极大的灵活性与松耦合,满足不同场景的二次开发。具体涵盖如下四个方面的插件化设计:注册中心插件源端消费插件目标端载入插件自定义数据处理插件集群机制Porter的集群模式依赖集群插件,默认的集群插件基于zookeeper实现。Porter任务节点和管理节点并不是强制绑定关系,任务部署可以通过任务配置文件,也可以通过管理节点推送。管理节点还可以管理节点、收集、展示监控指标信息等,是一个不错的、简化运维的管理平台。同样的,可以基于zookeeper数据结构协议实现你自己的管理平台。集群模式下的系统结构:zookeeper集群模式插件zookeeper数据结构协议:Porter的集群机制主要有以下功能:实现节点任务的负载,当前任务节点失效后自动漂移到其他任务节点实现任务节点与管理节点的通信实现任务处理进度的存储与拉取实现统计指标数据的上传(最新的开发版本支持自定义统计指标上传客户端,原生支持kafka)用于节点、任务抢占的分布式锁实现基于文件系统的单机模式插件最新开发版支持Porter任务节点以单机模式运行,不依赖管理后台和zookeeper,通过配置文件配置任务。单机模式是一种特殊的集群模式,仅支持部分集群功能,但简化了任务部署的复杂性,灵活多变。实现任务处理进度的存储与拉取实现统计指标数据的上传Porter任务节点运行模式的配置方式zookeeper集群配置porter.cluster.strategy=ZOOKEEPERporter.cluster.client.url=127.0.0.1:2181porter.cluster.client.sessionTimeout=100000单机模式配置porter.cluster.strategy=STANDALONEporter.cluster.client.home=/path/.porter

February 21, 2019 · 1 min · jiezi

微服务所需组件(大部分是Spring Cloud,持续更新)

服务发现将所有微服务注册到一个Server上,然后通过心跳进行服务健康监测。这样服务A调用服务B可以通过注册中心获取服务B的地址、端口调用Eureka - Eureka 提供云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移Spring Cloud Zookeeper - Spring Cloud Zookeeper 操作Zookeeper的工具包,用于使用zookeeper方式的服务发现和配置管理Consul - Consul 是一个服务发现与配置工具,与Docker容器可以无缝集成服务调用HTTP 客户端restTemplate - Spring Web RestTemplate 是同步客户端执行HTTP请求,在底层HTTP客户端库上公开简单的模板方法API,类使于JDK HttpURLConnection、Feign等Feign - Feign 使Java编写HTTP客户端更加简单负载均衡Ribbon - Ribbon 提供云端负载均衡,有多种负载均衡策略可供选择

February 15, 2019 · 1 min · jiezi

在Shell中进行独立的集成测试

翻译:疯狂的技术宅原文:https://zachholman.com/posts/…本文首发微信公众号:jingchengyideng欢迎关注,每天都给你推送新鲜的前端技术文章我在开发 during.com 时创建了一系列的微服务,它们被用来做一些同步、导入和单调繁重数据处理之类的工作。如果你对微服务不熟悉,那么它只是一个花哨的名词而已,意思就是“让我们把这些该死的业务逻辑散落的到处都是!”不管怎样,我的微服务到处都是,嗯,的确是“微”。不过我绝对不是一个逗逼,我已经多次重写了自己的web服务,从Rails中的一个目录开始,然后迁移到Ruby,接着是Crystal,之后是Go,现在又回到了Ruby。这并不是在浪费时间,这只是为了以防万一而尝试新的方法。最后我又把这些服务迁移回了Ruby。这段时间Ruby的表现真是没得说,它能很轻松的进行扩展来应对用户的请求。不过目前这个应用还没有进入beta测试阶段,在你还没有用户的时候,它的确容易扩展。实际上如果在没有用户使用的前提下,几乎任何关于软件开发的一切问题都不算什么,当然除了赚钱(当然了这也并没有成为硅谷任何一家公司的障碍)。好吧我跑题了,我一直都很享受用Shell来测试这些服务的过程。在POSIX shell环境下测试, 或者 UBIQUITOUSIX shell 环境也可以我已经用Shell脚本为这些服务编写了测试,很不错。首先,不需要为基本环境操心。无论是我的AWS实例,还是我的持续集成服务器,还有我自己的开发机上都有Shell环境。所以不需要安装任何东西,也不必运行什么Docker实例(实际上用它肯定也没什么坏处)。不过最重要的一点是,我的测试是独立的,独立于将来可能会使用的任何语言。我可以在不同的语言和框架之间进行切换,而不需要对测试脚本做任何改变。这一点非常重要,因为如果你的v1版本中有一个微妙的bug,而测试却通过了,当你开始重写v2版本的服务时,如果在无意中修正了这个bug,测试将可能失败。这意味着你暴露给其它服务的API不会因此而意外中断,你可以使用其它服务来暂时顶替,为修复bug争取时间,而不是在部署到生产环境后大吃一惊。这些测试的工具也是相当不错的,这些年我一直在用我的好友Blake Mizerany写的一个Shell环境下的小工具roundup。最近我一直在使用Sam Stephenson的 bats,现在它已经形成了一个十分活跃的社区(哈,谁能想到呢,仅仅是一个shell测试工具而已)。我的Shell测试看起来就像这样,用bats:@test “Responds with events within the given timespan” { url_params="?starts_at=2017-05-01T00:00:00-00:00&ends_at=2017-05-31T00:00:00-00:00" run curl “$URL$url_params” –silent -H “Authorization: Bearer:$bearer” assert_output –partial “Test Event 0” assert_output –partial “Test Event 2” refute_output –partial “Test Event 5” refute_output –partial “No location data” refute_output –partial “Not included in the date span”}测试非常简单,也容易理解。基本上就是运行curl然后检查输出结果,完成。整合周围的一切最后一点,这些微服务非常之小,我完全可以不用为它们写任何其它的测试,只需要写集成测试即可。全栈测试(full-stack)真的非常有趣,但是人们对此很谨慎,不知道它会成为下一个好主意还是成为世界上最差劲的想法。对于它的价值,GitHub的主旨是随时愉快地运行在零单元测试的生产环境下。总的来说我正在实践这种悬而未决的理论,不过我会悬崖勒马。如果你感兴趣的话可以阅读关于这个话题更多的文章。但是我要说的是在这种情况下,哇,一股新鲜空气袭来。我们的测试是可移植的,如果我重写了服务,不必为它们重写新的测试。我只需要通过自己的基于 shell 的测试即可。本文首发微信公众号:jingchengyideng欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章

February 13, 2019 · 1 min · jiezi

json to graphql schema: json2graphql

json2graphqljson2graphql 是一个根据 json 生成 GraphQL Schema 的工具。可在 https://luojilab.github.io/js… 在线体验其功能。关于 GraphQLGraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。由于其强类型,返回结果可定制,自带聚合功能等特性,由 facebook 开源后,被 github 等各大厂广泛使用。核心概念:TypeFieldQuery/MutationArgumentsInputVariablesAliases更多请参考 https://graphql.cn/为什么选用 GraphQL相比 REST API, GraphQL 提供了更高的灵活性。接口调用方能够精确的定义其所需数据,并通知服务方只返回这部分数据,该功能是 REST API 无法提供的。GraphQL 能够使客户端只进行一次接口调用,即可获取多个 REST API 请求返回的数据。这种数据聚合的能力,正是我们所需要的。json protobuf 与 GraphQL由于 protobuf 和 GraphQL 都是强类型的,所以可以直接从 protobuf 的 schema 生成 GraphQL Schema,因而才能有自动聚合 grpc 服务生成 GraphQL 接口的框架 rejoiner。但同样的方法不适用于 json,因为标准的 json 并不包含 schema,单纯根据 json 文件无法确定知道每个字段的类型(因为有空值,以及嵌套的情况)。因而目前无法实现类似 rejoiner for json 这样的全自动框架。我们虽不能生成最终的 GraphQL Schema,但是基于对 json 的解析和一些约定,我们可以生成一个 GraphQL Schema 的草稿,生成 Schema 的绝大部分内容,并将有疑问的地方标记出来。json2graphql 就是一个用 golang 实现的 json 生成 schema 的工具。如果你不熟悉 golang,可以使用其在线版本 https://luojilab.github.io/js…在从 REST API 迁移到 GraphQL 的过程中,我们有很多接口会返回大量字段(几十个),如果完全手动编写这些 Schema,将是非常痛苦的,我们开发 json2graphql 的初衷就是解决这个问题,大大缩短开发时间。以下介绍该工具用法。Usagego run main.go -hNAME: inspect - generate a graphql schema based on jsonUSAGE: main [global options] command [command options] [arguments…]DESCRIPTION: inspect json and generate draft schema.graphqlCOMMANDS: inspect generate a graphql schema based on json help, h Shows a list of commands or help for one commandGLOBAL OPTIONS: –verbose, -v show logs –input value, -i value the json filename –output value, -o value the target filename to store generated schema –help, -h show helpExamplego run main.go -i example.jsonLive Demohttps://luojilab.github.io/js…TODO[x] build it as a web service that render schema on the fly like json.cn[ ] support to read from multi json files.[ ] get input from http request rather than local file.[ ] integrate with graphql server frameworks like gqlgen and auto generate resolver ...

February 2, 2019 · 1 min · jiezi

Spring Cloud Alibaba基础教程:使用Nacos作为配置中心

通过本教程的前两篇:《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》《Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)》我们已经学会了,如何利用Nacos实现服务的注册与发现。同时,也介绍了在Spring Cloud中,我们可以使用的几种不同编码风格的服务消费方式。接下来,我们再来一起学习一下Nacos的另外一个重要能力:配置管理。简介Nacos除了实现了服务的注册发现之外,还将配置中心功能整合在了一起。通过Nacos的配置管理功能,我们可以将整个架构体系内的所有配置都集中在Nacos中存储。这样做的好处,在以往的教程中介绍Spring Cloud Config时也有提到,主要有以下几点:分离的多环境配置,可以更灵活的管理权限,安全性更高应用程序的打包更为纯粹,以实现一次打包,多处运行的特点(《云原声应用的12要素》之一)Nacos的配置管理模型与淘宝开源的配置中心Diamond类似,基础层面都通过DataId和Group来定位配置内容,除此之外还增加了很多其他的管理功能。快速入门下面我们通过一个简单的例子来介绍如何在Nacos中创建配置内容以及如何在Spring Cloud应用中加载Nacos的配置信息。创建配置第一步:进入Nacos的控制页面,在配置列表功能页面中,点击右上角的“+”按钮,进入“新建配置”页面,如下图填写内容:其中:Data ID:填入alibaba-nacos-config-client.propertiesGroup:不修改,使用默认值DEFAULT_GROUP配置格式:选择Properties配置内容:应用要加载的配置内容,这里仅作为示例,做简单配置,比如:didispace.title=spring-cloud-alibaba-learning创建应用第一步:创建一个Spring Boot应用,可以命名为:alibaba-nacos-config-client。第二步:编辑pom.xml,加入必要的依赖配置,比如:<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!– lookup parent from repository –></parent><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>0.2.1.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> <optional>true</optional> </dependency></dependencies>上述内容主要三部分:parent:定义spring boot的版本dependencyManagement:spring cloud的版本以及spring cloud alibaba的版本,由于spring cloud alibaba还未纳入spring cloud的主版本管理中,所以需要自己加入dependencies:当前应用要使用的依赖内容。这里主要新加入了Nacos的配置客户端模块:spring-cloud-starter-alibaba-nacos-config。由于在dependencyManagement中已经引入了版本,所以这里就不用指定具体版本了。可以看到,这个例子中并没有加入nacos的服务发现模块,所以这两个内容是完全可以独立使用的第三步:创建应用主类,并实现一个HTTP接口:@SpringBootApplicationpublic class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Slf4j @RestController @RefreshScope static class TestController { @Value("${didispace.title:}") private String title; @GetMapping("/test") public String hello() { return title; } }}内容非常简单,@SpringBootApplication定义是个Spring Boot应用;还定义了一个Controller,其中通过@Value注解,注入了key为didispace.title的配置(默认为空字符串),这个配置会通过/test接口返回,后续我们会通过这个接口来验证Nacos中配置的加载。另外,这里还有一个比较重要的注解@RefreshScope,主要用来让这个类下的配置内容支持动态刷新,也就是当我们的应用启动之后,修改了Nacos中的配置内容之后,这里也会马上生效。第四步:创建配置文件bootstrap.properties,并配置服务名称和Nacos地址spring.application.name=alibaba-nacos-config-clientserver.port=8001spring.cloud.nacos.config.server-addr=127.0.0.1:8848注意:这里必须使用bootstrap.properties。同时,spring.application.name值必须与上一阶段Nacos中创建的配置Data Id匹配(除了.properties或者.yaml后缀)。第五步:启动上面创建的应用。2019-01-27 18:29:43.497 INFO 93597 — [ main] o.s.c.a.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: ‘alibaba-nacos-config-client.properties’, group: ‘DEFAULT_GROUP'2019-01-27 18:29:43.498 INFO 93597 — [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name=‘NACOS’, propertySources=[NacosPropertySource {name=‘alibaba-nacos-config-client.properties’}]}在启动的时候,我们可以看到类似上面的日志信息,这里会输出应用程序要从Nacos中获取配置的dataId和group。如果在启动之后,发现配置信息没有获取到的时候,可以先从这里着手,看看配置加载的目标是否正确。第六步:验证配置获取和验证动态刷新用curl或者postman等工具,访问接口: localhost:8001/test,一切正常的话,将返回Nacos中配置的spring-cloud-alibaba-learning。然后,再通过Nacos页面,修改这个内容,点击发布之后,再访问接口,可以看到返回结果变了。同时,在应用的客户端,我们还能看到如下日志:2019-01-27 18:39:14.162 INFO 93597 — [-127.0.0.1_8848] o.s.c.e.event.RefreshEventListener : Refresh keys changed: [didispace.title]在Nacos中修改了Key,在用到这个配置的应用中,也自动刷新了这个配置信息。参考资料Nacos官方文档Nacos源码分析代码示例本文示例读者可以通过查看下面仓库的中的alibaba-nacos-config-client项目:Github:https://github.com/dyc87112/SpringCloud-Learning/Gitee:https://gitee.com/didispace/SpringCloud-Learning/如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!以下专题教程也许您会有兴趣Spring Boot基础教程Spring Cloud基础教程 ...

January 30, 2019 · 1 min · jiezi

鲜为人知的混沌工程,到底哪里好?

阿里妹导读:混沌工程属于一门新兴的技术学科,行业认知和实践积累比较少,大多数IT团队对它的理解还没有上升到一个领域概念。阿里电商域在2010年左右开始尝试故障注入测试的工作,希望解决微服务架构带来的强弱依赖问题。通过本文,你将了解到:为什么需要混沌工程,阿里巴巴在该领域的实践和思考、未来的计划。一、为什么需要混沌工程?(翻译自Chaos Engineering电子书)1.1 混沌工程与故障测试的区别混沌工程是在分布式系统上进行实验的学科, 目的是建立对系统抵御生产环境中失控条件的能力以及信心,最早由Netflix及相关团队提出。故障演练是阿里巴巴在混沌工程领域的产品,目标是沉淀通用的故障模式,以可控成本在线上重放,以持续性的演练和回归方式运营来暴露问题,不断推动系统、工具、流程、人员能力的不断前进。混沌工程、故障注入和故障测试在关注点和工具中都有很大的重叠。混沌工程和其他方法之间的主要区别在于,混沌工程是一种生成新信息的实践,而故障注入是测试一种情况的一种特定方法。当想要探索复杂系统可能出现的不良行为时,注入通信延迟和错误等失败是一种很好的方法。但是我们也想探索诸如流量激增,激烈竞争,拜占庭式失败,以及消息的计划外或不常见的组合。如果一个面向消费者的网站突然因为流量激增而导致更多收入,我们很难称之为错误或失败,但我们仍然对探索系统的影响非常感兴趣。同样,故障测试以某种预想的方式破坏系统,但没有探索更多可能发生的奇怪场景,那么不可预测的事情就可能发生。测试和实验之间可以有一个重要的区别。在测试中,进行断言:给定特定条件,系统将发出特定输出。测试通常是二进制态的,并确定属性是真还是假。严格地说,这不会产生关于系统的新知识,它只是将效价分配给它的已知属性。实验产生新知识,并经常提出新的探索途径。我们认为混沌工程是一种实验形式,可以产生关于系统的新知识。它不仅仅是一种测试已知属性的方法,可以通过集成测试更轻松地进行验证。混沌实验的输入示例:模拟整个区域或数据中心的故障。部分删除各种实例上的Kafka主题。重新创建生产中发生的问题。针对特定百分比的交易服务之间注入一段预期的访问延迟。基于函数的混乱(运行时注入):随机导致抛出异常的函数。代码插入:向目标程序添加指令和允许在某些指令之前进行故障注入。时间旅行:强制系统时钟彼此不同步。在模拟I/O错误的驱动程序代码中执行例程。在 Elasticsearch 集群上最大化CPU核心。混沌工程实验的机会是无限的,可能会根据分布式系统的架构和组织的核心业务价值而有所不同。1.2 实施混沌工程的先决条件要确定是否已准备好开始采用混沌工程,需要回答一个问题:你的系统是否能够适应现实世界中的事件,例如服务故障和网络延迟峰值?如果答案是“否”,那么你还有一些工作要做。混沌工程非常适合揭露生产系统中未知的弱点,但如果确定混沌工程实验会导致系统出现严重问题,那么运行该实验就没有任何意义。先解决这个弱点,然后回到混沌工程,它将发现你不了解的其他弱点,或者它会让你发现你的系统实际上是有弹性的。混沌工程的另一个基本要素是可用于确定系统当前状态的监控系统。1.3 混沌工程原则为了具体地解决分布式系统在规模上的不确定性,可以把混沌工程看作是为了揭示系统弱点而进行的实验。破坏稳态的难度越大,我们对系统行为的信心就越强。如果发现了一个弱点,那么我们就有了一个改进目标。避免在系统规模化之后问题被放大。以下原则描述了应用混沌工程的理想方式,这些原则来实施实验过程。对这些原则的匹配程度能够增强我们在大规模分布式系统的信心。二、阿里巴巴在混沌工程领域的实践:故障演练混沌工程属于一门新兴的技术学科,行业认知和实践积累比较少,大多数IT团队对它的理解还没有上升到一个领域概念。阿里电商域在2010年左右开始尝试故障注入测试的工作,开始的目标是想解决微服务架构带来的强弱依赖问题。后来经过多个阶段的改进,最终演进到 MonkeyKing(线上故障演练平台)。从发展轨迹来看,阿里的技术演进和Netflix的技术演进基本是同时间线的,每个阶段方案的诞生都有其独特的时代背景和业务难点,也可以看到当时技术的局限性和突破。2.1 建立一个围绕稳定状态行为的假说目前阿里巴巴集团范围内的实践偏向于故障测试,即在一个具体场景下实施故障注入实验并验证预期是否得到满足。这种测试的风险相对可控,坏处是并没有通过故障注入实验探索更多的场景,暴露更多的潜在问题,测试结果比较依赖实施人的经验。当前故障测试的预期比较两级分化,要么过于关注系统的内部细节,要么对于系统的表现完全没有预期,与混沌工程定义的稳态状态行为差异比较大。引起差异的根本原因还是组织形态的不同。2014年,Netflix团队创建了一种新的角色,叫作混沌工程师(Chaos Enigneer),并开始向工程社区推广。而阿里目前并没有一个专门的职位来实施混沌工程,项目目标、业务场景、人员结构、实施方式的不同导致了对于稳定状态行为的定义不太标准。2.2 多样化真实世界的事件阿里巴巴因为多元化的业务场景、规模化的服务节点及高度复杂的系统架构,每天都会遇到各式各样的故障。这些故障信息就是最真实的混沌工程变量。为了能够更体感、有效率地描述故障,我们优先分析了P1和P2的故障(P是阿里对故障等级的描述),提出一些通用的故障场景并按照IaaS层、PaaS层、SaaS层的角度绘制了故障画像。从故障的完备性角度来看,上述画像只能粗略代表部分已出现的问题,对于未来可能会出现的新问题也需要一种手段保持兼容。在更深入的进行分析之后,我们定义了另一维度的故障画像:任何故障,一定是硬件如IaaS层,软件如PaaS或SaaS的故障。并且有个规律,硬件故障的现象,一定可以在软件故障现象上有所体现。故障一定隶属于单机或是分布式系统之一,分布式故障包含单机故障。对于单机或同机型的故障,以系统为视角,故障可能是当前进程内的故障,比如:如FullGC,CPU飙高;进程外的故障,比如其他进程突然抢占了内存,导致当前系统异常等。同时,还可能有一类故障,是人为失误,或流程失当导致,这部分我们今天不做重点讨论。从故障注入实现角度,我们也是参照上述的画像来设计的。之前我们是通过Java字节码技术和操作系统层面的工具来分别模拟进程内和进程外的故障。随着Serverless、Docker等新架构、新技术的出现,故障实现机制和承接载体也将会有一些新的变化。2.3 在生产环境中运行实验从功能性的故障测试角度来看,非生产环境去实施故障注入是可以满足预期的,所以最早的强弱依赖测试就是在日常环境中完成的。不过,因为系统行为会根据环境和流量模式有所不同,为了保证系统执行方式的真实性与当前部署系统的相关性,推荐的实施方式还是在生产环境(仿真环境、沙箱环境都不是最好的选择)。很多同学恐惧在生产环境执行实验,原因还是担心故障影响不可控。实施实验只是手段,通过实验对系统建立信心是我们的目标。关于如何减少实验带来的影响,这点在"最小化爆炸半径"部分会有阐述。2.4 持续自动化运行实验2014年,线下环境的强弱依赖测试用例是默认在每次发布后自动执行的。2015年,开始尝试在线上进行自动化回归。不过发展到最近两年,手动实验的比例逐渐变高。原因也不复杂,虽然故障注入自动化了,业务验证的成本仍然比较高。在业务高速发展、人员变化较快的环境之下,保持一套相对完善的线上回归用例集对是见非常难的事情。虽然也出现了流量录制技术,不过因为混沌工程实验本身会打破系统已有的行为,基于入口和出口的流量比对的参考度就下降许多。为了解决测试成本问题,2017年初开始推进线上微灰度环境的建设。基于业务、比例来筛选特征流量,通过真实的流量来替换原来的测试流量,通过监控&报警数据来替代测试用例结果。目前已经有部分业务基于微灰度+故障演练的模式来做演练验证(比如:盒马APOS容灾演习)。因为故障演练之前是作为一个技术组件被嵌入到常态和大促的流程中,所以在系统构建自动化的编排和分析方面的产品度并不高。演练可视化编排和能力开放会是我们团队未来的一个重点,下文中的规划部分会有所阐述。2.5 最小化爆炸半径在生产中进行试验可能会造成不必要的客户投诉,但混沌工程师的责任和义务是确保这些后续影响最小化且被考虑到。对于实验方案和目标进行充分的讨论是减少用户影响的最重要的手段。但是从实际的实施角度看,最好还是通过一些技术手段去最小化影响。Chaos Engineering和Fault Injection Test的核心区别在于:是否可以进一步减小故障的影响,比如微服务级别、请求级别甚至是用户级别。在MonkeyKing演进的中期阶段,已经可以实现请求级别的微服务故障注入。虽然那个时候演练实施的主要位置在测试环境,但初衷也是为了减少因为注入故障而导致的环境不稳定问题。除了故障注入,流量路由和数据隔离技术也是减少业务影响的有效手段。三、未来的计划线上故障演练发展到今天是第三年,随着阿里安全生产的大环境、业务方的诉求、研发迭代模式的变化,以及大家对混沌工程的接受和认识程度的提高。集团的演练领域会向着未来的几个目标发力:建立高可用专家库,结构化提高应用容错能力(解决"稳定状态定义"的问题)建设故障注入实现标准,集团内开源,提升故障模拟的广度和深度(拓宽"多样化真实世界的事件"的广度)规模化覆盖核心业务(提升"在生产环境中运行实验"的规模)以产品化、平台化思路开放演练能力(探索"自动化运行实验"的方式)四、触手可及的混沌工程MonkeyKing已经提供商业化产品,欢迎在阿里云官网搜索“AHAS”,进行免费公测。地址:https://www.aliyun.com/product/ahas本文作者:中亭阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

January 29, 2019 · 1 min · jiezi

微服务架构到底应该如何选择?

什么是微服务?微服务的概念最早是在 2014 年由 Martin Fowler 和 James Lewis 共同提出,他们定义了微服务是由单一应用程序构成的小服务,拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通讯。同时,服务会使用最小规模的集中管理 (例如 Docker)技术,服务可以用不同的编程语言与数据库等。微服务是SOA架构下的最终产物,该架构的设计目标是为了肢解业务,使得服务能够独立运行。主要有一下几个特点服务拆分粒度更细 微服务可以说是更细维度的服务化,小到一个子模块,只要该模块依赖的资源与其他模块都没有关系,那么就可以拆分为一个微服务。服务独立部署每个微服务都严格遵循独立打包部署的准则,互不影响。比如一台物理机上可以部署多个 Docker 实例,每个 Docker 实例可以部署一个微服务的代码。服务独立维护每个微服务都可以交由一个小团队甚至个人来开发、测试、发布和运维,并对整个生命周期负责。服务治理能力要求高因为拆分为微服务之后,服务的数量变多,因此需要有统一的服务治理平台,来对各个服务进行管理。微服务架构下,服务调用主要依赖下面几个基本组件:服务描述 注册中心 服务框架 服务监控 服务追踪 服务治理开源RPC框架介绍Dubbo国内最早开源的 RPC 框架,由阿里巴巴公司开发并于 2011 年末对外开源,仅支持 Java 语言。中间一度没人维护坑了不少人,17年重启维护焕发新春。架构图如下官网: http://dubbo.io/通信框架方面,Dubbo 默认采用了 Netty 作为通信框架。通信协议方面,Dubbo 除了支持私有的 Dubbo 协议外,还支持 RMI 协议、Hession 协议、HTTP 协议、Thrift 协议等。序列化格式方面,Dubbo 支持多种序列化格式,比如 Dubbo、Hession、JSON、Kryo、FST 等。性能:http://dubbo.apache.org/zh-cn…TarsTars是基于名字服务使用Tars协议的高性能RPC开发框架,同时配套一体化的服务治理平台,帮助个人或者企业快速的以微服务的方式构建自己稳定可靠的分布式应用。 Tars是将腾讯内部使用的微服务架构TAF(Total Application Framework)多年的实践成果总结而成的开源项目。官网:https://github.com/TarsCloud/…架构图如下开源协议为:BSD-3-Clause支持多语言 C++,Java,Nodejs,PHP,Go性能:https://github.com/TarsCloud/…gRPC一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。 官网:https://grpc.io基于HTTP/2 HTTP/2 提供了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU,帮助移动设备延长电池寿命等。gRPC 的协议设计上使用了HTTP2 现有的语义,请求和响应的数据使用HTTP Body 发送,其他的控制信息则用Header 表示。IDL使用ProtoBuf gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。压缩和传输效率高,语法简单,表达力强。多语言支持(C, C++, Python, PHP, Nodejs, C#, Objective-C、Golang、Java) gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中,grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。MotanMotan 是国内另外一个比较有名的开源的 RPC 框架,同样也只支持 Java 语言实现,它的架构可以用下面这张图描述。Motan 与 Dubbo 的架构类似,都需要在 Client 端(服务消费者)和 Server 端(服务提供者)引入 SDK,其中 Motan 框架主要包含下面几个功能模块。register:用来和注册中心交互,包括注册服务、订阅服务、服务变更通知、服务心跳发送等功能。Server 端会在系统初始化时通过 register 模块注册服务,Client 端会在系统初始化时通过 register 模块订阅到具体提供服务的 Server 列表,当 Server 列表发生变更时也由 register 模块通知 Client。protocol:用来进行 RPC 服务的描述和 RPC 服务的配置管理,这一层还可以添加不同功能的 filter 用来完成统计、并发限制等功能。serialize:将 RPC 请求中的参数、结果等对象进行序列化与反序列化,即进行对象与字节流的互相转换,默认使用对 Java 更友好的 Hessian 2 进行序列化。transport:用来进行远程通信,默认使用 Netty NIO 的 TCP 长链接方式。cluster:Client 端使用的模块,cluster 是一组可用的 Server 在逻辑上的封装,包含若干可以提供 RPC 服务的 Server,实际请求时会根据不同的高可用与负载均衡策略选择一个可用的 Server 发起远程调用。Spring CloudSpring Cloud 是为了解决微服务架构中服务治理而提供的一系列功能的开发框架,它是完全基于 Spring Boot 进行开发的,Spring Cloud 利用 Spring Boot 特性整合了开源行业中优秀的组件,整体对外提供了一套在微服务架构中服务治理的解决方案。它的架构图可以用下面这张图来描述。以下为Spring Cloud的核心功能:分布式/版本化配置服务注册和发现路由服务和服务之间的调用负载均衡断路器分布式消息传递Spring Cloud对于中小型互联网公司来说是一种福音,因为这类公司往往没有实力或者没有足够的资金投入去开发自己的分布式系统基础设施,使用Spring Cloud一站式解决方案能在从容应对业务发展的同时大大减少开发成本。下图是RPC框架详细的比较如何选择?一家A轮融资的公司 原来架构是net,想换java架构。 公司没有强大的研发实力,公司主要是to B业务,对并发要求不高,那可以试试Spring Cloud 架构, Spring Cloud 不仅提供了基本的 RPC 框架功能,还提供了服务注册组件、配置中心组件、负载均衡组件、断路器组件、分布式消息追踪组件等一系列组件,被技术圈的人称之为“Spring Cloud 全家桶”,而 Dubbo、Motan 基本上只提供了最基础的 RPC 框架的功能,其他微服务组件都需要自己去实现,对于这类研发能力弱的团队,SpringCloud 无疑是最合适的,减少了研发成本,社区热度高,相关的教程文档很多,减少了入门成本;再比如这家公司不准备切换Java框架还是继续使用net架构, 有一定的研发能力,对并发要求很高, 那gRPC无疑是最适合的,跨语言支持,高性能;没有完美的解决方案,只有最合适的推荐阅读互联网公司面试必问的Redis题目互联网公司面试必问的mysql题目(下)学习Java进阶技术干货、实践分享,职位内推,一起聊聊理想。志同道合的朋友,欢迎你的加入。 ...

January 29, 2019 · 1 min · jiezi

Spring Cloud Alibaba基础教程:支持的几种服务消费方式

通过《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBalancerClient接口来获取某个服务的具体实例,并根据实例信息来发起服务接口消费请求。但是这样的做法需要我们手工的去编写服务选取、链接拼接等繁琐的工作,对于开发人员来说非常的不友好。所以接下来,我们再来看看除此之外,还支持哪些其他的服务消费方式。使用RestTemplate在之前的例子中,已经使用过RestTemplate来向服务的某个具体实例发起HTTP请求,但是具体的请求路径是通过拼接完成的,对于开发体验并不好。但是,实际上,在Spring Cloud中对RestTemplate做了增强,只需要稍加配置,就能简化之前的调用方式。比如:@EnableDiscoveryClient@SpringBootApplicationpublic class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Slf4j @RestController static class TestController { @Autowired RestTemplate restTemplate; @GetMapping("/test") public String test() { String result = restTemplate.getForObject(“http://alibaba-nacos-discovery-server/hello?name=didi”, String.class); return “Return : " + result; } } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }}可以看到,在定义RestTemplate的时候,增加了@LoadBalanced注解,而在真正调用服务接口的时候,原来host部分是通过手工拼接ip和端口的,直接采用服务名的时候来写请求路径即可。在真正调用的时候,Spring Cloud会将请求拦截下来,然后通过负载均衡器选出节点,并替换服务名部分为具体的ip和端口,从而实现基于服务名的负载均衡调用。关于这种方式,可在文末仓库查看完整代码示例。而对于这种方式的实现原理,可以参考我之前写的这篇文章的前半部分:Spring Cloud源码分析(二)Ribbon使用WebClientWebClient是Spring 5中最新引入的,可以将其理解为reactive版的RestTemplate。下面举个具体的例子,它将实现与上面RestTemplate一样的请求调用:@EnableDiscoveryClient@SpringBootApplicationpublic class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Slf4j @RestController static class TestController { @Autowired private WebClient.Builder webClientBuilder; @GetMapping("/test”) public Mono<String> test() { Mono<String> result = webClientBuilder.build() .get() .uri(“http://alibaba-nacos-discovery-server/hello?name=didi”) .retrieve() .bodyToMono(String.class); return result; } } @Bean @LoadBalanced public WebClient.Builder loadBalancedWebClientBuilder() { return WebClient.builder(); }}可以看到,在定义WebClient.Builder的时候,也增加了@LoadBalanced注解,其原理与之前的RestTemplate时一样的。关于WebClient的完整例子也可以通过在文末的仓库中查看。使用Feign上面介绍的RestTemplate和WebClient都是Spring自己封装的工具,下面介绍一个Netflix OSS中的成员,通过它可以更方便的定义和使用服务消费客户端。下面也举一个具体的例子,其实现内容与上面两种方式结果一致:第一步:在pom.xml中增加openfeign的依赖:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId></dependency>第二步:定义Feign客户端和使用Feign客户端:@EnableDiscoveryClient@SpringBootApplication@EnableFeignClientspublic class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Slf4j @RestController static class TestController { @Autowired Client client; @GetMapping("/test") public String test() { String result = client.hello(“didi”); return “Return : " + result; } } @FeignClient(“alibaba-nacos-discovery-server”) interface Client { @GetMapping("/hello”) String hello(@RequestParam(name = “name”) String name); }}这里主要先通过@EnableFeignClients注解开启扫描Spring Cloud Feign客户端的功能;然后又创建一个Feign的客户端接口定义。使用@FeignClient注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用Spring MVC的注解就可以来绑定服务提供方的REST接口,比如下面就是绑定alibaba-nacos-discovery-server服务的/hello接口的例子。最后,在Controller中,注入了Client接口的实现,并调用hello方法来触发对服务提供方的调用。关于使用Feign的完整例子也可以通过在文末的仓库中查看。深入思考如果之前已经用过Spring Cloud的读者,肯定会这样的感受:不论我用的是RestTempalte也好、还是用的WebClient也好,还是用的Feign也好,似乎跟我用不用Nacos没啥关系?我们在之前介绍Eureka和Consul的时候,也都是用同样的方法来实现服务调用的,不是吗?确实是这样,对于Spring Cloud老手来说,就算我们更换了Nacos作为新的服务注册中心,其实对于我们应用层面的代码是没有影响的。那么为什么Spring Cloud可以带给我们这样的完美编码体验呢?实际上,这完全归功于Spring Cloud Common的封装,由于在服务注册与发现、客户端负载均衡等方面都做了很好的抽象,而上层应用方面依赖的都是这些抽象接口,而非针对某个具体中间件的实现。所以,在Spring Cloud中,我们可以很方便的去切换服务治理方面的中间件。代码示例本文示例读者可以通过查看下面仓库:Github:https://github.com/dyc87112/SpringCloud-Learning/Gitee:https://gitee.com/didispace/SpringCloud-Learning/其中,本文的几种示例可查看下面的几个项目:alibaba-nacos-discovery-server:服务提供者,必须启动alibaba-nacos-discovery-client-resttemplate:使用RestTemplate消费alibaba-nacos-discovery-client-webclient:使用WebClient消费alibaba-nacos-discovery-client-feign:使用Feign消费如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!以下专题教程也许您会有兴趣Spring Boot基础教程Spring Cloud基础教程 ...

January 29, 2019 · 1 min · jiezi

微服务不是全部,只是特定领域的子集

大家都在学SpringCloud,貌似学会了SC就牛逼哄哄,感觉不得了的样子。但微服务,在整个企业级应用中,只占了一小部分。微服务引入的问题比解决的问题还要多,你会遇到各种各样的bottleneck。微服务解决的是计算节点的问题,然而根源却在存储节点。当业务规模变得越来越庞大,存储、编码、管理都会成为问题。接下来我们谈一些放之四海而皆准的道理,不需要贴上"XX公司最佳实践"之类的标签。下面是一张因数据扩张引出的微服务相关的图,简约但不简单。中小型公司只要有这些元素,就能玩的很好;大点的公司,因为规模太大,每个组件都会遇到瓶颈,所谓的专项的优化并不能脱离它的本质。那我们开始。注意,这张图仅是主要数据路径,一个子集,其他的包括CDN、通讯层等,不在此列。这张图并不包含某个特定领域的具体架构,属于一个整体性的概括。我们从数据库容量的瓶颈说起,看一下微服务在其中的比重。数据库用户数据要存储,就存在数据库。过去这么多年,NoSQL并不能消除开发人员的恐惧,所以,MySQL之类还是大多数公司的首选存储。假设你的业务增长的很好,这个就有意思多了。项目开始,你的sql玩的越6,那么给后人埋的坑,越多。因为sql的功能太丰富了,一不小心,就炫技了。你会发现,林子越大,对sql的规范要求越高。一些官宣的特性,在公司内是严格禁止的。市场发展很好,终于来报应了。以前的技巧变成了现在的累赘。慢查询、全文扫描,招招毙命。想要加缓存,结果发现无从下手;想要分库分表,结果发现表关系错综复杂。小表和宽表所以第一步,还是得去填坑。一个超过3个表的联合查询业务,大概率是不合理的。在加缓存和分库分表之前,还是得重新设计一下数据表。忘掉什么数据库范式,我们将存在两类表:小表和宽表。小表提供了最基本的数据,可能一个简单的KV就完成了。一些联合查询,是直接可以在程序里进行循环拼接的。程序里循环1000次10毫秒的查询,比单次查询耗费6秒要强的多。这就是分布式系统的特点,小耗时的批量查询,比hang在那里更加有生命力。宽表通过冗余的方式,提供了某个重要功能常用的分析数据。这种表的字段一般都特别多,在写入时通过拼接获取冗余数据,一般用在读多写少的场景。完成了这一步,接下来的工作才能进行。分库分表在《“分库分表" ?选型和流程要慎重,否则会失控》中,详细的说明了分库分表的选型,这里浅谈一下过程。分库分表很可能会引入某一种中间件,因为仅仅将数据库分开还不行。HA,FailOver等特性,是同时需要的。分库分为垂直分和水平分。垂直面向的是业务拆分,即将一部分表按照业务逻辑独立到其他库中;水平面向的是容量,即通过分库分表的模式使数据有一个扩张的途径。数据一定要有一个可以度量的切分维度,否则就过于分散,或者过于倾斜,影响后续的处理。数据同步有分就有合,比如某些报表业务需要全量的数据。不同业务通过共享数据库来共享数据不得不说是个非常蠢的主意。这个时候就需要一些数据同步工具。数据同步组件可以说是一个公司的必备组件。有基于最后更新时间的高延迟同步工具,也有基于binlog的低延迟同步工具。有的公司为了稳定,还会有所谓的多机房同步。 数据同步最怕异常,因为大多数同步都有顺序性要求。一切运行良好的时候,大家皆大欢喜;一旦出现异常,就需要其他手段来保证异常期间的数据同步和延迟。这都是些脏活,自动化有时候会适得其反,监控是第一位的。分层的数据存储可以预见的是,即使你分库分表了,还是能很快达到瓶颈。分库分表后,你的一些统计功能可能还用不了了,在一些传统的管理系统上,这是硬伤。一个分层的数据存储层是必要的。你的一些业务,可能一个分支走的是MySQL,换了另外一个条件就成了ES。不同的DB做不同的事情。RDBMS只做原是数据的存储和查询,是扁平快的数据通道;特定的单机高性能DB,做一些汇聚和科学计算;分布式的类RT的存储,用来存储一些中等规模的数据,并提供一些中延迟的搜索功能;海量的存储系统,存储系统所有的历史记录,并提供离线分析功能。不要想着某一类存储解决所有的问题,那是骗人的。存储部分的复杂性不是普通的微服务能够相比的。 是谁保证了分层的数据存储设计呢?除了一部分通过MQ分发数据的业务,还是得靠我们的数据同步组件。缓存但DB的压力实在是太大了,我们不得不考虑缓存。缓存不能乱用,有两个原则:一个是缓存不能侵入业务,也就是不能带有业务逻辑;一个是缓存的命中率要高,否则适得其反。缓存是对高并发、高速接口的补充,是系统稳定性的必要不充分条件。除了Redis等外置的缓存集群,jvm内缓存也是一个比较重要的场所。缓存的存在是因为I/O设备的缓慢,通常放在内存中,断电后即消失。缓存涉及到源数据库和缓存数据库之间的数据同步。通常,更新源库时,会同时删掉缓存中相关的就数据,这样在下次读取的时候,能够读取到最新的数据。缓存限制最大的就是其容量问题,而且都贵的很。假如业务模式固定,一些kv存储使用LevelDB或者HBase等方案,会显著节约成本。模块化是时候将工程模块化了,毕竟上百个程序员共享一个代码库,风险已经很大了。模块化通常会按照业务线进行拆分。比如,支付模块和报表模块的拆分。模块拆分后,相似的模块会共享数据库。但更多的是通过冗余数据来解决,这样能将业务解耦,一部分出现问题,另一部分能够运行良好。好比你隔壁出了杀人案你第二天还能正常去上班。模块之间要找到一种交互方式,比如使用HttpClient、OkHttp等。重要的是统一,统一了以后就有一个高大上的名字了:RPC。一个小模块很有可能会发展为一个大的业务线,也有可能无人问津。MQ模块化之间另一种共享数据或者数据交互的方式就是MQ。除了有削峰等功效,MQ更多改变的是一种交互模式,一种对业务的解耦。Kafka几乎每个公司都在用,最高能有几十万的吞吐量。RabbitMQ、RocketMQ等,更多用在可靠性要求非常高的场景,但比较耗机器。MQ资源一般都要求绝对的高可靠,作为基础设施,一旦出问题,将带来非常大的事故。设计的时候要考虑异常情况下的数据处理流向,以及MQ恢复后的补偿策略。MQ集群设计的比较小一些才合理,避免不同业务,不同可靠性级别的消息互相影响。MQ在业务上和功能上要相互隔离,做到最小服务集合。为了避免MQ当机对正常业务产生影响,非重要链路上的MQ不能阻塞业务的正常进行,这种消息通常通过异步线程发送。微服务我们已经使用消息和模块化,将系统拆分成了多个工程。将这些工程使用统一的方式管理起来,统一其交互模式和在上面的治理,就是微服务的范畴。微服务就是一个多模块项目规范化的过程。非规范的服务与微服务体系,是要共存一段时间的,如何保证新旧服务的替换,是一个管理上的问题。功能组件根据SpringCloud的描述,一个服务想要被发现,需要将自己注册到通用的注册中心,其他服务可以从同一个地方,获取它的实例,进而调用。而真正产生调用的功能,就是RPC的功能。RPC要考虑一系列比如超时、重拾、熔断等功能。在某些访问量非常大的节点,可能还要考虑预热。RPC要能产生一些统计性数据,比如TPS、QPS、TP值等,很显然SpringCloud是缺乏的,我们要借助外部系统进行分析。在外部请求流转到内部之前,需要经过一层网关的处理。像一些通用的操作,比如权限、限流、灰度等,就可以在网关层处理。服务治理微服务最重要的特色就是其治理功能。服务治理的依据就是监控信息。通过统计每次调用的大小、耗时、分布,能够得出服务的大体拓扑。通常以下信息最有用:1、QPS,时间序列的qps分布,最高区间qps2、平均响应时间,接口的平均响应时间,最大耗时和最小耗时3、TP值分布,90%,99%等请求是在x耗时内完成通过以上信息能够对服务进行画像。是扩容、缩容、专项治理的数据依据。微服务引出的另外一个问题就是调用链,即某个请求的真实路径。分布式环境下的问题排查,会非常的困难,调用链能够帮助研发快速定位问题,并帮助理解业务的数据流向。服务治理的目的就是找到不合理的请求和分布,比如某个接口耗时太长;某个接口请求量大,需要加缓存;某个功能依赖链条过长,需要业务优化等。服务治理要借助大量的外部分析工具,更多通用的业务模型,需要大数据平台的支持。我们把监控/报警也放在服务治理的部分,在《这么多监控组件,总有一款适合你》中,我们详细的讨论了监控部分的技术选择方案。日志微服务产生的另外一个问题就是日志太过分散。一个核心的业务可能有上百个实例,你不可能打开100个终端去看日志。这就涉及到日志的收集。日志归集功能就是把分散的日志集合到一个地方,它的主要挑战就是数据量。通常日志分为两部分,一部分是全量的,可以通过定时同步等方式,备份到日志堡垒机或者hdfs中;一部分是过滤后的日志,比如一些异常信息,集中在某一个处理平台中进行报警。很多研发喜欢将用户行为数据输出到日志文件中,这部分日志被收集后,会通过流计算或者离线计算,得到一些推荐和模型。日志信息进入了大数据处理的范畴,我们不过多描述。持续集成如果一个上点规模的公司,技术团队有什么值得一做的系统,那么发布系统算一个。《发布系统有那么难么?》中,谈了一种可能的模式。发布系统就是给一堆脚本包了一张方便的皮。一些流程性工具、发布验证、CI/CD功能,很容易能够添加到自己的发布系统中。很多微服务推广的文章中,谈到虚拟化(Docker)等,其实不是必须的。虚拟化减少了服务编排的时间,能够方便的进行扩容和缩容,但对监控、日志收集、网络拓扑等,要求比较高。建议是整个体系中的最后一步而不是第一步。你的系统是否灵活,还与公司的文化环境相关。如果上个线走审批流程就需要一两周,那么做一个敏捷的持续集成系统就不是那么必要了。基础设施基础设施更多指的是运维体系,这是支撑整个系统健康发展的基石。我倾向于基础运维和基础架构不分家,因为它们的模式和文化,是一个公司研发环境的基石。另外一些基础组件,比如配置中心、调度中心、分布式锁管理等,都对可靠性有较高的要求。END这套体系看着简单,也有固定的解决方案。但问题就在于,许多公司从成立玩到倒闭,玩了那么多年,还是没玩好。真是可怜。

January 25, 2019 · 1 min · jiezi

关于开源分布式事务中间件Fescar,我们总结了开发者关心的13个问题

开源分布式事务中间件 Fescar 自1月10日上线v0.1版本以来,受到了开发者们的极大关注(watch249,star3005,fork649,社区讨论的issue58,数据统计于1月17日14:00),可见,天下苦分布式事务久矣。为此,我们收集了大家在社区(Github)和社群(钉钉群&微信群)关注的核心问题,总结如下,并给出回复。Q1:Fescar 的发展经历了哪些历程?和阿里云全局事务服务GTS之间是什么关系?A1:阿里巴巴是国内最早一批进行应用分布式(微服务化)改造的企业,所以很早就遇到微服务架构下的分布式事务问题。2014 年阿里巴巴中间件团队发布TXC(Taobao Transaction Constructor),为集团内应用提供分布式事务服务。2016 年TXC 经过产品化改造,以GTS(Global TransactionService)的身份上线阿里云,成为当时业界唯一一款云上分布式事务产品,以阿里云公有云或专有云解决方案的形式,交付给众多外部客户。2019 年基于 TXC 和 GTS 的技术积累,阿里巴巴中间件团队发起了开源项目Fescar(Fast & EaSy Commit And Rollback, FESCAR),和社区一起建设这个分布式事务解决方案。TXC/GTS/Fescar一脉相承,为解决微服务架构下的分布式事务问题交出了一份与众不同的答卷。Q2:Fescar 有哪些适用场景?A2:Fescar 的愿景是让分布式事务的使用像现在本地事务的使用一样简单、高效,最终的目标是希望可以适用于所有的分布式事务场景。目前,核心的 AT 模式适用于构建于支持本地 ACID 事务的关系型数据库。非关系型数据库类资源的管理,通过 MT 模式来支持。AT 模式与 MT 模式完全兼容,所以可以在同一个分布式事务中,同时管理两类资源。Q3:目前有已经有一些其他的分布式事务开源方案,Fescar 和他们之间有哪些区别?和JTA支持分布式事务有哪些区别?A3:既有的分布式事务解决方案按照对业务侵入性分为两类,即:对业务无侵入的和对业务有侵入的。业务无侵入的方案既有的主流分布式事务解决方案中,对业务无侵入的只有基于 XA 的方案(注:问题中提到的 JTA 是XA 方案的 Java 版本),但应用XA 方案存在 3 个方面的问题:1、要求数据库提供对 XA 的支持。如果遇到不支持 XA(或支持得不好,比如 MySQL 5.7 以前的版本)的数据库,则不能使用。2、受协议本身的约束,事务资源(数据记录、数据库连接)的锁定周期长。长周期的资源锁定从业务层面来看,往往是不必要的,而因为事务资源的管理器是数据库本身,应用层无法插手。这样形成的局面就是,基于 XA 的应用往往性能会比较差,而且很难优化。3、已经落地的基于 XA 的分布式解决方案,都依托于重量级的应用服务器(Tuxedo/WebLogic/WebSphere 等),这是不适用于微服务架构的。侵入业务的方案实际上,最初分布式事务只有 XA 这个唯一方案。XA 是完备的,但在实践过程中,由于种种原因(包含但不限于上面提到的3 点)往往不得不放弃,转而从业务层面着手来解决分布式事务问题。比如:基于可靠消息的最终一致性方案TCCSaga都属于这一类。这些方案的具体机制在这里不做展开,网上这方面的论述文章非常多。总之,这些方案都要求在应用的业务层面把分布式事务技术约束考虑到设计中,通常每一个服务都需要设计实现正向和反向的幂等接口。这样的设计约束,往往会导致很高的研发和维护成本。不可否认,侵入业务的分布式事务方案都经过大量实践验证,能有效解决问题,在各行种业的业务应用系统中起着重要作用。但回到原点来思考,这些方案的采用实际上都是迫于无奈。回到问题:与基于消息的最终一致、TCC、Saga等业务逻辑侵入方案的不同在于,Fescar 的设计初衷就是保持对业务的非侵入性,不要求业务层面按照分布式事务的特定场景来设计正向和反向的两套(甚至多套)业务逻辑。这方面的差别就不展开了。与 XA 的区别在于,设计了一套不同与 XA 的两阶段协议,在保持对业务不侵入的前提下,保证良好的性能,也避免了对底层数据库协议支持的要求。可以看作是一套轻量级的XA 机制。具体的差别如下:架构层次XA方案的 RM 实际上是在数据库层,RM本质上就是数据库自身(通过提供支持 XA 的驱动程序来供应用使用)。而 Fescar 的RM 是以二方包的形式作为中间件层部署在应用程序这一侧的,不依赖与数据库本身对协议的支持,当然也不需要数据库支持XA 协议。这点对于微服务化的架构来说是非常重要的:应用层不需要为本地事务和分布式事务两类不同场景来适配两套不同的数据库驱动。这个设计,剥离了分布式事务方案对数据库在协议支持上的要求。两阶段提交先来看一下 XA 的2PC 过程。无论 Phase2 的决议是commit 还是 rollback,事务性资源的锁都要保持到Phase2 完成才释放。再看 Fescar 的2PC 过程。分支事务中数据的 本地锁 由本地事务管理,在分支事务 Phase1 结束时释放。同时,随着本地事务结束,连接 也得以释放。分支事务中数据的 全局锁 在事务协调器侧管理,在决议 Phase2 全局提交时,全局锁马上可以释放。只有在决议全局回滚的情况下,全局锁 才被持有至分支的 Phase2 结束。这个设计,极大地减少了分支事务对资源(数据和连接)的锁定时间,给整体并发和吞吐的提升提供了基础。Q4:Fescar 支持 Dubbo 的哪些版本?A4:所有版本。Q5:Fescar 支持 Spring Cloud么?A5:Fescar 与微服务框架的接口点在于,需要把事务的唯一标识 XID(一个字符串)通过微服务框架的服务调用间调用的机制中,透明地传递,并通过 Fescar 的 API 来绑定(或解绑)到应用的线程上下文中。(机制可以参考内置的对 Dubbo 支持的实现 com.alibaba.fescar.dubbo.TransactionPropagationFilter)所以,本质上这个问题不是支不支持 Spring Cloud,而是如何支持 Spring Cloud 中选用的服务调用机制。目前正在和 Spring Cloud Alibaba 的同学合作,准备在v0.5.x版本(或更早)发布对 Spring Cloud默认的支持。同时,非常欢迎社区的朋友参与进来,贡献包括 Spring Cloud 在内的各类微服务框架的支持。Q6:Fescar 是否支持本地跨库多数据源?除了关系型数据库,是否还支持NoSQL数据库?A6:本地跨多数据源同样是支持的,在 Fescar 的架构中,同一个服务中的多个数据源与跨服务的多个数据源,没有本质区别。AT 模式目前仅限于对关系型数据库的支持(本身具备ACID 事务支持),后面会发布出来的 MT 模式可以支持 NoSQL 这类本身不具备本地事务支持的资源。Q7:Fescar 现在开源的是AT模式,MT模式暂时不支持,什么时候会开源?A7:当前 0.1.0 版本只是把 Fescar 最核心的 AT 模式的最小集发布出来,一方面是按开源的规划和架构的重构进展,另一方面也是希望通过最小集版本,让用户和开发者社区更容易理解到我们核心的设计思路,让更多人比较容易地参与进来建设,而不是完全由阿里巴巴主导,仅仅把我们的整套方案开源出来给大家用而已。阿里巴巴在分布式事务上的技术积累,我们会通过 Fescar 项目毫无保留地贡献给社区,所有功能特性都会按规划和社区的反馈陆续开源出来。MT 按初步的计划,会在 0.5.x 版本发布。Q8:Fescar 什么时候提供HA cluster,单节点的server的瓶颈如何处理?A8:按初步的计划,HA Cluster 会在 0.5.x 版本发布,解决单机部署的单点问题。Q9:因网络中断、网张闪断、节点宕机和超时等引起的异常,Fescar会提供相应的补偿措施么?A9:这些异常情况的处理是分布式事务解决方案的基本要求,Fescar 同样也是提供了整套方案来处理各类异常场景。这方面的具体机制会在 HA Cluster 版本发布时,给出全面的分析介绍。Q10:Fescar框架中,如何监控分布式事务?A10:监控是非常重要的一块儿内容。TXC 和 GTS 的监控在阿里巴巴内部使用了很多基础设施的辅助。而在开源版本中,我们还没有一个现成的监控方案。大体上,监控的基础是两个方面:一方面是日志,通过日志的采集和处理,可以形成一个完整的事务链路,这些数据对于业务层面的分析和调优是重要的参考依据。另一方面是 API,Fescar 会提供一套管控 API,用于对运行时事务的管理。我们后续会把这两方面的数据格式、部署形态及接口整理出来,希望和社区来共建监控这个重要的方面。Q11:Fescar 的roadmap 有了么?A11:目前最新的roadmap如下:v0.1.0微服务框架支持: Dubbo数据库支持: MySQL基于 Spring AOP 的 Annotation事务协调器: 单机版本v0.5.x微服务框架支持: Spring CloudMT 模式支持 TCC 模式事务的适配动态配置和服务发现事务协调器: 高可用集群版本v0.8.xMetrics控制台: 监控/部署/升级/扩缩容v1.0.0General Availability: 生产环境适用v1.5.x数据库支持: Oracle/PostgreSQL/OceanBase不依赖 Spring AOP 的 Annotation热点数据的优化处理机制RocketMQ 事务消息纳入全局事务管理NoSQL 纳入全局事务管理的适配机制支持 HBase支持 Redisv2.0.0支持 XA当然,项目迭代演进的过程,我们最重视的是社区的声音,路线图会和社区充分交流及时进行调整。Q12:Fescar 官网什么时候上线?A12:Fescar 官方域名已经注册,官网将采用静态开源站点搭建工具Docsite「传送门」进行搭建,logo 已经设计并将于近期公布。Q13:如何加入 Fescar 社区,进行贡献,已经摩拳擦掌了。A13:我们非常欢迎大家通过各种形式参与到我们项目的建设中,包括但不限于:架构设计模块设计代码实现Bug FixDemo样例文档、网站和翻译具体的参与方法可以参见我们项目中的CONTRIBUTING 指引,或与 @eternaltingting@163.com 联系。实际上,我们并不拘泥于贡献的形式,开发者提出的每一个 issue,无论是Bug Report、改进建议或者甚至是问题咨询都代表着对项目的关注和帮助。希望 Fescar 项目和社区一起健康成长,成为分布式事务领域一个优秀的解决方案。本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 22, 2019 · 1 min · jiezi

阿里高级技术专家:研发效能的追求永无止境

背景大约在5年前,也就是2013年我刚加入阿里的时候,那个时候 DevOps 的风刚吹起来没多久,有家公司宣称能够一天发布几十上百次,这意味着相比传统软件公司几周一次的发布来说,他们响应商业需求的能力可以甩后者几条街,而且这差距根本不是加班能赶上的。今天的 AliExpress 技术团队小几百人的规模,可一天发布几十次也已经司空见惯了,这主要得益于三个方面:非常彻底地微服务化,拆分粒度很细,且旗帜鲜明地反对重二方库。阿里集团整体的运维标准化,尤其是 Docker 技术的全面覆盖。AliExpress SRE 团队不断努力保证稳定性。然而,效能这个东西,你永远不会说:“够了,够快了”,尤其是在当下的消费型社会,人人都是消费者,而消费者恨不得脑子里的欲望刚闪现出来,你的商品或服务瞬间就到他面前。况且,随着我们不断国际化的步伐,新的因素必然会影响原来的高效能。沟通带宽衰减问题第一个因素是研发团队自身的发展和变化,今天的 AliExpress 技术团队已经是一个名副其实的分布式国际化团队,工作地是杭州+深圳+莫斯科+马德里+其他欧亚都市,外籍同学的比例是 15%,而且能看到这个比例会不断提高,新的国外工作地点也会增加。而这样的团队,对比在同一层楼里的一群中国人组成的团队,是有本质的区别的。我们可以将人与人之间的沟通和网络通信做类比,我们知道网络通信是有带宽的,从早期的拨号上网几十K,到现在的家庭宽带主流的几十上百M,再到数据中心内部局域网内部G级别的数量级,带宽越大,能传输的信息也就越多(通常浪费也就越多)。而人与人之间沟通也可以认为是有带宽的,例如充分信任的全由中国工程师组成小团队,平时相互一起吃饭散步聊天,大家彼此都特别了解,沟通起来就特别顺畅,想到一个点子转个朝向说两句对方就懂了。可对于一个分布式国际化团队来说,这个沟通带宽可是衰减得厉害:中文到英文的转换,衰减一次。对于大多数人来说,英语不是母语,沟通的效率自然会降低。单地到多地,衰减一次。电话,视频,钉钉,都没有面对面沟通来的高效。(否则大家都不会不约而同地刷脸了)时差,再衰减一次。杭州和莫斯科的时差是5个小时,所以基本上北京时间上午我们是联系不上莫斯科的同学的。文化的差异,再衰减一次。例如很多我们可以用来增强感情的团建方法,撸串K歌王者吃鸡,外籍同学可能完全不感冒。那有人可能会说,既然沟通成本这么高,那直接在一个地方全部招中国工程师多简单?这么做简单是简单的了,可都这么搞的话,怎么在全球范围吸引优秀的人才呢?更何况 AliExpress 的用户基本都是老外,这后面的人才如果全是中国人,听起来这生意就不太靠谱对不?谷歌微软亚马逊,哪家不是在全世界搜罗顶尖人才?所以说,既然沟通带宽的衰减是难以避免的,那我们唯有把对这带宽的利用率提上去。具体我们已经做了,或者在做一些事情:尽可能和行业主流技术接轨,降低工程师学习成本。我们基于开源 Spring Boot 做的阿里巴巴生态集成,摒弃 antx, webx, pandora,都是这个思路。English First:注释,文档,工具,英文必选,中文可选。服务发现,让所有微服务可见,增强自描述,可搜索。拥抱 Kotlin关于开发效率,我个人认为所有 Java 程序员都应该认认真真、仔仔细细去看下 Kotlin,因为这门语言太简洁了,而且和 Java 可以无缝互操作,完全具备生产环境使用的条件。有关简洁,我这两天把一块 Java 代码改成了 Koltin,在丝毫不降低可读性的情况下(实际上可读性是提高了),代码行妥妥地减少了 1/3 。此外我忍不住分享一下最近我基于 Sergey 的 Kotlin HSF DSL 写的一个将函数发布成 HSF 服务的功能:只需要不到 15 行代码,就可以启动一个 Spring Boot 应用,把一个字符串小写的功能发布成 HSF 服务,大家可以对比下 Java 需要写多少东西。语言层面的升级,给框架,中间件,API设计带来更多的可能性,这就能使我们砍掉更多的所谓脚手架代码,让业务代码更精简,更优雅,进而带来效率提升。作为程序员,如果只掌握一种语言,是非常危险的,因为这种语言的各种设计会禁锢你的思维。我自己会在业余看一些其他语言,不过在日常工作中基本也只能写 Java(如果 shell 也算一种语言的话,还是写过些 shell 的)。不过从现在开始,我会开始尽可能地用 Kotlin 写代码,我的团队也全面把日常编程语言从 Java 切换到 Kotlin,其实我们都已经不算 Early Adoptor 啦,雷卷在一年多前就已经不停在鼓吹 Koltin 并上线了一个应用,AliExpress 俄罗斯办公室的 Sergey 等同学也已经在生产用上了 Kotlin,Sergey 个人也在很多地方分享他的经验。我们会推动 AliExpress 拥抱 Koltin,从语言层面来提升我们的效率。阿里资深技术专家雷卷,在他最近的一篇谈程序员学习的文章中写了很多东西,我都是很认同的,其中一段话尤其想点赞:不要和程序员谈自己的编程历史,很多经验今天已经不适用啦,可能有一些,但是会给别人带来甄别成本,别人也懒得来甄别。2-3年不关注技术,基本快和程序员和编程绝缘啦,不是绝对,但是通常不会错。持续学习,与诸君共勉。FaaSFunction as a Service,又一个新的 Buzz Word?是的,不过我还真的相信这个 Buzz Word,行业里 AWS Lambda, Google Cloud Functions, Microsoft Azure Functions 等服务相继推出,大家都在尝试把自己的业务往上面搬,这其中的道理在哪?如果作为云服务提供商,这个道理是很显而易见。你的对手按照 docker instance 收费,2 core 4g 起,一小时多少钱;如果你能做到按调用次数收费,一小时内运行了 30 次。那这个价格差必然是数量级的,用这一招就可以秒杀对手了。上面所说的纯粹是硬件成本的考量,但我们还需要从效率方面看这个事情。首先由于 Function 天生是无状态的,而且是足够轻量的,那么理论上做到 ms 级别的 auto scaling 是没有问题的,例如 graalvm 就在这方面很有潜力。ms 级别的 auto scaling 不仅能够大幅提升资源利用率,更是提升了运维效率,开发几乎就不再需要考虑容量的事情的。例如在双11的时候,我们做大量的压测,很大程度上是为了保证系统各个部分的水位在预测的安全的线上,如果做到了实时扩缩,那么当流量高峰来的时候再扩容好了。什么是轻量?今天很多工程师可能已经忘了轻量的概念是什么,大家就是各种侵入,写个简单的应用,打出来的 jar 包,业务代码的占比往往不到 1/10。先不说这里可能无谓浪费了多少内存,无谓增加了多少启动时间。这个 client 那个 share 满天飞带来的最麻烦的后果就是,开发经常要做各种升级,而且一升就挂,一查就半天。打着所谓性能旗号的各种重客户端,就是反服务化的;各种缺乏细心设计的 API 导致的不兼容升级(而且是暴力推动,不升级卡发布),就是反工程师操守的。微服务化做得好的,应该积累一大批轻量的接口,使用这些接口甚至都不需要引入什么 share/open/client 的依赖,直接用 HSF 的泛化调用即可,这样的接口才不对用户有代码侵入。我们已经在 AliExpress 尝试(并已经上线)基于 Koltin DSL 和 HSF 泛化调用编写 Function,用户只需要依赖很简单的一个 FaaS SDK 就可以编写业务代码,基于前面提到的阿基米德服务发现,他可以快速重用现有服务,做一些聚合和过滤的操作,满足业务需求,这个在贴近无线的业务中非常有用。当然,这个尝试只是一个开始,但我们已经看到,其实有大量的业务逻辑(在 AliExpress 可能是 5/1 至 1/3)其实自身不依赖于数据,可以做成 Function,而且我们可以做到让这些业务不依赖任何业务二方库,甚至借助 Service Mesh 等技术,不依赖于任何中间件 client。这些业务的 owner 不需要关心各种乱七八糟的升级问题,不需要关心容量问题,真正地只关心自己的业务逻辑。我认为这是 FaaS 该成为的样子,而我及我的团队,正不断努力去实现之。作者介绍许晓斌,阿里高级技术专家,《Maven实战》作者,《Maven权威指南》译者,并合译有《Cucumber:行为驱动开发指南》,曾经负责维护 Maven 中央仓库,参与开发 Maven 仓库管理软件 Sonatype Nexus。曾多次在 ScrumGathering 和 AgileTour 等大会上发表演讲。工作之余喜欢读读人文、跑跑步。本文作者:云效鼓励师阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 18, 2019 · 1 min · jiezi

用友微服务事务一致性实践

导读:本文就微服务事务一致性问题产生根源、业界常用方案优缺点进行了分析对比,在此基础上提出了用友微服务事务一致性解决方案,详细介绍了用友CC事务模型及原理,以及此方案解决的场景。一致性问题的产生在传统巨石应用架构模式下,架构特点主要是mvc模式,由controller层负责对外提供服务接口,所有功能集中在一个服务实例中,通过增减服务实例来扩展集群的处理能力,但数据持久化集中在一个数据库存储,数据一致性主要依靠传统数据库本地事务机制保证,这种架构模式特点是简单、快捷,方便业务规模不大,业务功能单一的场景,随着业务增长,无论是业务规模还是业务范围都在快速变化,这种巨石架构模式就显得力不从心,不易于开发协调,因此,微服务架构模式应运而生,所谓微服务通俗来说就是对服务进行垂直拆分,将一个整体服务拆分成功能相对独立的单元服务,各单元服务之间通过rpc进行同步或异步调用。微服务架构模式下各个服务单元各自有独立的数据持久层,一个业务请求需要多个微服务单元共同协作,要求各服务单元要么同时成功或同时失败,但微服务实例分别部署在不同的进程或主机节点上,每个服务实例的状态、网络等情况是不可预知的,因此,如何保证一个业务请求中各单元服务数据保持一致性成为微服务架构中一个关键的问题。常见解决方案两阶段提交两阶段提交属于刚性事务,两阶段分为准备阶段和提交阶段,在准备阶段,由事务协调器向各个参与者发送Prepare消息,参与者收到消息后,要么返回失败,要么执行本地事务,并写本地redo和undo日志,但是并不commit事务,此时,本地事务资源是被锁定状态,其它服务或应用是不能使用此资源的。在提交阶段,事务协调者在接收到所有参与者事务消息通知之后,根据所有参与者提交阶段返回的状态确定在提交阶段是回滚还是提交事务,只要有一个参与者超时或者失败,协调者就向所有参与者发送回滚请求,否则就向参与者发送提交请求。二阶段提交的优点1)实现了事务的隔离,确保了强一致性,即本地事务未提交的数据对其它事务不可见,事务要么都提交成功要么都失败2)业务编程简单,由于事务管理是由事务协调者及本地事务资源管理器实现,开发者必须要介入太多事务相关的工作二阶段提交缺点1)同步阻塞调用,在事务执行过程中,所有参与者同步锁定资源以实现隔离,被锁定的资源不能被其他事务访问2)需要本地事务支持,即本地数据库需要支持xa协议3)需要事务协调者,协调者存在单点问题4)事务会出现无法确认的状态。当协调者发出commit请求后,然后协调者宕机,而参与者可能只有一个已提交,其它参与者尚未提交,此时如果唯一的参与者也宕机,整个事务状态将无法确认5)主要解决的单JVM跨库的事务一致性TCC事务TCC事务即Try-Confirm-cancel三个阶段,是柔性事务的一种,实现的是最终一致性,适合于同步调用过程。TCC是应用层的两阶段提交,不需要事务本地数据库对XA协议的支持。TCC事务模型有三个部分组成·主业务服务主业务服务为整个业务活动的发起方,通常是服务聚合应用,比如商城系统的下单系统,下单时需要调用库存系统减库存,支付系统付款及积分系统给用户积分以及购物车系统清理购物车内容。·从业务服务从业务服务负责提供TCC业务操作,是整个业务活动的操作方。从业务服务必须实现Try、Confirm和Cancel三个接口,供主业务服务调用。由于Confirm和Cancel操作可能被重复调用,故要求Confirm和Cancel两个接口必须是幂等的。·业务活动管理器业务活动管理器管理控制整个业务活动,包括记录维护TCC全局事务的事务状态和每个从业务服务的子事务状态,并在业务活动提交时确认所有的TCC型操作的confirm操作,在业务活动取消时调用所有TCC型操作的cancel操作。1)Try:尝试执行业务完成所有业务检查(一致性)预留必须业务资源(准隔离性)2)Confirm:确认执行业务真正执行业务不做任何业务检查只使用Try阶段预留的业务资源只要Try阶段执行成功,需要确保Confirm一定成功,可以不断重试3)Cancel:取消执行业务释放Try阶段预留的业务资源只要try阶段失败,必须确保Cancel最终一定成功TCC模式优点1)解决了跨应用的事务问题2)把数据库层面的两阶段提交提到应用层来实现,不需要数据库层面来支持XA协议,规避了数据库的XA支持的缺陷TCC模式缺点1)需要从业务的角度来设计业务接口,确保业务可分解成Try、Confirm、Cancel三个阶段,增加了业务编程的复杂性2)由于每个应用的网络不一定可靠,可能会多次调用业务接口,需要业务层面考虑幂等性操作3)由于三个阶段都是同步调用过程,因此随着参与者增多,对主业务响应速度有影响基于消息队列的最终一致性基于消息队列的最终一致性考虑的场景是业务之间通过异步调用来实现,即作为服务调用方发起方异步调用之后立即返回,不必等待被调用服务实际返回结果,这样就可以基于消息队列来实现业务之间的解耦,由各业务来确保最终一致性。基于消息队列的最终一致性方案的优点1)各业务之间完全解耦,单个业务性能不会影响整体服务2)有助于提升服务的整体性能和吞吐量3)实现起来简单,只需要参与事务的各方在收到消息后确保本地事务一致性、幂等性基于消息队列的最终一致性方案的缺点1)需要业务调用方来确保本地事务和发送消息的原子性,虽然像ActiveMq支持事务消息,但是事务消息对性能影响较大,可以在本地建立消息表的方式来确保本地事务与发送消息同时成功或失败2)当出现不一致时,需要人工介入处理各个业务的执行状态用友微服务事务一致性解决方案用友微服务治理中的事务一致性解决方案综合了TCC与基于消息队列的最终一致性,CC事务模型,即Confirm 和Cancel模型。该模型将分布式事务边界划以异步调用为边界,只要在调用链中加入事务的同步调用,都属于一个全局事务,在这个全局事务中,保证事务的最终一致性,如图:在此图中一个完整的调用链从A服务开始,在左边方框内是rpc同步调用,而右边也是一个rpc同步调用,两个方框之间的服务C是通过异步调用框架EOS基于可靠消息队列对服务E发起调用,CC事务模型将此次调用当做两个事务处理。CC事务模型事务状态变化时序图,rpc调用链关系为A->B,B->C,B->D,C->E,时序图如下:CC事务模型过程,A同步调用B服务,事务框架在A服务内部数据库记录对B的调用上下文及事务记录,事务状态为Confirming状态,同时,rpc框架将事务上下文传递给B,B服务接收到rpc调用请求,B服务记录事务,同时事务为Confirming状态,同理,B调用C,C调用E,B调用D.此时,如果B调用D异常,则B本地事务回滚,同时B服务捕捉到异常后根据B服务记录的调用关系上下文,通过EOS框架向C和D发起异步补偿方法调用,所有方法补偿方法调用成功,则B事务状态为Cancelled,C服务补偿调用成功后继续向E服务发起异步补偿调用。同时,B向A抛出异常,A捕捉异常后执行补偿异步调用,同时本地事务回滚,最终AB事务状态为Cancelled或者Confirming状态,C、D、E已提交事务执行补偿方法后状态为Cancelled.最终,所有的事务状态都会confirmed时,则事务成功,或者所有状态都为Cancelled时,回退成功,如果有节点处于Confirming状态,说明整个事务发生了不一致状态,需要人工介入处理。CC事务模型优点1)没有事务管理器的概念,每个事务节点都是对等的2)模型简单,代码侵入少,开发者只需要在业务接口上方法上使用@CCTransaction(cancel=‘异常时补偿事务方法’)标识此方法纳入事务管理,同时,补偿方法上加入@CCTransCancel3)异步消息补偿机制。事务补偿机制通过EOS可靠消息投递,减少事务补偿回调对业务系统性能的影响CC事务模型缺点1)该事务模型与自研rpc框架iris绑定,不支持其它rpc框架2)没有Try阶段锁定资源,一进入事务本地事务就已实际提交,不具备事务隔离能力,业务需要考虑如何实现Cancel才能符合业务实际回滚需求。

January 15, 2019 · 1 min · jiezi

腾讯 Tars-Go 服务 Hello World——从 HTTP 开始

引言本人上一篇文章《腾讯 Tars 基础框架手动搭建》简单介绍了 Tars 框架及其搭建方法。在我们的实际应用中,目前基于 Taf / Tars,主要采用 Node.js 和 C++ 进行开发。对于 C++ 程序员来说,目前最热门的后台开发语言莫过于 Google 的 Go。Tars 框架最新的版本已经把内部的 Taf-Go 开源为 Tars-Go。作为与时俱进的程序员,当然要尝鲜啦。本文中的代码均可以在 我的 GitHub repo 中查阅。本系列文章:腾讯 Tars 基础框架手动搭建——填掉官方 Guide 的坑腾讯 Tars-Go 服务 Hello World——从 HTTP 开始腾讯 Tars-Go 服务 Hello World——RPC 通信环境准备Go 环境开发环境显然要安装好 Go 了。请注意的是,TarsGo 要求 Go 版本 1.9 以上。最新稳定版已经是 1.11 了。安装最新版即可。Go 安装好之后,请注意配置好 $GOPATH 和 $GOROOT 环境变量,建议配置为 $HOME/go 目录。尽管在 Go 1.8 之后,go 命令的运行已经不再需要程序员配置上述变量(go 会自动配置,可执行 $ go env 查看),但是 TarsGo 的脚本在执行的时候还是需要依赖。TarsGo 包执行 go 安装命令并编译:$ go get github.com/TarsCloud/TarsGo/tars$ cd $GOPATH/src/github.com/TarsCloud/TarsGo/tars/tools/tars2go && go build .$ sudo cp tars2go $GOPATH/bin上述命令会把 TarsGo 下载下来,并且将比较重要的一个命令 tars2go 安装好。代码设计TarsGo 的官方 Quick Start 文档 的第一个例子,就是使用 tars 协议进行 server-client 的通信。不过我个人觉得,要说后台服务程序的 hello world 的话,第一个应该是 http 服务嘛,毕竟程序一运行就可以看到效果,这才是 hello world 嘛。给服务命名Tars 实例的名称,有三个层级,分别是 App(应用)、Server(服务)、Servant(服务者,有时也称 Object)三级。在前文我们已经初步接触到了:比如 Tars 基础框架中的 tarsstat,其服务的完整名称即为:tars.tarsstat.StatObj。Tars 实例的名称其中一个非常重要的作用就是用于服务间名字服务寻址。而对于 HTTP 这样的直接对外提供服务的实例而言,其实这块相对不是很重要,我们更多的是以描述服务功能的角度去命名。这里我把我的 HTTP 服务命名为 amc.GoWebServer.GoWebObj创建基础框架和 TarsCpp 一样,TarsGo 也提供了一个 create_tars_server.sh 脚本用于生成 tars 服务,但却没有提供 create_http_server.sh 生成 HTTP 服务。所以这里我们就直接用它就行了:$ cd $GOPATH/src/github.com/TarsCloud/TarsGo/tars/tools$ chmod +x create_tars_server.sh$ ./create_tars_server.sh amc GoWebServer GoWeb执行后我们可以查看生成的文件,清除不需要的:$ cd $GOPATH/src/amc/GoWebServer$ rm -rf GoWeb.tars client debugtool$ chmod +x start.sh$ ls -ltotal 44-rw-rw-r– 1 centos centos 303 Jan 5 22:09 GoWebImp.go-rw-rw-r– 1 centos centos 964 Jan 5 22:09 GoWebServer.conf-rw-rw-r– 1 centos centos 422 Jan 5 22:09 GoWebServer.go-rw-rw-r– 1 centos centos 252 Jan 5 22:09 makefile-rw-rw-r– 1 centos centos 59 Jan 5 22:09 start.shdrwxrwxr-x 2 centos centos 4096 Jan 5 22:09 vendor其实留下的,各文件里的内容,实际上我们都要完全替换掉的……首先是修改 makefile,自动生成的 makefile 内容是这样的:$ cat makefile APP := amcTARGET := GoWebServerMFLAGS :=DFLAGS :=CONFIG := clientSTRIP_FLAG:= NJ2GO_FLAG:= libpath=${subst :, ,$(GOPATH)}$(foreach path,$(libpath),$(eval -include $(path)/src/github.com/TarsCloud/TarsGo/tars/makefile.tars))我们把 “CONFIG := client” 行去掉就行了。代码修改GoWebServer.go接着是修改代码了。首先是 GoWebServer.go,这里参照官方 Guide 的写法就好了,TarsGo 的 HTTP 实现用的是 Go 原生的组件。我稍微调整了一下,把回调函数放在 GoWebImp.go 中(“imp” 是 implementation,我以前一直以为是小恶魔的意思……),将 GoWebServer.go 简化为:package mainimport ( “github.com/TarsCloud/TarsGo/tars”)func main() { mux := &tars.TarsHttpMux{} mux.HandleFunc("/", HttpRootHandler) cfg := tars.GetServerConfig() tars.AddHttpServant(mux, cfg.App+"."+cfg.Server+".GoWebObj") //Register http server tars.Run()}代码还是比较简单的,无需多言。GoWebImp.goGoWebServer.go 中的 HTTPRootHandler 回调函数定义在业务的主要实现逻辑 GoWebImp.go 文件中:package mainimport ( “fmt” “time” “net/http”)func HttpRootHandler(w http.ResponseWriter, r *http.Request) { time_fmt := “2006-01-02 15:04:05” local_time := time.Now().Local() time_str = local_time.Format(time_fmt) ret_str = fmt.Sprintf("{"msg":"Hello, Tars-Go!", "time":"%s"}", time_str) w.Header().Set(“Content-Type”, “application/json;charset=utf-8”) w.Write([]byte(ret_str)) return}部署发布编译打包编译打包上面的工程:$ cd $GOPATH/src/amc/GoWebServer$ make && make tar成功后,会在目录下生成目标文件 GoWebServer.tgz,后文部署发布时需要上传这个包。部署发布创建服务在 Tars 管理平台主页中,点击 “运维管理”,界面如下:Tars 管理平台没有专门的 “新增应用” 功能,所有 app、server、object 的新增都在这个界面中配置。输入一个不存在的对象,就相当于新增操作。所以我们新增 “amc.GoWebServer.GoWebObj”,就是在各项中如下填写:应用:amc服务名称:GoWebServer服务类型:tars_go模板:tars.default节点:填写你打算部署的 IP 地址OBJ:GoWebObj端口类型:TCP协议:非TARS端口可以自定义,也可以填好信息后点 “获取端口” 来生成。各项填写完毕后,点 “确定”,然后刷新界面,重新进入 Tars 管理平台主页,可以看到界面左边的列表就多了上面的配置:发布服务点击 “GoWebServer”,显示 “发布管理” 子标签。在 “服务列表” 中选中需要发布的节点,然后点击 “发布选中节点” 按钮:再点击 “上传发布包”,进入如下界面:点击 “发布包” 右边的 “确定” 按钮,在弹出的对话框中选择前面提到的 GoWebServer.tgz 文件。给这个发布包写好描述之后,点击确认,开始上传发布包:发布成功后,回到 “发布管理” 界面,在该界面中,选择刚才发布的包,然后点击发布,一切正常情况下,即可发布成功。服务验证假设前面获取到的 servant 端口为 10008,那么可以在机器上执行 curl 命令(比如我的机器 IP 是 10.0.4.11):$ curl 10.0.4.11:10008{“msg”:“Hello, Tars-Go!”,“unix”:1546747070,“time”:“2019-01-06 11:57:50”,“client”:":-1"}这就验证 OK 啦,同时也说明了 Tars 管理平台的配置值配置正确了。错误示范此外,本人开始的时候用的是 localhost 地址,但是却错误了:$ curl 127.0.0.1:10008curl: (52) Empty reply from server这里让我误以为服务没有发布成功,折腾了好久。究其原因,是因为在 Tars 中对 servant 自动生成的配置是这样的(以我的为例,在 “服务管理” 中点击 ”管理Servant“):留意在 “绑定地址” 中,线程监听的 IP 地址是 10.0.4.11,所以 localhost 自然就访问不到了。这里不建议修改,如果要修改的话,还需要修改 “服务配置”。这歌内容相对比较深入,本文就不详述了。本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。原文发布于:https://cloud.tencent.com/developer/article/1381300。 ...

January 12, 2019 · 2 min · jiezi

微服务入门【系列视频课程】

本文首发于本博客 猫叔的博客,转载请申明出处公众号:Java猫说现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不定期干货。视频教程地址第一章 从传统单体架构走向微服务第二章 传统单体电商架构第三章 SpringCloud入门第四章 Eureka实操与微服务架构搭建第五章 服务拆分和应用间通信第六章 微服务的不解和深入探讨GitHub源码:mic-demo第一章 从传统单体架构走向微服务Hello,大家好,我是猫叔MySelf,本课程将带领大家入门微服务。各位年轻又帅气的靓仔们!新入职公司,接手公司项目,你所看到的是不是就是一座大山你们接触的项目是不是庞大的代码块、并关系错综复杂(一大堆的目录与包)是不是接手后交付周期也很长(入门也是几个通宵)有没有觉得该项目的扩展能力与弹性受限同时,对于大家这样热爱新技术的同学,有时一用上新技术与工具框架就各种BUG而且一个微不足道的小问题,可以导致整个应用挂掉(高层还总是唠叨我们)也是辛苦大家那段时间每夜每夜的加班工作了!在听微服务之前,因为学员层次不一,希望大家有了解到至少一个单体架构的web项目开发经验或大致流程,这样学起来更轻松哦!聪明的老外总是能先于我们发现新的高效的开发模式,近几年前一个老头就提出了我们将要学习的“微服务”:微服务架构风格是一种将单个应用程序作为一套小型服务开发的方法,每种应用程序都在自己的进程中运行,并与轻量级机制(通常是HTTP资源API)进行通信。 这些服务是围绕业务功能构建的,可以通过全自动部署机制独立部署。 这些服务的集中管理最少,可以用不同的编程语言编写,并使用不同的数据存储技术。大叔的图片这个看起来有点复杂,我就不念了,像教科书一样的文案,有兴趣的同学可以上网深入了解。我们整理一下,并优先入门一些重点。其目的是有效的拆分应用,实现敏捷开发和部署只做一件事,并把它做好对于我们这种要求简单的,工作的时候一般都只想做一件事就好了,不要让我顾及太多。单一(隔离)、独立指责我们可以尽情的在自己负责的项目上“玩耍”啦!对于其他服务层的对接仅需要按照各个应用通信接口文档去走即可!通信(同异步)我们总是要和人交流的,对于我们自己独自负责的服务也是需要去交朋友的,因此它需要与其他各个服务进行通信,这里的通信可能是同步的、异步的。对于每个引用都有他们自己的数据,微服务的采纳有助于我们可以针对部分火爆业务采用不同的数据库类型或者分库读取,而不再需要在同一项目整合多个数据库操作。数据独立我们可以发挥不同语言的优势,比如python、nodejs、php….这对技术专项不同的开发团队来说,配合起来将更加容易与得心应手。技术栈灵活(数据流、存储、业务)独立部署、团队组织架构有效调整第二章 单体架构电商Demo讲解一个普通的电商项目:用户服务:注册商品服务:查询商品订单服务:下单、查看订单数据库表:用户表:用户id、用户名、用户密码、创建时间商品表:商品id、商品名、商品详情、商品价格、库存表:商品id、库存数订单表:订单id、用户名、商品id、订单价格、商品总数、创建时间大致的模拟环境:用户下单与查询订单列表,同时还具备管理人员查询库存接口列表:地址: http://localhost:8080/sells/order/order POST参数id 》 用户id goodsId 》 商品id num 》 商品数量例子{ “code”: 200, “msg”: “成功”, “data”: “MS04780334”}地址:localhost:8762/order/order?id=1 GET参数id 》 用户id例子{ “code”: 200, “msg”: “成功”, “data”: [ { “orderId”: “MS04475904”, “goodsId”: “MS000001”, “name”: “猫叔”, “orderPrice”: 1598, “orderNum”: 2, “createTime”: “2018-12-13T05:59:24.000+0000” }, { “orderId”: “MS04663799”, “goodsId”: “MS000002”, “name”: “猫叔”, “orderPrice”: 2999, “orderNum”: 1, “createTime”: “2018-12-12T16:04:18.000+0000” }, { “orderId”: “MS04780334”, “goodsId”: “MS000001”, “name”: “猫叔”, “orderPrice”: 1598, “orderNum”: 2, “createTime”: “2018-12-13T08:10:29.000+0000” } ]}地址: localhost:8763/goods/goods?id=1&goodsId=MS000002 GET参数id 》 管理员idgoodsId 》 商品id例子{ “code”: 200, “msg”: “成功”, “data”: { “inventoryId”: “IN4567825”, “goodsId”: “MS000002”, “inventoryNum”: 13 }}微服务架构拆分当前只有三个服务,一个用户服务、一个订单服务、一个库存服务假设我们的生意狂飙上涨,投放了分销环节、线上广告啥的,这个时候的订单量非常高。那么我们就可以使用微服务的思想,讲订单服务抽离出来。那么我们将使用SpringCloud来完成这一操作与编码。在基于单体架构的情况下,我们将进行手把手的演进,希望同学们可以一起来撸一把。首先是Eureka注册中心,我们需要向某人说明这里是什么,并将单体服务拆分为两个,order-client服务 还有 其余的服务。那么我们就再新建两个对应的Eureka Client的服务并注册到注册中心同时两个服务之间的通讯也需要采用SpringCloud的操作。第三章 SpringCloud入门说到SpringCloud,我们还需要说一下它基于的更厉害的框架,它就是Netflix。Netflix的多个开源组件一起正好可以提供完整的分布式微服务基础架构环境,而SpringCloud就是对Netflix的多个开源组件进一步封装而成的。同时,它利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,比如我们今天将学到的服务发现注册(Eureka)、调用框架(声明式服务客户端Fegin)等等。Spring Cloud将目前各个比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,因为我们仅仅配置一下、写几句代码就可以实现一个想要的简单的微服务。第四章 Eureka实操与微服务架构搭建Spring Cloud Eureka1、Eureka是一个基于REST的服务2、基于Netflix Eureka做了二次封装3、核心组件为:Eureka Server 注册中心(服务端)Eureka Client 服务注册(客户端)第五章 服务拆分与应用间通信Spring Cloud 服务间的一种RestFul调用方式1、Feign声明式REST客户端接口 + 注解(开启、指定服务名)本质依旧是一个HTTP客户端第六章 关于微服务的不解与深入探讨我想极具好奇心的同学们一定不满足这么一点的概况,的确,微服务还有更多的知识点需要大家去掌握与了解。负载均衡安全机制配置中心链路追踪容器搭配说了那么多,微服务的缺点是什么呀!?我总是希望唱反调的同学毒液中的片段,世界掌握在我们手中没错,任何思想都有其适用性与自身环境,微服务也不例外。在介绍了微服务原理后,大家会提出什么问提呢?我做学生的时候就提出了几个小问题。微服务架构的取舍?需要避免为了“微服务”而“微服务”。 对传统企业而言,开始时可以考虑引入部分合适的微服务架构原则对已有系统进行改造或新建微服务应用,逐步探索及积累微服务架构经验,而非全盘实施微服务架构。微服务的不足又是哪些?微服务的复杂度分布式事务(CAP理论,AP系统)服务的划分服务的部署各个服务组件的版本与部署乃至升级?一套完善的开发管理规范,包括开发设计规范、分支管理规范、持续集成规范,再利用Docker容器的天然的特性:“版本控制、可移植性、隔离性”就可以实现组件的版本管理。实质上基于在支持DevOps完整流程的容器云平台,即可实现整个开发过程及交付中的持续集成、快速部署、灰度发布及无缝升级。最后希望大家都能在未来深入了解并使用微服务。 ...

January 10, 2019 · 1 min · jiezi

用友云服务治理平台 助力企业微服务架构落地

本文主要阐述使用微服务架构时,治理框架或者平台需要解决的主要问题,微服务落地实施过程中所遇到的关键问题和对应解决方案。同时,文章也介绍用友云旗下的微服务治理平台的核心功能和技术架构,以及微服务治理平台在用友云一些产品下的实践,下一步的发展计划和趋势。用友云微服务治理平台由来伴随互联网、云计算、大数据等技术的快速发展,越来越多的企业在信息化之后,将企业上云和数字化提上日程。软件架构的微服务方式重构、应用的自动化运维、容器化等需求强烈,催生出了众多的PaaS平台。同时,针对微服务,也涌现除了许多RPC框架和微服务治理平台,各个框架和平台都有各自的优势和自身独特的适应场景。相比于单体应用和SOA架构,微服务的小团队开发运维、复杂度可控制、独立扩缩、可灵活组合等等优势也逐渐凸显,被广大架构师和技术人员引入和推崇。但同时也引出了配置繁杂、事务不可控等诸多问题,如何恰当的解决微服务中暴露出的各种问题,成为各微服务治理平台的重点和难点。软件架构在微服务之前,各个服务通过RestFul接口或者RPC进行互联和调用,进行功能的服务化和解耦,诸多成熟的RPC框架被引入,例如:RPC调用是微服务治理的基础,但单单RPC不能称为微服务,微服务的核心功能还应该包含服务注册、发现,动态和可视化配置,限流熔断,链路追踪、分析,异步调用,数据一致性处理,API网关等等。上文中所介绍的不同厂商的框架和产品,都围绕着以上核心功能,进行了实现和融合。各个产品都有不同的复杂度和局限性,并和自身厂商的其它产品联系密切。用友云主要面向企业级应用,在TOB领域有独特的技术特色和要求,且用友云下的微服务治理需要和自身的DevOps平台、容器云平台及数据平台进行协同和能力聚合。在借鉴和吸收其他产品的优势的同时,用友云微服务治理平台团队针对自身产品需要做了完善和适配,充分的和用友云开发者中心、数据平台、租户中心、用户中心等结合,推出了更适合自身的用友云微服务治理平台,平台具有以下鲜明的特色:用友微服务治理平台从2015年立项以来,经过团队的不断打磨,已经发展了几个版本,推出了较为成熟的多个版本,例如2.3.1-RELEASE、3.0.1-RELEASE,并在3.5后进行了类隔离机制和插件机制的增强,推出3.5.2-RELEASE、5.0.0-RELEASE. 并在资金云、人力云、财务云、协同云等多个产品,中建、中广核、DIWORK等大型项目中得到了验证。平台的主要功能和技术架构(1)功能架构:服务治理平台提供RPC调用框架、异步调用框架、服务注册发现、配置中心、元数据、一致性框架等基础中间件,并预留了插件机制的扩展,方便开发者使用和集成;也从中间件容器层面提供类隔离和组件加载机制,尽量避免和业务应用引用的三方组件版本冲突;提供统一的门户入口,可视化的管理和查看远程服务的接口信息、调用链路日志、统计信息、评价信息,动态的控制具体接口和方法的权限和流量限制;提供限流、链路追踪等组件保证服务的稳定和可用性。同时,在外围还支持和服务网关API Link的对接,支持使用IDE进行微服务的编排和一键发布。(2)技术架构服务治理平的几大核心技术模块包含注册中心,元数据、控制台、配置中心、基础SDK、链路计算、限流熔断、异步调用和一致性适配组件,IUAP和DUBBOX适配组件等,大致可以分为两类:微服务SDK(middleware)和后端支撑服务。微服务SDK:SDK主要可分为启动和加载(helix),基础的RPC调用(iris),配置中心sdk(proteus)、限流(sentinel)、链路(yyeye)、监控(ms-monitor)、异步调用和可靠消息(eos-spring-support)、数据最终一致性(cctrans-springsupport)、IUAP上下文支持(iuap-support)、dubbox适配(dubbox-support)等。各个组件通过核心的插件机制和类加载机制整合在一起,形成整体对外提供服务,具有两大鲜明特性:1:支持SPI方式扩展的插件机制,灵活组合,易于扩展;2:基于ClassLoder的类隔离机制,组件分离,避免冲突;通过服务治理平台的SDK,业务方可以简单快速的集成微服务的能力到业务工程,达到技术架构的微服务化的目的。后端支撑:后端支撑较为核心的包括注册中心、元数据、控制台和链路计算、监控、配置中心、权限管控等。·注册中心源于springcloud体系下的eureka,在其基础上增加了多租户和权限校验机制,和用友云的租户机制和验证机制有机结合;·元数据服务记录了业务服务中暴露出的远程RPC接口和方法,为可视化的管控及数据分析打好基础;·统一控制台提供服务治理平台的UI交互的对接,支持用户可视化的管控接口、权限、链路,查看统计信息和监控信息;·链路计算通过队列接收调用信息,使用数据平台的存储和分析机制统一计算和管理;·监控服务收集各个应用和实例的基础配置、权限限流配置、端口和域名信息、接入和输出列表、调用基本统计等并统一展示;·配置中心统一存储各个应用的各种配置信息,动态管理和下发全局配置、权限配置、限流配置等;EDAS是阿里云平台推出的分布式服务调用和管控平台,其依赖其自身云平台的配置中心、调度中心、基础资源管理、核心容器、监控中心、权限中心等服务,构建整体服务对外提供服务,功能强大但相对复杂,整体技术栈对阿里云体系的其他产品强依赖,不易专属化的实施落地。用友云平台的微服务治理团队也对其架构进行分析和对比,借鉴其优势的同时,结合自身特点,对各个模块进行拆分,并在异步调用、多套环境支持、去容器依赖等方面进行了针对性的适配;同时在支持与开发者中心、用户中心、权限中心等服务结合方面做了扩展,支持轻量化的独立部署,为平台的专属化减轻了负担。关键问题点和解决方案服务治理平台的几大核心功能包含基础的RPC框架、注册中心元数据、配置中心、链路追踪、异步和一致性、限流熔断等;服务治理平台在实现和落地微服务的几个核心功能的过程中,也遇到一些难点,这也是众多厂家和平台共同的难点。针对这些关键点,服务治理平台提出了适合自身场景的多种合理的解决方案并实现,较为关键的几点简单说明如下:(1)类隔离机制和插件机制:JAVA 版的SDK,在和各种业务应用整合的同时,会遇到很多三方组件版本冲突的问题,给业务整合方带来了困扰。服务治理平台自3.5 版本开始对其进行了优化,引入了类隔离机制,推出了冰山(iceberg)思想,内部自身加载其依赖的三方组件,不对外部的业务三方引用造成冲突,大大简化了集成的难度。同时,服务治理平台各个组件使用插件(plugin)机制进行组合,为后续的扩展和能力增强打好基础。(2)动态配置:业务应用的微服务化拆分,使得业务工程的配置文件更加繁多和分离,微服务的权限和流量的实时控制,也需要动态的管理各项配置。所以配置中心的后端服务和前端SDK体现出更重要的作用。服务治理平台的SDK为每个使用的客户端,内置了配置中心的SDK,其使用长轮询的方式,近实时的感知远程配置文件的变化,从而及时的响应变化。云端的操作提供RestFul接口和可视化界面,操作简单实用。(3)异步调用数据最终一致性:异步调用框架提供可靠消息组件,完善了队列的权限认证体系,简化了异步调用的开发方式,业务开发只需要简单配置和注解,即可完成异步操作。同时,异步事务控制台可以在云端可视化的下发命令,提供错误事务的重试机制。服务治理平台的SDK,将eos、cc等适配组件有机结合,一体化对外提供服务:上述几个关键点只是服务治理平台的部分问题的解决方案,还有更多的技术点,本文在这里不做更深层次的阐述。通过云平台和支持和服务治理平台团队的共同努力,我们攻克了许多难题并给出了比较合理的解决方案且落地实现,为云平台及其他产品的微服务化铺平了道路。服务治理平台在用友云的实践和落地微服务治理平台自推出以来,经历了多个版本的迭代和多次升级完善,目前已经相对稳定。线上支持的应用数量已达到900多个,API数量已经接近三万个。目前,使用服务治理平台的云产品和组织包括资金云、财务云、人力云、协同云、用友审计、用友能源等,支持的大型项目包括中建、中广核、DIWORK等。感谢各个平台和产品的支持,也希望微服务治理平台在对各产品和项目的微服务拆分及落地提供更多更有效的服务。下图为线上监控系统分析出的各个产品和模块的调用依赖图,随着各个产品和服务的接入,用友云服务间的调用层级、依赖关系会越来越清晰,我们也能从中提炼出更多的价值。微服务治理发展趋势和展望服务治理平台经过长时间的发展和磨练,已经在分布式服务调用、运维管控和服务治理、生命周期管理和统一控制台、数字化监控和运营、开发支持扩展和兼容等等大方面有沉淀和输出。我们也和其他成熟的产品及框架进行对比,吸收和优化,构建和完善自身的微服务能力体系。随着产品的发展,服务治理平台也总结了自身的几个重要阶段,我们从基础的调用框架走来,加强了权限和安全的管控,加入了服务稳定性保证,这些功能已经能覆盖大部分的业务需求。但同时,我们要把握好技术的发展趋势,站在发展的前沿。服务治理平台下一步的发展规划,包括支持服务搜索和集市、对服务编排和网关更有效的组合、服务网格、服务监控等。各个产品和服务间的调用数据已经收集,如何更好的更充分的利用这些数据,挖掘出有价值的信息,是服务治理平台的一个重要课题,我们可以借鉴京东云的思路,从这些数据中发掘出类似知识搜索、服务评价、调用图谱等,不仅从技术上,也从业务和流程上给出有价值的分析结果。同时,线上应用变得更多,调用关系变的更复杂后,微服务监控的重要性就更加凸显。有效和及时的监控到各个服务和实例的参数、指标,能更有针对性的进行问题问题的排查和解决。下一阶段,微服务监控也是我们需要重点、大力投入的。我们希望构建一个统一的可视化微服务监控体系,可以从中直观的获取到各类监控信息,譬如运行时环境、全局配置、异步调用配置、一致性组件的配置等,链接、端口、域名、跃点等,还有服务接口的调入、调出列表和统计信息,调用出错的链路和堆栈信息等等。有效的服务监控必将在开发和运维的不同阶段体现出更大的作用。能力聚合、生态链、协同发展服务治理平台的发展并非原生和独立的,其成功推出也伴随着其他产品和技术的支撑,云平台的DevOps、容器云的发展和微服务的发展相辅相成,有机组合,数据平台的大数据存储和分析为链路追踪和分析提供了可能。微服务治理平台、DevOps平台、容器云平台合力,成为各个云产品和服务成功上云的三把尖刀,为其底层的技术支撑提供了强有力的保障。相信三把尖刀也会在技术中台中体现出越来越重要的价值。对内有机整合,对外需要扩展和延伸,服务治理平台和API Link、服务编排等在微服务外围合理组合,使得微服务的利用率更高、可组合性更强。但是,我们清楚,服务治理平台的各个技术架构和数据分析机制,依赖于各个业务平台的数据,只有各个业务线的数据不断完善,整体的用友云调用链路不断完整,服务治理才更加能突出治理和协调的作用,服务的分析和评价才更能落地。各个业务的云化和微服务化需要技术中台的有力支撑,技术平台的发展也需要各个业务的有力配合,希望服务治理平台和开发者中心能够构建出越来越稳定和完善的服务,更多的云产品和项目接入进来,构建更为完整的用友云生态。服务治理平台,作为用友云平台下 3+2战略 (技术中台、业务中台、数据中台 + 混合云、生态链)下的技术中台核心产品,也必将展示出更强的战斗力。

January 10, 2019 · 1 min · jiezi

基于 lumen 的微服务架构实践

lumen为速度而生的 Laravel 框架官网的介绍很简洁,而且 lumen 确实也很简单,我在调研了 lumen 相关组件(比如缓存,队列,校验,路由,中间件和最重要的容器)之后认为已经能够满足我目前这个微服务的需求了。任务目标因为业务需求,需要在内网服务B中获取到公网服务A中的数据,但是B服务并不能直接对接公网,于是需要开发一个relay 中转机来完成数据转存和交互。任务列表环境准备 【done】RSA数据加密 【done】guzzle请求封装 【done】添加monolog日志RocketMQ java请求转发程序数据库migrateEvent和Listener的业务应用Scheduler计划任务(基于crontab)Jobs和Queue业务应用使用supervisor守护queue进程和java进程添加sentry来获取服务日志信息和实现邮件报警jwt用户身份校验.env 文件的配置可能的扩展 K8S docker性能并发测试环境准备机器是centos6.8, 使用work用户, 安装 php(^7),mysql,nginx,redisyum 安装的同学可以试试 https://www.softwarecollectio…安装composerhttps://getcomposer.org/downl…# 注意php的环境变量php -r “copy(‘https://getcomposer.org/installer', ‘composer-setup.php’);“php -r “if (hash_file(‘sha384’, ‘composer-setup.php’) === ‘93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8’) { echo ‘Installer verified’; } else { echo ‘Installer corrupt’; unlink(‘composer-setup.php’); } echo PHP_EOL;“php composer-setup.phpphp -r “unlink(‘composer-setup.php’);“mv composer.phar /usr/local/bin/composer安装lumencomposer global require “laravel/lumen-installer"composer create-project –prefer-dist laravel/lumen YOURPROJECT配置 .env配置Lumen 框架所有的配置信息都是存在 .env 文件中。一旦 Lumen 成功安装,你同时也要 配置本地环境。应用程序密钥在你安装完 Lumen 后,首先需要做的事情是设置一个随机字符串到应用程序密钥。通常这个密钥会有 32 字符长。 这个密钥可以被设置在 .env 配置文件中。如果你还没将 .env.example 文件重命名为 .env,那么你现在应该去设置下。如果应用程序密钥没有被设置的话,你的用户 Session 和其它的加密数据都是不安全的!配置nginx 和 php-fpm配置nginx的serverserver { listen 8080; server_name localhost; index index.php index.html index.htm; root /home/work/YOURPROJECT/public; error_page 404 /404.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ .php$ { root /home/work/YOURPROJECT/public; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; #include fastcgi.conf; }}php-fpm的监听端口推荐一篇文章:Nginx+Php-fpm运行原理详解lumen 基础介绍lumen的入口文件是 public/index.php,在nginx配置文件中已有体现初始化核心容器是 bootstrap/app.php 它做了几件非常重要的事情加载了 composer的 autoload 自动加载创建容器并可以选择开启 Facades 和 Eloquent (建议都开启,非常方便)Register Container Bindings:注册容器绑定 ExceptionHandler(后面monolog和sentry日志收集用到了) 和 ConsoleKernel(执行计划任务)Register Middleware:注册中间件,例如auth验证: $app->routeMiddleware([‘auth’ => AppHttpMiddlewareAuthenticate::class,]);注册Service Providers$app->register(App\Providers\AppServiceProvider::class);$app->register(App\Providers\AuthServiceProvider::class);$app->register(App\Providers\EventServiceProvider::class);在AppServiceProvider 里还能一起注册多个provider// JWT$this->app->register(\Tymon\JWTAuth\Providers\LumenServiceProvider::class);// redis$this->app->register(\Illuminate\Redis\RedisServiceProvider::class);// 方便IDE追踪代码的Helper,因为laravel使用了大量的魔术方法和call方法以至于,对IDE的支持并不友好,强烈推荐开发环境安装$this->app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);// sentry$this->app->register(\Sentry\SentryLaravel\SentryLumenServiceProvider::class);加载route文件 routes/web.php//localhost:8080/test 调用app/Http/Controllers/Controller.php的 test方法$router->get("/test”, [‘uses’ => “Controller@test”]);// 使用中间件进行用户校验$router->group([‘middleware’ => ‘auth:api’], function () use ($router) { $router->get(’/auth/show’, ‘AuthController@getUser’);});还可以添加其他初始化控制的handler,比如说这个 monolog日志等级和格式,以及集成sentry的config$app->configureMonologUsing(function(Monolog\Logger $monoLog) use ($app){ // 设置processor的extra日志信息等级为WARNING以上,并且不展示Facade类的相关信息 $monoLog->pushProcessor(new \Monolog\Processor\IntrospectionProcessor(Monolog\Logger::WARNING, [‘Facade’])); // monolog 日志发送到sentry $client = new Raven_Client(env(‘SENTRY_LARAVEL_DSN’)); $handler = new Monolog\Handler\RavenHandler($client); $handler->setFormatter(new Monolog\Formatter\LineFormatter(null, null, true, true)); $monoLog->pushHandler($handler); // 设置monolog 的日志处理handler return $monoLog->pushHandler( (new Monolog\Handler\RotatingFileHandler( env(‘APP_LOG_PATH’) ?: storage_path(’logs/lumen.log’), 90, env(‘APP_LOG_LEVEL’) ?: Monolog\Logger::DEBUG) )->setFormatter(new \Monolog\Formatter\LineFormatter(null, null, true, true)) );});配置文件 config/ 和 .env 文件其他目录文件用到时再具体说明RSA数据加密因为业务中包含部分敏感数据,所以,数据在传输过程中需要加密传输。选用了RSA非对称加密。借鉴了 PHP 使用非对称加密算法(RSA)但由于传输数据量较大,加密时会报错,所以采用了分段加密连接和分段解密php使用openssl进行Rsa长数据加密(117)解密(128)如果选择密钥是1024bit长的(openssl genrsa -out rsa_private_key.pem 1024),那么支持加密的明文长度字节最多只能是1024/8=128byte;如果加密的padding填充方式选择的是OPENSSL_PKCS1_PADDING(这个要占用11个字节),那么明文长度最多只能就是128-11=117字节。如果超出,那么这些openssl加解密函数会返回false。分享一个我的完成版的工具类openssl genrsa -out rsa_private_key.pem 1024//生成原始 RSA私钥文件openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem//将原始 RSA私钥转换为 pkcs8格式openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem<?phpnamespace App\Lib\Oscar;class Rsa{ private static $PRIVATE_KEY = ‘—–BEGIN RSA PRIVATE KEY—–xxxxxxxxxxxxx完整复制过来xxxxxxxxxxxxxxxxxxx—–END RSA PRIVATE KEY—–’; private static $PUBLIC_KEY = ‘—–BEGIN PUBLIC KEY—–xxxxxxxxxxxxx完整复制过来xxxxxxxxxxxxxxxxxxx—–END PUBLIC KEY—–’; /** * 获取私钥 * @return bool|resource / private static function getPrivateKey() { $privateKey = self::$PRIVATE_KEY; return openssl_pkey_get_private($privateKey); } /* * 获取公钥 * @return bool|resource / private static function getPublicKey() { $publicKey = self::$PUBLIC_KEY; return openssl_pkey_get_public($publicKey); } /* * 私钥加密 * @param string $data * @return null|string / public static function privateEncrypt($data = ‘’) { if (!is_string($data)) { return null; } $EncryptStr = ‘’; foreach (str_split($data, 117) as $chunk) { openssl_private_encrypt($chunk, $encryptData, self::getPrivateKey()); $EncryptStr .= $encryptData; } return base64_encode($EncryptStr); } /* * 公钥加密 * @param string $data * @return null|string / public static function publicEncrypt($data = ‘’) { if (!is_string($data)) { return null; } return openssl_public_encrypt($data,$encrypted,self::getPublicKey()) ? base64_encode($encrypted) : null; } /* * 私钥解密 * @param string $encrypted * @return null / public static function privateDecrypt($encrypted = ‘’) { $DecryptStr = ‘’; foreach (str_split(base64_decode($encrypted), 128) as $chunk) { openssl_private_decrypt($chunk, $decryptData, self::getPrivateKey()); $DecryptStr .= $decryptData; } return $DecryptStr; } /* * 公钥解密 * @param string $encrypted * @return null */ public static function publicDecrypt($encrypted = ‘’) { if (!is_string($encrypted)) { return null; } return (openssl_public_decrypt(base64_decode($encrypted), $decrypted, self::getPublicKey())) ? $decrypted : null; }}使用tip// 私钥加密则公钥解密,反之亦然$data = \GuzzleHttp\json_encode($data);$EncryptData = Rsa::privateEncrypt($data);$data = Rsa::publicDecrypt($EncryptData);guzzle使用安装超简单 composer require guzzlehttp/guzzle:~6.0guzzle 支持PSR-7 http://docs.guzzlephp.org/en/…官网的示例也很简单,发个post自定义参数的例子use GuzzleHttp\Client;$client = new Client();// 发送 post 请求$response = $client->request( ‘POST’, $this->queryUrl, [ ‘form_params’ => [ ‘req’ => $EncryptData ]]);$callback = $response->getBody()->getContents();$callback = json_decode($callback, true);guzzle支持 异步请求// Send an asynchronous request.$request = new \GuzzleHttp\Psr7\Request(‘GET’, ‘http://httpbin.org’);$promise = $client->sendAsync($request)->then(function ($response) { echo ‘I completed! ’ . $response->getBody();});$promise->wait();值的注意的是github上有一个很好玩的项目 https://github.com/kitetail/zttp它在guzzle的基础上做了封装,采用链式调用$response = Zttp::withHeaders([‘Fancy’ => ‘Pants’])->post($url, [ ‘foo’ => ‘bar’, ‘baz’ => ‘qux’,]);$response->json();// => [// ‘whatever’ => ‘was returned’,// ];$response->status();// int$response->isOk();// true / false#如果是guzzle 则需要更多的代码$client = new Client();$response = $client->request(‘POST’, $url, [ ‘headers’ => [ ‘Fancy’ => ‘Pants’, ], ‘form_params’ => [ ‘foo’ => ‘bar’, ‘baz’ => ‘qux’, ]]);json_decode($response->getBody());高可用问题思考数据传输量过大可能导致的问题RSA加密失败请求超时数据库存储并发列队失败重试和堵塞数据操作日志监控和到达率监控未完待续….. ...

January 9, 2019 · 3 min · jiezi

Dubbo作者亲述:那些辉煌、沉寂与重生的故事

摘要: Dubbo 这个名字,最后会变成一个 Apache 的商标,会成为一个在 GitHub 上有 2 万多人关注、一百多人参与贡献的超级项目。梁飞在 2011 年开源 Dubbo 这个项目的时候,完全没有想过,Dubbo 这个名字,最后会变成一个 Apache 的商标,会成为一个在 GitHub 上有 2 万多人关注、一百多人参与贡献的超级项目。在自己退出这个项目多年后,Dubbo 仍在野蛮生长,并焕发新机。从商业公司开源出去的产品会变成什么样?开源是否一定要按照某种既定的方式去生长?还是说开源的世界有足够的包容性、开放性,能够允许各种各样的创作在其中成长?且看本次二叉树——Dubbo 项目的故事。嘉宾简介梁飞(虚极),2009 年加入阿里巴巴,负责中间件的开发,Dubbo 开源分布式服务框架作者,HTTL 开源模板引擎作者,QCon 优秀出品人。 2012 年加入天猫,负责手机天猫 APP 的技术团队,见证了天猫双 11 无线化全过程。热衷参与开源社区建设,传播服务化,SOA,框架设计,移动应用等架构设计理念。Dubbo 项目诞生于 2008 年。梁飞最早进入阿里的时候,Dubbo 项目还没有 Dubbo 这个名字,那时的 Dubbo 还是一个阿里内部的系统。2010 年,Dubbo 项目进行了重构。“2009 年下半年主要在修 bug,到了 2010 年初的时候觉得这个架构实在是不堪重负,觉得改起来太痛苦了,于是就重写了。”从 1.0 进入 2.0,梁飞推动了大量的工作,同时继续在 JavaEye 写着他的博客。“写博客对你有什么影响?”“在社区里面看别人的博客,他们也在写一些开源软件,大家互相看博客,然后就认识了。推荐我来阿里的朋友就是当时圈子里认识的。”2011 年的阿里,憋了一股劲儿要成为一家技术人向往的企业。那个时候,开发者刚刚成为国内各大厂商争相夺取的宝贵资产。靠什么吸引最顶尖的开发者?黑客文化。工程师文化。开源文化。“那时候公司觉得要做一些开源的事情,一个是反哺开源界,同时也希望通过开源来提升公司的影响力。”当时在淘宝、在阿里 B2B,都有团队在推动开源。阿里 B2B 这边决定先拿 Dubbo 项目开源出去。“大概在 2011 年初做了很多剥离的工作,也把文档做了梳理。我们并没有做很强的推广,我们自己在技术群里发了一些文章,就有人开始在用了。”“那个时候的团队多少人?我看到你们有一张六个人团队的照片。”“人员的变化还是挺多的,六个人是顶峰时期,是我们知名度上来之后加入我们的。我们平时开发基本上就是一到两个为主。”“有外面的人来贡献代码吗?”“有很多人给我们贡献代码。还有很多公司请我们来跟他们讲。”“还有公司问说能不能我们付一点钱,这样的话他们觉得出了问题可以找我们。”“但是我们当时没有这种机制。”一年时间很快过去了,Dubbo 的用户越来越多,有知名汽车厂商、证券厂商、水泥厂商、电器厂商、电商厂商。“当时来这么多公司,在你的预期之内吗?”“超出我的预期。”就在这个时候,发生了一件大事:阿里巴巴集团要强化 One Company,开始进行架构调整。技术层面,整个公司大统一,就希望不要重复建设,但凡相同的项目都要合并。当时的淘宝有一个项目叫做 HSF,也是一个中间件服务框架,跟 Dubbo 做的事情高度重合。“一开始说可以让 HSF 合并到 Dubbo 里面来,给了我们三个月时间要把它们整合起来。”HSF 项目的作者林昊(毕玄),也是当时国内 Java 领域的知名技术领袖。在 OSGi 非常流行的时候,毕玄可能是国内能够把 OSGi 解释的最清楚的人之一。HSF 和 Dubbo,虽然做的事情高度重合,但是设计理念不怎么一样,虽然有些碰撞,但最终目的还是为了“强强联合”。“合并的时候,整个淘系都在用 HSF,而阿里金融、集团、B2B 都在用 Dubbo。”“时间没有达到预期,还是没合并起来。但其实我们把两边的协议都兼容好了。”“后来就决定反向合并,把 Dubbo 合并到 HSF 里面去。”“你当时觉得应该合并吗?”“我觉得协议能互通是有好处的,并不是坏事。我觉得他们做的挺好,把两边的设计理念全部整合在一起了。”不久之后,Dubbo 团队调整,去到了各个地方。从外面看来,Dubbo 项目从 2014 年之后就再也没有更新过。倒是当当网开发的扩展版本 Dubbox 后来持续发展,被圈内人评价为“墙内开花墙外香”。“你会不会觉得建立共识是一个特别困难的事情?”“我觉得任何东西必须要有一个主导,但这个东西其实没有对错。一个设计是没有对错的,有些人可能就是不会认同你这个共识,但你总是能找到认同你共识的人。”“我就是认为越简单越好,我的设计原则就是一定要实用。增加的复杂度越小,能带来更大的收益,我觉得就值得。”“那么,你要怎么吸引那些能够认同你的人到你的身边来?在他们还不知道你的时候。”“我会去其他团队认识人,或者在圈子里面认识人,我会跟他去聊我的理念,我会去分享。有人特别认同的话,他就会来。”就在所有人都以为 Dubbo 项目已经没有未来的时候,事情又出现了变化。2017 年 9 月,就在项目已经将近 3 年没动静的时候,Dubbo 连续发布了好几个新版本,并且开始在内部招募对 Dubbo 感兴趣的同事。新版本背后的主力开发团队是阿里巴巴中间件团队,其中一个重要的人名叫北纬,他从 2017 年 7 月开始接手 Dubbo。在一次对外公开的采访中,北纬说到:“我对 Dubbo 的了解主要来自梁飞在 JavaEye 的系列文章,再通过自己阅读源码,以及在内部 RPC 框架对 Dubbo 兼容的工作中学习所得。”梁飞曾经在 2015 年写过一个继续推动 Dubbo 的规划,找了很多人聊过:找过开源委员会,找过内部的朋友,找过外面的朋友,希望能共同把这个事情继续推起来。但是,梁飞已经没有那么多时间可以投入到 Dubbo 上。他当时在做天猫客户端。“不管是谁,靠一腔热血都很容易凉掉。”有的开源项目,通过志愿者们投入各自的业余时间活下去。但我们应该要求所有的开源项目都能做到这一点吗?事实上,用户也不会愿意将自己重要的东西跑在单纯靠志愿者们的业余时间堆砌起来的项目上——尤其是企业用户。Dubbo 是中间件项目,用户一定是企业。企业用户宁愿花钱,有人给他提供服务,而不是搞来一堆免费而没有保障的东西,自己为所有的问题负责。Dubbo 的转机,在于阿里云的流行。2017 年的阿里云,发现有一批客户上云之后,想要用 Dubbo。因为他们 Dubbo 已经用的很熟了,不想因为上云而被迫改变自己的使用习惯。于是,阿里云就把 Dubbo 服务作为自己的一个产品,卖给了这些客户。但是,客户们又提出了一个问题:“你看你们 Dubbo 都不怎么更新代码了是吧?你们自己都不维护了,我们用你的框架就觉得特别不放心。”这下好了,真正的客户提出要求了。提升客户对 Dubbo 的信心,成为了一件在公司层面有价值的事情。“怎样提升客户对 Dubbo 的信心?”“让它进一步升级。”“最好的办法是什么?”“捐给 Apache。”北纬带动着他的团队,将 Dubbo 项目捐给了 Apache。2018 年初,Dubbo 项目正式进入了 Apache 的孵化器。一边是 Apache Dubbo 重启后的第一个里程碑版本 2.7.0 进入社区投票阶段,并将作为社区的毕业版本;另一边,Dubbo 正在从一个微服务领域的高性能 Java RPC 框架,演进到微服务框架 Dubbo Ecosystem,打造出一个完整的微服务生态。而此时,距离去年 Dubbo 重启仅过一年有余。我们去找到北纬,希望他聊聊 Dubbo 的未来。北纬说,还是让梁飞跟我们多讲讲。“你觉得什么是开源的精神?”“开源的精神,就是大家的智慧能共同成长。”“你觉得中国的开源现在有哪些做得好的地方和不足的地方?”“我觉得中国的开源最缺对社区的重视,很多都只是把代码 push 出来,有些甚至连文档都不完善,好像人家爱用不用,出了问题也不是我的事。但这可能是一个初级阶段,慢慢会成熟起来。但我觉得好的地方就是,大家都相信开源的力量。”“您会不会觉得中国企业做开源,功利心特别重,光去看这个东西是不是有用?”“输出技术影响力是吧?我觉得一个开源社区要能够一直运作下去,而且能跟上时代的潮流,其实是要与时俱进的。我觉得做开源,就是期望这个东西一直有生命力,这个作品能够活多久应该作为它的核心目标。”“那您觉得 Dubbo 还能活多久?”“我觉得技术的革新其实挺快的,不革新的话,就有淘汰的危险。但是在这个节点上进行一次革新的话,我觉得它还有很长的生命力。”“那是什么样的革新?”“任何技术一定是没有终点的。没有任何架构能解决现实中所有的问题,而任何一个架构去解决前面的问题的时候,一定会带来副作用,然后就需要下一个架构去治理。这个探索的方向是没有止境的,但只有你到达了一个阶段,你才能够去想下一个阶段的很多事情。”“回到原点,十年前的选择一定是最正确的吗?就算当时是最正确的,现在也不一定正确对吧?因为时代在变化。如果我们今天从零开始,我们有没有更好的选择?有时候我们背了十年的包袱,反而不敢行动了。但我希望我们下一代演化的时候,我们能够提出一些颠覆式的理念,真正革新的解决我们现在面临的问题背后的那些问题,而不是头痛医头脚痛医脚。这是我们期望做的事情。”如常,早上 9 点多,梁飞打开邮箱,关于 Apache Dubbo 重启后的第一个里程碑版本 2.7.0 的讨论邮件还在 mailing list 里热烈进行着;另一边,Dubbo 正在从一个微服务领域的高性能 Java RPC 框架,演进到微服务框架 Dubbo Ecosystem,打造出完整微服务生态。而此时,距离去年 Dubbo 重启仅过一年有余。本文作者:二叉树阅读原文本文来自云栖社区合作伙伴“InfoQ”,如需转载请联系原作者。 ...

January 3, 2019 · 1 min · jiezi

iUAP云运维平台v3.0全面支持基于K8s的微服务架构

什么是微服务架构?微服务(MicroServices)架构是当前互联网业界的一个技术热点,业内各公司也都纷纷开展微服务化体系建设。微服务架构的本质,是用一些功能比较明确、业务比较精练的服务去解决更大、更实际的问题。该架构强调的一些准则:单一职责、协议轻量、进程隔离、数据分离、独立部署、按需伸缩。什么是Kubernetes?Kubernetes是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用,其主要功能:1) 自动化容器的部署和复制,随时扩展或收缩容器规模。2) 以集群的方式运行、管理跨机器的容器。3) 将容器组织成组,并且提供容器间的负载均衡。4) 解决Docker跨机器容器之间的通讯问题。5) Kubernetes的自我修复机制使得容器集群保持健康状态。微服务架构(MSA)跟SOA架构有何不同?微服务架构是伴随敏捷迭代开发而兴起的,更加强调快速敏捷部署和伸缩,适用于功能拆分比较细的场景,粒度也更小、更独立。协议上基于更加轻量化的REST API,供内部各子系统及微服务之间调用。适合业务相对独立、简单的互联网场景。强调服务的独立部署和易伸缩能力。下图是详细的对比:怎么理解服务注册和服务发现?微服务架构下,有大量的微服务需要处理。由于微服务的快速和敏捷研发,他们的位置可能会动态变化。因此在运行时需要能够发现服务所在的位置,服务发现可以解决这个问题。服务注册:注册中心有微服务的实例和位置信息,微服务在启动时向注册中心注册自己的信息,关闭时注销。其它使用者能够通过注册中心找到可用的微服务和相关信息。服务发现:为了能找到可用的服务和他们的位置信息,需要服务发现机制。有两种发现机制,客户端发现和服务端发现。WEB应用中,比较常用的是服务端发现的方式:客户端/API网关把请求发送到已知位置信息的组件(比如负载均衡器)。组件去访问注册中心,找到微服务的路径信息,并跳转到相应的微服务。云运维平台如何基于Kubernetes实施微服务?基于平台的微服务部署变得不同于传统模式:能够独立于其他微服务发布或者取消发布; 微服务可以水平扩展(某一个服务比其他的请求量大);能够实现快速的构建和发布;各微服务之间的功能不相互影响。使用基于Kubernetes的方式部署微服务,用户需要的只是定义服务的状态,而不是部署过程。先来看一下Kubenetes整体框架,如下图所示:主要包括kubecfg、Master API Server、Kubelet、Minion以及Proxy。Master定义了Kubernetes 集群Master/API Server的主要声明,包括Pod Registry、Controller Registry、Service Registry、Endpoint Registry、Minion Registry、Binding Registry、REST Storage以及Client, 是client(Kubecfg)调用Kubernetes API,管理Kubernetes主要构件Pods、Services、Minions、容器的入口。 Minion负责跟踪Kubernetes 集群中有多少台主机。Pod负责跟踪集群中有多少Pod在运行,及跟Minion的映射关系。下面我们一起看下,基于Kubernetes是如何进行服务注册发现的,其详细的架构如下图所示:Kubelet是Kubernetes集群中每个Minion和Master API Server的连接点,Kubelet运行在每个Minion上,是Master API Server和Minion之间的桥梁,接收Master API Server分配给它的commands和work,与持久性键值存储etcd、file、server和http进行交互,读取配置信息。Kubelet的主要工作是管理Pod和容器的生命周期,其包括Docker Client、Root Directory、Pod Workers、Etcd Client、Cadvisor Client以及Health Checker组件。部署完毕后的Kubernetes集群,其各组件和微服务架构所提出的一些准则的对应关系,如下图所示:应用以Docker容器的形态,通过Namespace隔离的运行在定义好的Pod当中,各微服务之间的调用变得如此简单,再也不用为微服务的实施和治理烦恼了。

December 27, 2018 · 1 min · jiezi

被忽略的后台开发神器 — Docker

刚接触Docker的时候,以为只是用来做运维。后来真正用的时候才发觉,这个Docker简直是个神器。不管什么开发场景都能轻松应付。想要什么环境都能随意生成,而且灵活性更高,更轻量,完美实现微服务的概念。什么是DockerDocker是一个开源的应用容器引擎,基于Go语言 并遵从Apache2.0协议开源。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。它占用的资源更少,能做到的事更多。与传统虚拟机的对比特性容器虚拟机启动秒级分钟级 硬盘启动一般为MB一般为GB性能接近原生弱于系统支持量单机支持上千个容器一般几十个安装Docker安装的方法都挺简单的,我用的是mac,直接通过Docker官网下载软件安装,全程无障碍。Docker概念镜像(images):Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。(直白点可以理解为系统安装包)容器(container):镜像和容器的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。(可以理解为安装好的系统)Docker镜像使用一、下载镜像大概了解了Docker的概念以后,我们就尝试拉取flask镜像使用一下。查找镜像可以通过https://hub.docker.com/网站来搜索,或者通过命令搜索。docker search flask在这里,我是通过Docker hub官网挑选出了python3.7 + alpine3.8组合的运行环境,alpine是精简版的linux,体积更小、运行的资源消耗更少。# 拉取镜像docker pull tiangolo/uwsgi-nginx-flask:python3.7-alpine3.8# 下载好可查看镜像列表是否存在docker images二、运行flask镜像下载镜像以后,就开始运行下试试,感受一下Docker的轻量、快捷。首先创建个flask运行文件来,在这里,我创建了/docker/flask作为项目文件,然后在根目录下再创建个app文件夹来存放main.py文件,代码如下:from flask import Flaskapp = Flask(name)@app.route("/")def hello(): return “Hello World from Flask!“if name == “main”: # 测试环境下才开启debug模式 app.run(host=‘0.0.0.0’, debug=True, port=80)现在的文件结构:flask └── app └── main.py运行命令docker run -it –name test -p 8080:80 -v /docker/flask/app:/app -w /app tiangolo/uwsgi-nginx-flask:python3.7-alpine3.8 python main.py这里说明一下命令的参数含义:-it 是将-i -t合并起来,作用是可以用指定终端对容器执行命令交互。–name 对容器进行命名。-p 将主机的8080端口映射到容器的80端口。-v 将主机的/docker/flask/app文件挂载到容器的/app文件,如果容器内没有的话会自动创建。-w 将/app文件作为工作区,后面的执行命令都默认在该文件路径下执行。tiangolo/uwsgi-nginx-flask:python3.7-alpine3.8 镜像名跟标签。python main.py 通过python来运行工作区的main.py文件。运行结果:现在主机跟容器的链接已经建立起来了,主机通过8080端口就能访问到容器的网站。自定义镜像在使用别人定制的镜像时总是不能尽善尽美的,如果在自己项目里面,不能每次都是拉取下来重新配置一下。像上面的镜像,我可不喜欢这么长的名字,想想每次要敲这么长的名字都头疼(tiangolo/uwsgi-nginx-flask:python3.7-alpine3.8)。编写Dockerfile文件打开我们刚才的/docker/flask路径,在根目录下创建Dockerfile文件,内容如下。# 基础镜像FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.8# 没有vim来查看文件很不习惯,利用alpine的包管理安装一个来RUN apk add vim# 顺便用pip安装个redis包,后面用得上RUN pip3 install redis# 将我们的app文件加入到自定义镜像里面去COPY ./app /app现在我们的文件结构是:flask├── app│ └── main.py└── Dockerfile剩下的就跑一遍就OK啦!记得一定要在Dockerfile文件同级目录下执行build命令。docker build -t myflask .Sending build context to Docker daemon 4.608kBStep 1/4 : FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.8 —> c69984ff0683Step 2/4 : RUN apk add vim —> Using cache —> ebe2947fcf89Step 3/4 : RUN pip3 install redis —> Running in aa774ba9030eCollecting redis Downloading https://files.pythonhosted.org/packages/f5/00/5253aff5e747faf10d8ceb35fb5569b848cde2fdc13685d42fcf63118bbc/redis-3.0.1-py2.py3-none-any.whl (61kB)Installing collected packages: redisSuccessfully installed redis-3.0.1Removing intermediate container aa774ba9030e —> 47a0f1ce8ea2Step 4/4 : COPY ./app /app —> 50908f081641Successfully built 50908f081641Successfully tagged myflask:latest-t 指定要创建的目标路径。. 这里有个点记住啦,表示是当前路径下的Dockerfile文件,可以指定为绝对路径。编译完后就通过docker images查看一下,就能看到myflask镜像了,里面能直接运行python main.py来启动flask,并且内置了vim和redis包。Docker Compose让多容器成为一个整体我们的每个容器都负责一个服务,这样容器多的时候一个个手动启动的话是不现实的。在这种情况我们可以通过Docker Compose来关联每个容器,组成一个完整的项目。Compose项目由Python编写,实现上调用了 Docker服务提供的 API 来对容器进行管理。# 安装docker-composesudo pip3 install docker-compose实现能记录访问次数的web在这里,我们通过docker-compose.yml文件来启动flask容器和redis容器,并将两个不同容器相互关联起来。首先在/docker/flask目录下创建docker-compose.yml文件,内容如下:version: ‘3’services: flask: image: myflask container_name: myflask ports: - 8080:80 volumes: - /docker/flask/app:/app working_dir: /app # 运行后执行的命令 command: python main.py redis: # 如果没有这个镜像的话会自动下载 image: “redis:latest” container_name: myredis然后我们把上面的main.py代码修改一下,连接redis数据库并记录网站访问次数。main.py修改后内容如下:from flask import Flaskfrom redis import Redisapp = Flask(name)redis = Redis(host=‘redis’, port=6379)@app.route(”/")def hello(): count = redis.incr(‘visit’) return f"Hello World from Flask! 该页面已被访问{count}次。“if name == “main”: # Only for debugging while developing app.run(host=‘0.0.0.0’, debug=True, port=80)目前的文件结构是:flask├── app│ └── main.py└── Dockerfile└── docker-compose.yml这些编排的文件参数都是取自于Docker,基本都能看懂,其它就没啥啦,直接命令行跑起来:docker-compose up就辣么简单!现在我们在浏览器上访问http://localhost:8080/就能看到结果了,并且每访问一次这页面都会自动增加访问次数.在这里,我们也能通过docker ps命令查看运行中的容器:docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES66133318452d redis:latest “docker-entrypoint.s…” 13 seconds ago Up 12 seconds 6379/tcp myredis0956529c3c9c myflask “/entrypoint.sh pyth…” 13 seconds ago Up 11 seconds 443/tcp, 0.0.0.0:8080->80/tcp myflask有了Docker Compose的Docker才是完整的Docker,有了这些以后开发简直不要太爽,每个容器只要维护自己的服务环境就ok了。Docker的日常操作镜像常用操作# 下载镜像docker pull name# 列出本地镜像docker images# 使用镜像运行生成容器docker run name:tag# 删除镜像docker rmi id/name容器常用操作可以通过容器的id或者容器别名来启动、停止、重启。# 查看运行中的容器docker ps# 查看所有生成的容器docker ps -a# 开始容器docker start container# 停止容器docker stop container# 重启容器docker restart container# 移除不需要的容器(移除前容器必须要处于停止状态)docker rm container# 进入后台运行的容器docker exec -it container /bin/sh# 打印容器内部的信息(-f参数能实时观察内部信息)docker logs -f container通过-i -t进来容器的,可以先按ctrl + p, 然后按ctrl + q来退出交互界面组,这样退出不会关闭容器。docker-compose常用操作# 自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。docker-compose up# 此命令将会停止 up 命令所启动的容器,并移除网络docker-compose down# 启动已经存在的服务容器。docker-compose start# 停止已经处于运行状态的容器,但不删除它。通过start可以再次启动这些容器。docker-compose stop# 重启项目中的服务docker-compose restart默认情况,docker-compose up启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试。当通过Ctrl-C停止命令时,所有容器将会停止。结语这次接触Docker的时间虽然不长,但是这种微服务细分的架构真的是惊艳到我了。以前玩过VM虚拟机,那个使用成本太高,不够灵活,用过一段时间就放弃了,老老实实维护自己的本机环境。有了这个Docker以后,想要什么测试环境都行,直接几行代码生成就好,一种随心所欲的自由。上面写的那些都是日常使用的命令,能应付基本的需求了,真要深入的话建议去找详细的文档,我就不写太累赘了,希望大家都能去接触一下这个Docker,怎么都不亏,你们也会喜欢上这小鲸鱼的。 ...

December 27, 2018 · 2 min · jiezi

用友云微服务架构下配置文件管理利器:配置中心

微服务架构是这几年IT领域的一个高频词汇,越来越多的项目和应用正在以微服务的思想进行重构。相比于单体应用和SOA架构,微服务优势也逐渐凸显,被广大架构师和技术人员引入和推崇。当然,单体应用、SOA、微服务等各有优势和不足。单体架构在早期的企业内部信息化或者搭建中小型项目时很常见,简单说就是将应用程序的所有功能都打包成一个独立的单元,可以是JAR、WAR、EAR或其它归档格式。一般单体应用使用通用的IDE即可开发调试,项目便于共享、易于部署和测试。但是单体架构的应用不够灵活,任何修改都需要重新构建和部署,而且应用可能较大,不利于持续的迭代和交付。此类应用容易受到技术栈的限制,一旦先期设计出现问题,后期的技术债务会加重负担。微服务架构模式有点像SOA,它们都由多个服务构成。SOA架构将多服务整合在一起,但其和服务总线ESB过于紧密的联系以及其复杂性,也使得其在互联网应用中的部分场景里不太适用。微服务架构模式不包含ESB服务,微服务应用乐于采用简单轻量级协议,比如REST或者RPC来实现。常见的微服务调用拓扑结构如下,此示例是基于Spring Cloud的微服务调用。完整的微服务解决方案应该包括服务注册治理中心、API网关、服务的降级熔断以及分布式配置等机制。在业务逻辑体现上,其调用关系可能如下:微服务架构下有很多优势,这里不做具体扩展,可简单罗列如下:1:独立微服务复杂度可控制;2:可灵活水平扩展;3:可独立部署运维;4:开发针对性强、支持小团队敏捷开发;5:提高系统的可组合性和可替代性;但是,在解决服务拆分问题、水平扩展问题的同时,其使用也衍生出了一系列问题,如分布式应用部署自动化问题、数据一致性、配置文件管理、服务的注册、服务的治理等。当然,也有一系列的方案来处理解决上述问题,如基于DevOps的自动化运维工具(用友云运维平台)、配置中心、最终一致性方案、服务注册治理中心与统一的服务网关等。本文主要讨论下在微服务和分布式架构下,配置文件如何更好的管理。每个微服务都维护着相对独立的业务,服务之间通过RPC或者REST API的方式相互调用,聚合成整体。每个微服务一般有自己的数据库和支撑环境,每一个微服务实例也会拥有自己的运行环境或者说是独立的进程,也就相应的需要维护一份自身环境的配置文件,如Spring的配置文件、属性文件、业务的XML文件、AccessKey认证文件等等。一个完整的业务通常由多个微服务组成,每个微服务在开发环境、测试环境、预发布环境和生产环境对应着不同的配置信息,需要针对不同环境维护多份。开发者在开发测试以及联调的时候需要对应不同的环境信息,频繁的修改和调整配置信息,带来了很大麻烦。大量的配置文件的维护给运维人员带来相当大的困扰。痛点一:配置文件太多,如果开发规范不严格,各个组件集成在一起时配置文件整合麻烦;痛点二:一个服务一般对应开发、测试、预发布、生产等多组环境,多套环境下配置文件手动管理也很复杂;痛点三:运行中的环境对应的配置项需要变化调整时,调整配置文件需要重启环境;上述问题的出现,迫切需要一个统一的配置文件管理、维护的服务出现,此服务需能统一管理多个微服务的配置文件,还能根据开发、测试、预发布、生产等环境进行区分隔离,并且能记录配置文件的多个版本。我们通常将这类服务定义为分布式配置管理或者配置中心。在配置中心的管理下,运维管理员只构建一份代码,即可发布到不同的环境,应用从配置中心拉取不同环境的配置,各个应用可以定义多个配置文件,运维管理员在配置中心统一维护各个服务的配置信息。配置中心具有的如下几大基础功能:1:配置文件和配置项的统一管理、支持多套环境;2:提供统一SDK,获取不同的配置;3:统一的信息监控和统计;4:实时或近实时推动变化信息到客户端;同时,配置中心本还要考虑安全和加密等问题,其自身也是集群应用,应该具有高可用、支持高并发等特性。业界常用的配置中心开源产品如百度的disconf和阿里的diamond以及携程的Apollo等,几种产品各有所长,这里也不统一展开。用友云配置中心(以下简称配置中心)在对比开源产品提供功能的基础上,提供基于自身技术特色的配置中心服务,更加适用用友云体系的云产品,其示意图如下:配置中心优势:优势1:配置中心服务端权限控制,统一管理界面;通过配置中心的服务端,管理员可以进行应用管理、配置管理、文件上传、在线修改、查看客户端连线状态等操作;可以通过超级管理员登录,也可以统一在开发者中心进行登录。管理员可以配置通知邮箱,在配置文件变化后以邮件方式通知对应的关注人。优势2:支持配置的多环境、多应用、多版本;业务应用可能同时有多个版本在线,也可能有测试、预发布、生产等多个环境同时运行。配置中心包含应用、环境、版本等概念,可以维护多个应用,针对每个应用的不同环境,管理多个版本的配置文件,保证不同版本业务应用的运行环境对应不同版本的配置文件的需要。优势3:支持SaaS应用的多租户隔离、应用隔离管理;基于用友云平台,已经发展起了很多SaaS应用,各个SaaS应用在数据库隔离、文件存储隔离、缓存隔离等做了大量的工作。配置中心也支持将各个租户的配置文件数据隔离管理,更好的适配了SaaS应用对于数据隔离的需求。优势4:SDK、动态属性注入、回调机制;和配置中心管理服务端配和使用的,是Client端的SDK。利用SDK,开发者可以集成配置中心的拉取配置、监听变化等功能,其使用配置和注解的方式让集成过程简单快捷且侵入较小。优势5:实时监控连接状态;配置中心的管理员可以下开发者中心的控制台,监控到各个版本的配置文件被客户端的拉去和连接的状态,令管理员可以全局监控各个客户端的状态。优势6:多种连接方式,短轮询和长轮询机制支持近实时推送;集成与使用篇用友云的配置中心的集成和使用相当简单,可以通过SDK的方式单独使用,也可以通过开发者中心应用管理中的配置提取和下载方式使用。使用方式一:SDK方式步骤1:配置文件统一管理,通过界面操作配置文件的上传和修改;步骤2:属性文件、XML文件SDK拉取;步骤3:配置变化动态通知、属性注入和回调机制支持,注解支持;可以看到,无需编写复杂的代码,只需要进行Spring的配置修改和少量的Annotation的编写即可,大大简化了开发者的集成过程。使用方式二:开发者中心结合配置中心使用(用友云配置中心和开发者中心结合,相得益彰!)用友云开发者中心简介:用友云开发者中心为开者提供了资源管理、持续集成、持续交付、容器服务、镜像仓库等应用基础服务,同时为应用的微服务架构落地提供完备的支撑,结合DevOps的理念,通过提供自动化运维、日志管理、中间件服务等功能,帮助开发及运维人员降低产品研发迭代过程中的负担。详情请参考http://iuap.yonyou.com/produc…://developer.yonyoucloud.com。(1)与配置中心的结合,在开发者中心的应用发布的过程中进行配置文件提取,并使用golang版本工具拉取配置;(2)配置中心将各个租户间数据进行隔离并加入了权限控制,使得其对多租户的支持更加完善;此之外,配置中心和消息总线结合,可以完美支持微服务间解耦!配置中心是逻辑解耦,物理不解耦的微服务的利器。它可以解决配置导致的系统耦合,架构反向依赖的问题,配置中心的演进过程,配置私藏到全局配置文件,到配置中心。异步消息是逻辑上解耦,物理上也解耦的微服务架构利器。它非常适合数据驱动的任务依赖,调用方不关注处理结果,或者调用方关注处理结果,但是回调的时间很长的场景。综上所述,利用用友云配置中心,可以集中管理微服务架构下应用的配置文件,并且其支持多套环境、多个版本,提供完善的SDK,可利用注解的方式简便的拉取指定的配置。而且,用友云配置中心以服务的方式提供统一的管理界面,结合用友云的认证中心可以提供可靠的安全保障。

December 25, 2018 · 1 min · jiezi

微服务配置中心实战:Spring + MyBatis + Druid + Nacos

在结合场景谈服务发现和配置中我们讲述了 Nacos 配置中心的三个典型的应用场景,包括如何在 Spring Boot 中使用 Nacos 配置中心将数据库连接信息管控起来,而在“原生”的 Spring 中可以怎么使用 Nacos 配置中心呢?很多基于 Spring MVC 框架的 Web 开发中,Spring + MyBatis + Druid 是一个黄金组合,在此基础上融入 Nacos 配置中心,将会发生什么特别的变化呢?本文将通过一个用户信息查询示例,演示在 Spring Web 项目中如何将数据库连接池的配置存放到 Nacos 中,统一运维管控,达到配置治理与降低数据泄露风险的目的。数据表在测试数据库中新建 user 表,其中包含用户名称等字段,与接下来的 User model 类相对应。CREATE TABLE user ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, name varchar(10) NOT NULL DEFAULT ’’ COMMENT ‘名字’, create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’, update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间’, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘用户表’;添加一行测试数据:INSERT INTO user (name, create_time, update_time) VALUES (‘Nacos’, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);Spring该示例是 Spring 常规的 Web 项目,项目结构如下:pom.xml引入 Nacos Spring 的依赖包 nacos-spring-context:<dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-spring-context</artifactId> <version>${latest.version}</version></dependency>笔者在撰写本文时,nacos-spring-context 的最新版本为:0.2.2-RC1dispatcher-servlet.xmldispatcher-servlet.xml 为示例中 Spring MVC 的入口配置,在其中通过 import 引入了 Nacos、Druid、MyBatis 的配置,其内容如下:<?xml version=“1.0” encoding=“UTF-8”?><beans xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xmlns:context=“http://www.springframework.org/schema/context" xmlns:mvc=“http://www.springframework.org/schema/mvc" xmlns=“http://www.springframework.org/schema/beans" xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven/> <context:annotation-config/> <context:component-scan base-package=“com.alibaba.nacos.example.spring”/> <import resource=“nacos.xml”/> <import resource=“datasource.xml”/> <import resource=“spring-config-mybatis.xml”/></beans>nacos.xml关键看 nacos.xml ,nacos-spring-context 的扩展了 Spring 的 XML Schema 机制,自定义了 <nacos:property-source/> 等元素,详细配置内容如下:<?xml version=“1.0” encoding=“UTF-8”?><beans xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xmlns=“http://www.springframework.org/schema/beans" xmlns:nacos=“http://nacos.io/schema/nacos" xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://nacos.io/schema/nacos http://nacos.io/schema/nacos.xsd"> <nacos:global-properties server-addr=“127.0.0.1:8848” /> <nacos:property-source data-id=“datasource.properties”/></beans>其中通过 <nacos:global-properties /> 设置 Nacos Server 的连接地址,通过 <nacos:property-source /> 从 Nacos 配置中心加载了 dataId 为 datasource.properties 的配置,nacos-spring-context 会解析获取到的配置内容并添加到 Spring Environment 的 PropertySources 中,使得后续初始化 Druid 连接池的时候能获取到数据库连接地址、账号密码、初始连接池大小等信息。这就是 Nacos 配置中心与 Spring 结合的关键点。datasource.xml这是数据库连接池的配置,初始化了 DruidDataSource 的 Spring Bean,并将其通过 DataSourceTransactionManager 设置为 Spring 的数据库连接池。<?xml version=“1.0” encoding=“UTF-8”?><beans xmlns=“http://www.springframework.org/schema/beans" xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xmlns:tx=“http://www.springframework.org/schema/tx" xsi:schemaLocation=“http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id=“dataSource” class=“com.alibaba.druid.pool.DruidDataSource” init-method=“init” destroy-method=“close”> <property name=“url” value="${datasource.url}”/> <property name=“username” value="${datasource.username}”/> <property name=“password” value="${datasource.password}”/> <property name=“initialSize” value="${datasource.initial-size}”/> <property name=“maxActive” value="${datasource.max-active}”/> </bean> <bean id=“txManager” class=“org.springframework.jdbc.datasource.DataSourceTransactionManager”> <property name=“dataSource” ref=“dataSource”/> </bean> <tx:annotation-driven transaction-manager=“txManager”/></beans>从上面的配置内容看一看到,数据库连接池不需要因为引入 Nacos 配置中做任何特殊的改变。其他User 的 Model、Service 等也跟不使用 Nacos 配置中心时完全一致,这里就不一一贴出,完整示例代码可以在 nacos-examples 获取:https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-config-datasource-exampleNacos参照 Nacos 官网的快速开始:https://nacos.io/zh-cn/docs/quick-start.html从 Nacos 的 github 上下载最新稳定版本的 nacos-server:https://github.com/alibaba/nacos/releases解压后到 Nacos 的 bin 目录下,执行 startup 启动脚本以单机模式启动 Nacos Server, Windows 请使用 cmd startup.cmd ,Linux/Unix/Mac 环境请使用 sh startup.sh -m standalone 。启动后,浏览器访问:http://localhost:8848/nacos/index.html 就可以来到 Nacos 的控制台,新增 dataId 为 datasource.properties 的配置,对应上面 Spring 的 nacos.xml 中的 dataId。配置内容则与 Spring 的 datasource.xml 中的连接池属性一一对应,示例如下:datasource.url=jdbc:mysql://localhost:3306/testdatasource.username=rootdatasource.password=rootdatasource.initial-size=1datasource.max-active=20运行示例中是 UserController#get() 通过 UserServce 调用 Mybatis 的 Mapper 类(UserMapper)从数据库中查询指定 ID 的用户信息,假设该示例是运行在端口为 8080 的 Tomcat 上,访问:http://localhost:8080/users?id=1 地址将返回:{ “id”: 1, “name”: “Nacos”}总结本文通过一个示例演示在“原生” Spring 中如何使用 Nacos 配置中心,从示例可以看出,对原有的 Spring 项目基本没有任何侵入,只需在 pom.xml 中添加 nacos-spring-context 的依赖,然后再定义并引入 nacos.xml 配置,就可以将数据库连接池信息管控起来,做到统一运维,并降低数据泄露的风险。试想,如果你有多个项目连接同一个数据库或一个项目部署很多实例,当数据库密码修改时,你不需要去修改每个项目的 datasource.properties 文件,再走一次应用的部署发布流程,而是到 Nacos 的控制台上修改一个配置项,再去重启应用实例即可。当然,如果你是自己管理数据库连接池,则可以做到连“重启应用实例”都不需要了,只需在监听到 Nacos 配置变化时重新初始化数据库连接池即可。将 Spring 配置放置到 Nacos 配置中,还能用上“动态推送”、“版本管理”、“快速回滚”、“监听查询”,以及后续的 “灰度发布”、“配置加密”、“权限管控”等功能,为 Spring + MyBatis + Druid 插上“飞翔”的翅膀。作为 Nacos 配置中心的阿里云免费产品 ACM:https://www.aliyun.com/product/acm,已经提供了上面所有的功能,如果您不想自己部署运维 Nacos Server 或者想使用“推送轨迹”、“细粒度权限控制”、“ECS 实例 RAM 角色”等高级特性,不妨尝试下免费的 ACM。完整示例代码:Nacos: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-config-datasource-exampleACM: https://github.com/nacos-group/nacos-examples/tree/acm/nacos-spring-example/nacos-spring-config-datasource-example本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 24, 2018 · 2 min · jiezi

你真的了解RPC吗?

现微服务盛行,服务之间通信大概就两种方式Api和Rpc。下面两个列子来让你了解Api和Rpc的区别。列子一 文章的增删改查。Api 实现:Router::get(’/article/{id}’,‘ArticleController@get’);Router::post(’/article’,‘ArticleController@create’);Router::put(’/article/{id}’,‘ArticleController@edit’);Router::delete(’/article/{id}’,‘ArticleController@delete’);然后在控制器Article调用模型return Article::find($id)->toArray();Rpc 实现RpcServer::add(‘Article’);没错就一行代码列子二 计算器假如机器A上面一个计算器 Counter,以Rpc的方式提供给其他机器使用.计算器Counter代码class Counter{ private $i = 0; public function __construct($i = 0) { $this->i = $i; } // 加法 public function add($v) { $this->i += $v; return $this; } // 减法 public function sub($v) { $this->i -= $v; return $this; } // 乘法 public function mul($v) { $this->i *= $v; return $this; } // 除法 public function div($v) { $this->i /= $v; return $this; } // 获取结果 public function get() { return $this->i; }}Rpc 实现RpcServer::add(‘Counter’);Rpc客户端调用$c = new ClientCounter(10);echo $c->add(3)->mul(2)->sub(10)->div(5)->get();Api 实现:你觉得 Api 应该怎么实现?以上代码是我在设计 one框架的一些思考?如你喜欢请star https://github.com/lizhichao/one如其他观点,欢迎留言讨论。 ...

December 24, 2018 · 1 min · jiezi

Tars基础框架手动搭建——填掉官方 Guide 的坑

背景Tars 简介腾讯 Tars 是腾讯内部使用的 TAF(Tencent Application Framework)的对外开源版,去掉了许多冗杂多余的部分。该框架集开发、运维、微服务、RPC 等为一体。对程序员而言,这就是一个能够快速搭建整个微服务体系的开发框架。这个框架支持基于 C++、Node.js、PHP、Java 等语言开发,最新版本已经支持后台开发语言新贵——Go。安装任务Tars 实际的应用场景是多机器、多节点部署的,不过从实验验证的角度,我做的只是在单一一台机器上,实现 Tars 管理平台部署,以及任务的发布。由于 Tars 版本一直在迭代,为防止文章过时误导后来者,本文以 f3ef251013 节点为准,请读者 follow 最新的 Tars 版本来。官方安装文档在这里。然而,正如很多新的开源项目一样,代码很丰满,文档很骨感。一步一步跟着官方文档走的话,是有可能无法一次走通的……本文跟随文档的安装脉络,进行了重新梳理,为读者呈现一个尽量不挖坑的搭建过程。请注意,“Tars” 这个概念,除了其基础框架之外,还包含开发工具(如 TarsCpp、TarsJava 等等)、协议等等许多内容。不过本文主要讲述 Tars 基础框架,因此下文所提及的 “基础框架”,如无特别说明,都专指 “Tars 基础框架”。本文解决的问题前文提及,直接 follow 官方文档,是无法完成服务部署的。因为过程中遇到很多坑,每一个坑都导致基础框架无法搭建,或者是搭建后无法发布服务。笔者根据文档搭建过程中遇到的坑有:部分操作需要 sudo——文档中有些温馨地提醒了 sudo,但是另外一些未提醒数据库采用 MySQL 5.6 版,但部分说明不适用于 MariaDB说明文字与配图不完全一致不同代码处的数据库用户名和密码不统一启动所需的数据库表信息有缺失环境准备系统准备部署实验需要准备至少一台 Linux 机器。这可以是一台本地的实体机或虚拟机,也可以是一台云主机。由于部署过程中,需要编译 Tars 框架以及 MySQL 代码(如果系统里没装 Oracle 的 MySQL 的话),强烈建议系统至少要求有 4GB 的内存!系统建议采用 CentOS 或 Ubuntu。本文采用 Ubuntu 来安装,但 CentOS 差别不大,读者可以参考执行。此外,笔者不采用 root 账户,只有在需要 root 权限的时候才使用 sudo 操作。像笔者这样只有 1 核 1GB 云主机的,还需要在本地额外准备一台 Linux 虚拟机用于编译,再将编译出来的目标文件转移到云主机上。软件准备使用 Ubuntu,基础框架和 C++ 开发环境需要以下开发组件:gcc g++(CentOS 则是 gcc-c++) flex bison make cmake perl gcc zlibc gzip git libncurses5-devprotobuf-c-compiler protobuf-compiler libprotobuf-dev libprotobuf-c-dev libprotoc-devlibmariadb-client-lgpl-dev mariadb-client mariadb-server此外,还需要手动安装的软件或库有:mysql-server node.js(包括 npm)TarsCloud/TarsFramework TarsCloud/TarsWeb TarsClous/TarsCpp这些手动安装的软件会在后问说明。MySQL 问题官方文档使用的 MySQL 版本是 5.6。但是这有两个问题:Oracle 维护的开源 MySQL 已经发展到 5.7 和 8.0 版了,Tars 是否向后兼容?最新的 CentOS 和 Ubuntu 的软件包中已移除 MySQL,以 MariaDB 取代,Tars 是否支持?本人的答案是:从网上的资料看,基础框架支持 5.7,但需要修改 cmake 的选项,麻烦点;此外,在交流群中也有反馈 5.7 版有问题,但没有深入了解。支持,详见后文操作。笔者的方案是:使用 mariadb 作为数据库使用 libmysqlclient.a 作为 TarsCpp 开发环境创建时链接的库(基础框架编译时强制链接静态库)使用 libmariadb.so 作为实际应用开发时用的库备份安装之前,强烈建议不熟悉 Tars 基础框架的读者先给自己的机器做下备份,比如打个快照或者做个镜像之类的,这样如果后面部署失败了,也便于回滚系统,而不是一个一个抓虫。安装支持软件笔者所使用的用户名是 ubuntu,后文会有一些 shell 命令中采用了这个用户名,请读者留意替换成为自己的用户名。MySQL安装路径准备默认下载的 Tars 基础框架需要链接 MySQL 的静态库 libmysqlclient.a,此外对库所在的位置也写死在了 Makefile 中。因此我们需要为 Tars 基础框架准备环境。首先创建供基础框架链接的路径:$ sudo mkdir -p /usr/local/mysql$ sudo chown ubuntu:ubuntu /usr/local/mysql然后需要寻找一下 mariadb 的动态库位置和头文件位置:$ sudo find / -name ‘mariadb_com.h’ 2>/dev/null$ sudo find / -name ’libmariadbclient*’ 2>/dev/null笔者的环境中,两者分别在 /usr/include/mariadb 和 /usr/lib/x86_64-linux-gnu 下,那么我们就创建两个软链接:$ ln -s /usr/include/mariadb /usr/local/mysql/include$ ln -s /usr/lib/x86_64-linux-gnu /usr/local/mysql/lib再创建一个目录给 MySQL 实际安装用:$ mkdir /home/ubuntu/mysql-5.6 # /home/ubuntu 是笔者系统的家目录,读者请注意替换。以下同理。编译安装直接从 GitHub 上 clone MySQL 的工程代码后,选择合适的版本:$ mkdir -p ~/github.com/mysql/mysql-server$ cd ~/github.com/mysql/mysql-server$ git clone https://github.com/mysql/mysql-server.git ./$ git checkout -b 5.6 origin/5.6 # 切换到 5.6 版配置、编译、安装:$ cmake . -DCMAKE_INSTALL_PREFIX=/home/ubuntu/mysql-5.6 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_USER=mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DDOWNLOAD_BOOST=1 -DWITH_BOOST=/home/ubuntu/others/boost$ make && make install通过之后,我们还需要将 mysql 的静态库复制(或者链接)到为 Tars 基础框架准备的目录下:$ ln -s /home/ubuntu/mysql-5.6/libmysqlclient.a /usr/local/mysql/lib/Node.jsTars 管理平台是使用 node.js 开发的,因此需要安装 nvm。对不熟悉 node 的读者,这里也简单列下安装方式(不建议使用 root 账户操作):$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash$ source ~/.bashrc$ nvm install v8.11.3$ npm install -g pm2 –registry=https://registry.npm.taobao.orgTars 基础框架首先,要下载 Tars 的基础框架代码:$ mkdir -p /homes/ubuntu/github.com/TarsCloud/TarsFramework$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework$ git clone https://github.com/TarsCloud/TarsFramework.git ./编译之:$ cd build$ chmod +x build.sh$ ./build.sh prepare$ ./build.sh all如果编译失败(一般是缺某些库或组件),建议在解决问题后,清掉 TarsFramework 下的所有文件,重新 clone 后再编译。安装的过程复杂一点,安装路径是固定的(虽然可以在工程文件中调整,为统一起见,不建议修改):$ sudo mkdir -p /usr/local/tars$ sudo chown ubuntu:ubuntu /usr/local/tars$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/build$ ./build.sh install准备 Tars 数据库Tars 使用用户名 tars、密码 tars2015 的组合,操作 MySQL 数据库。高级玩法自然是修改 Tars 中的用户名/密码组合。这里为了简单起见,干脆就直接采用默认的就好了。不过后文会介绍如何使用自定义的用户名密码。笔者做验证时的 MySQL 与 Tars 部署在同一台机器上,IP 地址是 172.19.16.13。实际部署中,读者请注意换成实际地址。添加相关账户的命令如下:$ mysql -u root -p进入 mysql 命令行后:MariaDB [(none)]> grant all privileges on . to tars@localhost identified by ’tars2015’;MariaDB [(none)]> flush privileges;MariaDB [(none)]> exit;官方文档说的配置备份什么的,就不用关心了。使用 Tars 的系统基本是部署在云上的,大都会用云服务商提供的自带主备的数据库服务(推荐腾讯云 TDSQL 哦,金融级 DB,但是价格和普通 DB 一个等级)。接下来,我们通过执行 Tars 基础框架的 sql 脚本来创建相应的数据库结构:$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/sql/$ sed -i “s/192.168.2.131/172.19.16.13/g” grep 192.168.2.131 -rl ./*$ sed -i “s/db.tars.com/172.19.16.13/g” grep db.tars.com -rl ./*$ sed -i “s/10.120.129.226/172.19.16.13/g” grep 10.120.129.226 -rl ./*$ chmod +x exec-sql.sh$ ./exec-sql.sh其中,172.19.16.13 是笔者的 DB 的 IP 地址,读者实际部署时请注意修改。这些命令也给我们一个启发:数据库地址允许采用域名。TIPS-1如果读者不使用 tars/tars2015 的用户名/密码组合来操作数据库,那么可以自行修改上述的 sql 脚本:$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/sql/$ git status .On branch masterYour branch is up-to-date with ‘origin/master’.Changes not staged for commit: (use “git add <file>…” to update what will be committed) (use “git checkout – <file>…” to discard changes in working directory) modified: db_tars.sql modified: tarsconfig.sql modified: tarslog.sql modified: tarsnotify.sql modified: tarspatch.sql modified: tarsproperty.sql modified: tarsqueryproperty.sql modified: tarsquerystat.sql modified: tarsstat.sql可以看到被 sed 语句修改了的文件。读者可以在这些文件中找到用户名和密码配置项进行修改后,再执行。TIPS-2MariaDB server 安装之后默认监听 127.0.0.1 地址,但官方文档明确说明 DB 的 IP 地址不能使用 127.0.0.1。读者需要修改 MariaDB 的配置文件中监听地址的选项,否则后续 Tars 基础框架启动后,会遇到没有权限访问数据库的错误。部署 Tars 基础框架Tars 框架核心服务Tars 核心基础框架指的是 tarsAdminRegistry, tarsregistry, tarsnode, tarsconfig, tarspatch 五个。前面我们其实已经编译好了,我们可以先把这些服务打包:$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/build$ make framework-tar这会在 build 目录下生成 framework.tgz 文件。接下来我们需要做一些操作:$ sudo mkdir -p /data/log/tars$ sudo mkdir -p /home/tarsproto$ sudo mkdir -p /usr/local/app/tars$ sudo chown -R ubuntu:ubuntu /usr/local/app /data/log/tars /home/tarsproto$ mv /homes/ubuntu/github.com/TarsCloud/TarsFramework/build/framework.tgz /usr/local/app/tars$ cd /usr/local/app/tars$ tar zxvf framework.tgz这会在 /usr/local/app/tars/ 下面生成前述几个核心基础框架组件对应的文件夹。此外,还有 tars_install.sh 和 tarsnode_install.sh 两个脚本。不过我们得先配置一下——五个核心基础框架组件的目录下均有 conf 文件夹,可以看到各个组件的配置文件,比如 tars.tarsregistry.config.conf。对操作已经很熟悉了的读者可以手动修改这些配置。不过也可以简单点地进行以下修改:$ cd /usr/local/app/tars$ sed -i “s/192.168.2.131/172.19.16.13/g” grep 192.168.2.131 -rl ./*$ sed -i “s/db.tars.com/172.19.16.13/g” grep db.tars.com -rl ./*$ sed -i “s/registry.tars.com/172.19.16.13/g” grep registry.tars.com -rl ./*$ sed -i “s/web.tars.com/172.19.16.13/g” grep web.tars.com -rl ./*四个 sed 命令修改的地址,对应的是:本机地址,不能写 127.0.0.1;前述数据库的地址;tarsregistry 的 部署地址,可以不是本机;web.tars.com 是 rsync 服务和 web 管理平台的部署地址。修改了 IP 地址之后,还需要检查 tars 访问数据库的用户名和密码。这里我们最好是手动 vim 去改,因为几个文件的书写格式不完全一致:$ cd /usr/local/app/tars$ grep dbpass -rl ./检查搜索出来的 conf 文件中的 dbuser 和 dbpass 字段。最后就是启动核心框架服务和 rsync(好艰难):$ cd /usr/local/app/tars$ chmod +x tars_install.sh$ ./tars_install.sh$ sudo ./tarspatch/util/init.sh$ chmod +x tarsnode_install.sh$ ./tarsnode_install.sh然后我们可以在 croncab 中配置核心基础框架的监控项: * * * * /usr/local/app/tars/tarsnode/util/monitor.sh这样一来,五个框架核心服务就启动起来了。Tars web 管理平台Tars web 管理系统在另一个 Git repo 中:$ mkdir -p /homes/ubuntu/github.com/TarsCloud/TarsWeb$ cd /homes/ubuntu/github.com/TarsCloud/TarsWeb$ git clone https://github.com/TarsCloud/TarsWeb.git ./$ sed -i ’s/db.tars.com/172.19.16.13/g’ config/webConf.js$ sed -i ’s/registry.tars.com/172.19.16.13/g’ config/tars.conf其中 172.19.16.13 是笔者机器的 IP,读者请注意Tars web 是用 node.js 编写的,不需要编译。管理平台默认监听在 3000 端口上,可在 config/webConf.js 中修改 port 参数的值。配置了端口之后,就可以启动 Tars web 管理平台了:$ cd /homes/ubuntu/github.com/TarsCloud/TarsWeb$ npm install –registry=https://registry.npm.taobao.org$ npm run prd可以查看 TarsWeb 目录下的 package.json 文件可以看到更多的信息——毕竟并不是每个人都懂得 node.js 开发。Tars 框架基础服务检查核心服务状态Tars web 管理平台启动后,如果按照默认设置的话,平台会在 3000 端口建立 http 服务。使用浏览器访问,可以看到如下界面:这三个组件,就是前文所述的 “tars 框架核心服务” ,如果按照前述逻辑部署后,在 web 页面就可以看到的。可以依次点开这三个服务,确保服务的状态都如下图所示:如果服务的状态不对,那么可能是前面哪一步操作不恰当。可以查找 log 来定位(log 文件的路径参见后文)。部署其他基础服务剩下的几个基础框架服务就需要进行手动部署。但部署的方法其实还是蛮简单的,这里挑一个出来细讲,其他的类似。首先,我们需要把其他的基础框架打包出来:$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/build$ make tarsstat-tar$ make tarsnotify-tar$ make tarsproperty-tar$ make tarslog-tar$ make tarsquerystat-tar$ make tarsqueryproperty-tar这样会在 /homes/ubuntu/github.com/TarsCloud/TarsFramework/build 目录下分别生成上述六个组件的 tgz 文件。接下来我们以 tarsstat 为例说明部署方法:创建服务点击 web 主页的 “运维管理” 选项卡,进入服务界面:各参数按照如下填写:应用:填 “tars”服务名称:填 “tarsstat”服务类型:在下拉菜单中选 “tars_cpp”模板:在下拉菜单中选 “tars.tarsstat”节点:选择本机的出口地址,像笔者的情况,就是 172.19.16.13SET:现阶段不用填,这是 tars 的进阶功能OBJ:填 “StatObj”OBJ 绑定地址 和 端口:可以手动调整,也可以点 “获取端口” 按钮自动分配端口类型:TCP协议:TARS其他默认即可。填好后,点 “确定” 即可部署。注意,此时的 “部署”,只是在 tars 内注册了一个服务(占了个坑),但这个服务还没有上线提供可用的功能。发布服务部署了服务后,需要刷新页面,这样就可以看到左边 tars 的服务列表多了一项:“tarsstat”现在,我们需要真正地发布这个服务了。点击 “tarsstat” 选项卡,可以看到上面有六个功能选项。点击 “发布管理”,视图如下:勾选节点,然后点击 “发布选中节点”,界面如下:这个时候点 “发布版本” 的下拉菜单,是没有内容的。我们需要点 “上传发布包”,在新打开的窗口,选择上一步 “创建服务” 时打包的 tarsstat.tgz 文件上传即可。上传成功后,我们再在 “发布版本” 下拉菜单中选择刚刚上传的包,然后点 “发布”。稍等一会后,我们只要看到 tarsstat 的状态变成如下,就是发布成功了:其他各个服务的特殊参数除了不需要额外配置数据库之外,接下来的五个服务的配置发布流程基本一致。但也有以下一些不同,读者在发布剩余服务的时候请注意修改:各服务的名称不同,请相应地修改;各服务的服务类型均为 “tars_cpp”,但是模板不同——每一个服务均有其对应的专用模板,比如 tarsconfig 对应 tars.tarsconfig 模板;tarsquerystat 和 tarsqueryproperty 的 “协议” 应选 “非TARS”,其他服务为 “TARS”;各服务对应的 Obj 名称如下:tarsnotify: NotifyObjtarsproperty: PropertyObjtarslog: LogObjtarsquerystat: NoTarsObj(非 TARS 协议)tarsqueryproperty: NoTarsObj(非 TARS 协议)此外,以下这一步是 tarsstat 特有的步骤:在发布服务之前,需要进入数据库进行以下操作,防止 tarsstat 启动失败:MariaDB [(none)]> use db_tars;MariaDB [db_tars]> CREATE TABLE t_server_notifys ( id int(11) NOT NULL AUTO_INCREMENT, application varchar(128) DEFAULT ‘’, server_name varchar(128) DEFAULT NULL, container_name varchar(128) DEFAULT ’’ , node_name varchar(128) NOT NULL DEFAULT ‘’, set_name varchar(16) DEFAULT NULL, set_area varchar(16) DEFAULT NULL, set_group varchar(16) DEFAULT NULL, server_id varchar(100) DEFAULT NULL, thread_id varchar(20) DEFAULT NULL, command varchar(50) DEFAULT NULL, result text, notifytime datetime DEFAULT NULL, PRIMARY KEY (id), KEY index_name (server_name), KEY servernoticetime_i_1 (notifytime), KEY indx_1_server_id (server_id), KEY query_index (application,server_name,node_name,set_name,set_area,set_group) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;MariaDB [db_tars]> exit;所有服务均发布完成并状态正确之后,Tars 基础框架就部署完成啦,恭喜你!日志查询如果部署 Tars 框架服务过程中遇到什么错误,可以查阅的 log 在以下路径:/usr/local/app/TarsWeb/log/usr/local/app/tars/app_log/tars关于自动部署Tars 其实还提供了一套比较简易的快速部署脚本。那个脚本我没有尝试过,但据说也是有一些坑……这里我推荐 maq128 同学 的文章:tars小白安装必成手册,分别讲述了快速部署、手工部署、docker 部署的内容。另外,如果有问题,读者也可以加入 Tars 官方交流群,不保证所有问题都能够精准回答,但是群里不少大神还是给了我不少启发。群号参见 Tars 官方文档。下一步研究按照官方的建议,Tars 的所有基础服务都需要至少进行灾备部署,但是部署方式如何实现,并没有明确的说明或者建议。这是笔者后续准备实验的。参考资料pm2 日志加时间戳mysql/mariadb centos7 修改root用户密码及配置参数tars 部署过程-youz1976的专栏腾讯Tars环境搭建中遇到的坑tars各个自带的服务都是做什么的,又是怎么保障他们的可靠性的?请问t_server_notifys建表语句?TARS 用户体系模块+资源模块使用指引tars小白安装必成手册本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。本文地址:https://segmentfault.com/a/1190000017482106。原文发布于:https://cloud.tencent.com/developer/article/1372998,也是本人的博客。 ...

December 22, 2018 · 4 min · jiezi

史上最全Java学习内容

前端部分:1)HTML:网页的核心语言,构成网页的基础2)CSS:使网页更加丰富多彩灿烂的利器3)JavaScript:使网页动起来的根本,加强了网页和用户之间的交互4)HTML DOM:换一种更加形象化的角度来看待网页,让我们更加方便的控制网页5)HTML BOM:与浏览器交互不可或缺的工具6)JavaScript库,主要是:jQuery及其插件、YUI及其插件,使编写网页更加的方便快捷和健壮的强大工具7)AJAX:异步提交,增强了用户使用网页的良好交互体验8)JSON:比 XML更小、更快,更易解析的数据传输工具9)FLEX:提供丰富多彩的动画效果10)普元工作流:更加清晰明了的帮助用户处理业务流程上面的工作11)JSP:Servlet的展示层,使网页逻辑与网页设计的显示分离12)JSTL:加强和简化了JSP页面的开发13)EL:使JSP页面写起来更加简单后台部分:1)JAVA语言编程基础部分:内容丰富是Java知识体系结构的核心和基础2)JDBC:提供了一种基准,据此可以构建更高级的工具和接口,使Java开发人员能够编写数据库应用程序3)JavaMail:用于电子邮件的相关的编程工作4)JUnit:单元测试,整个变成工作测试的地位始终非常重要5)Log4j:使我们能够更加细致地控制日志的生成过程6)Servlet:JavaWeb的核心7)Struts2:JavaWeb编程中明星级的框架,优点多功能强使编程工作更简单,主要用于控制跳转8)Spring:JavaWeb编程中明星级的框架,同样优点多功能强使编程工作更简单,主要用于管理对象9)iBatis:JavaWeb编程中明星级的框架,同样也是优点多功能强使编程工作更简单,主要用于程序和数据库之间的交互10)SQL:与数据库交互式编程的必备工具版本控制:1)SVN:版本控制,方便团队协同工作WEB服务器:1)Tomcat:优秀免费的中小型WEB服务器2)Weblogic:功能很强大的WEB服务器开发工具:1)Eclipse:开源强大的Java编程工具2)MyEclipse:在eclipse基础上加上自己的插件开发而成的功能强大的企业级集成开发环境数据库:1)Oracle:数据库业界老大,这个常用一点当然,也仅仅是常用一些常用的功能而已,需要加强2)MySQL:最好的关系型数据库之一3)SqlServer:最好的关系型数据库之一数据库客户端:1)Toad:非常棒的数据库客户端软件操作系统:1)Windows2)Linux远程登录的会话工具:1)SSH:一直在用,非常不错其他:各种种类和版本的浏览器(推荐使用FireFox)、office办公软件系列、各种文本编辑器(推荐Sublime)、各种阅读器等等下面是从网上找的三幅图片,比较好的说明了作为一个Java程序员的学习路线图,这里作为一种自我提醒的工具,不时看看,并且会赶紧修补自己的知识树!1、Java的知识体系结构2、JavaWeb开发的基本学习路线图3、JavaWeb开发的成长路线图第一部分:Java高级学习课程大纲1、工程化专题我们的工程化专题有五大内容:Maven、Nexus 、jenkins、代码审查 、Git/SVN一共耗时一个月2、源码分析专题源码分析有三大内容: spring的源码分析,里面包括FactoryBean和MVC和事务处理与Spring源码中设计模式分析;持久层 ;企业级开发前瞻,一共耗时2个月3、高并发与高性能加粗文字高并发与高性能有四大内容:并发编程, 里面又包含有线程安全和NIO和AIO 。异步通信,里面包含有本地队列和消息中间件。分布式协调技术,里面包含有Zookeeper和服务锁 。NoSqI: 里面包含有 MongoDB和Redis和Memcached 。一共耗时2个月4、高可用性与可扩展高可用性与可扩展有两大内容: 分布式架构介绍,里面有导流技术和服务设计和存储设计。服务调用,里面包含有WebService和Dubbo。 一共耗时2个月5、性能优化性能优化有四大内容:优化技巧,如何寻找性能瓶颈。JVM优化。数据库优化。服务器优化。一共耗时2个月上面这五大专题,是几位工作经验十多年的大牛,根据自己往年的工作经验与经历,在根据现在科技发展的实际情况,历经几个月的时间编写而成,换句话说,上面的五大专题,也就是他们这十几年精华总结,现在,您只要按照上面的课题学习,只需要花费掉七个月多的时间,就能够学会与理解几位大牛十多年总结出来的精华。学完这些,还怕公司老总不给涨工资和升职么?第二部分:阶段性的学习学什么东西都一样,小宅相信大家也是一样,在学东西的时候,总会安排好自己阶段性的学习,这样才能有效的提升自己与有效的理解和认知所学的知识。合理安排好,才能起到事半功倍的效果。阶段一:阶段二:阶段三:阶段四:阶段五:如何一起学习,有没有学习资料?由于文笔也有限,只能按照自己的理解这样浅显分享给大家。还是一句话不能去停止学习。学习以上技术可以加入Java进阶架构学习群:952124565。

December 21, 2018 · 1 min · jiezi

阿里重磅开源Blink:为什么我们等了这么久?

摘要: 阿里巴巴计算平台事业部研究员蒋晓伟深入分享Flink和Blink的关系以及未来发展。推荐阅读。12月20日,由阿里巴巴承办的 Flink Forward China 峰会在北京国家会议中心召开,来自阿里、华为、腾讯、美团点评、滴滴、字节跳动等公司的技术专家与参会者分享了各公司基于 Flink 的应用和实践经验。感兴趣的开发者可以看云栖社区的对于大会的主会+5场分论坛的直播与视频点播。会议进行中,看到AI前线对蒋晓伟的采访。正如许多开发者所关心的Flink和Blink的关系(云栖社区2016年文章:阿里蒋晓伟谈流计算和批处理引擎Blink,以及Flink和Spark的异同与优势),如今有了更新的方向。本篇AI前线的专访讲述的极为清晰。特别转载,共享。*今年,实时流计算技术开始步入主流,各大厂都在不遗余力地试用新的流计算框架,实时流计算引擎和 API 诸如 Spark Streaming、Kafka Streaming、Beam 和 Flink 持续火爆。阿里巴巴自 2015 年开始改进 Flink,并创建了内部分支 Blink,目前服务于阿里集团内部搜索、推荐、广告和蚂蚁等大量核心实时业务。在大会的主题演讲上,阿里巴巴集团副总裁周靖人宣布,阿里巴巴内部 Flink 版本 Blink 将于 2019 年 1 月正式开源! 阿里希望通过 Blink 开源进一步加深与 Flink 社区的联动,并推动国内更多中小型企业使Flink。Flink Forward China会上,AI 前线对阿里巴巴计算平台事业部研究员蒋晓伟(花名量仔)进行了独家专访,他与我们分享了关于下一代实时流计算引擎的看法,并针对 Blink 的重要新特性、开源后 Blink 与 Flink 之间的关系、Blink 后续规划等问题进行了解答。阿里巴巴与 Flink随着人工智能时代的降临和数据量的爆发,在典型的大数据业务场景下,数据业务最通用的做法是:选用批处理的技术处理全量数据,采用流式计算处理实时增量数据。在很多的业务场景之下,用户的业务逻辑在批处理和流处理之中往往是相同的。但是,用户用于批处理和流处理的两套计算引擎是不同的。因此,用户通常需要写两套代码。毫无疑问,这带来了一些额外的负担和成本。阿里巴巴的商品数据处理就经常需要面对增量和全量两套不同的业务流程问题,所以阿里巴巴就在想:能不能有一套统一的大数据引擎技术,用户只需要根据自己的业务逻辑开发一套代码。这样在各种不同的场景下,不管是全量数据还是增量数据,亦或者实时处理,一套方案即可全部支持,这就是阿里巴巴选择 Flink 的背景和初衷。彼时的 Flink 不管是规模还是稳定性尚未经历实践,成熟度有待商榷。阿里巴巴实时计算团队决定在阿里内部建立一个 Flink 分支 Blink,并对 Flink 进行大量的修改和完善,让其适应阿里巴巴这种超大规模的业务场景。简单地说,Blink 就是阿里巴巴开发的基于开源 Flink 的阿里巴巴内部版本。阿里巴巴基于 Flink 搭建的平台于 2016 年正式上线,并从阿里巴巴的搜索和推荐这两大场景开始实现。目前阿里巴巴所有的业务,包括阿里巴巴所有子公司都采用了基于 Flink 搭建的实时计算平台。目前,这套基于 Flink 搭建的实时计算平台不仅服务于阿里巴巴集团内部,而且通过阿里云的云产品 API 向整个开发者生态提供基于 Flink 的云产品支持。以下内容整理自 AI 前线对蒋晓伟的采访。开源的时机AI 前线:为什么选择现在将 Blink 开源?这其中有哪些考量?什么样的时机才是开源最合适的时机?蒋晓伟: 在我看来,有几个因素:第一个因素是,这几年我们一直试图把阿里对 Flink 的改进推回社区,但社区有自己的步伐,很多时候可能无法把我们的变更及时推回去。对于社区来说,需要达成共识,才能更好地保证开源项目的质量,但同时就会导致推入的速度慢一些。经过这几年积累,我们这边和社区之间的差距已经变得比较大了。Blink 有一些很好的新功能,比如批处理功能,在社区版本是没有的。在过去这段时间里,我们不断听到有人问,Blink 什么时候能开源、是不是能开源这样的呼声。我们有两种方法,一种就是慢慢地推回去再给用户用。但我们认为这样等下去对社区不是最好的。我们还是希望尽快把我们的代码拿出来,尽量让大家都能用起来。所以最近这半年,我们一直都在准备把代码整理好去进行开源。选择在这个时间点开源有几个好处:第一个好处是我们所开源的这些代码在阿里内部经过像双一十、双十二这样巨大流量的检验,让我们对它的质量有更大的信心,这是非常大的好处;第二个好处,Flink Forward 大会是第一次在中国举办,在这样一个场合开源表明了阿里对 Flink 社区坚定的支持,这是一个比较好的场合。主要是基于这些考虑。选 Blink 还是 Flink?这不会是一个问题AI 前线:开源的 Blink 版本会和阿里巴巴内部使用的 Blink 保持一致吗?蒋晓伟: 即将开源的是阿里巴巴双十二的上线版本,还会有一些小的改进。AI 前线:Blink 开源后,两个开源项目之间的关系会是怎样的?未来 Flink 和 Blink 也会由不同的团队各自维护吗?蒋晓伟: 开源的意思是,我们愿意把 Blink 的代码贡献出来,但这两个项目是一个项目。有一件事情需要澄清一下,我们将公开 Blink 的所有代码,让大家都可以看到,但与此同时,我们会跟社区一起努力,通过讨论决定 Blink 以什么样的方式进入 Flink 是最合适的。因为 Flink 是一个社区的项目,我们需要经过社区的同意才能以分支的形式进入 Flink,或者作为变更 Merge 到项目中。我想强调一下,我们作为社区的一员需要跟社区讨论才能决定这件事情。Blink 永远不会成为另外一个项目,如果后续进入 Apache 一定是成为 Flink 的一部分,我们没有任何兴趣另立旗帜,我们永远是 Flink 的一部分,也会坚定地支持 Flink。我们非常愿意把 Blink 的代码贡献给所有人,所以明年 1 月份我们会先将 Blink 的代码公开,但这期间我们也会和社区讨论,以什么样的形式进入 Flink 是最合适的、怎么贡献是社区最希望的方式。我们希望,在 Blink 开源之后,和社区一起努力,把 Blink 好的地方逐步推回 Flink,成为 Flink 的一部分,希望最终 Flink 和 Blink 变成一个东西,阿里巴巴和整个社区一起来维护。而不是把它分成两个东西,给用户选择的困难,这不是我们想要的。因此未来用户也不会面临已经部署了 Flink、是否要把 Flink 迁移到 Blink 的问题,企业选型时也不需要在 Flink 和 Blink 之间抉择,Blink 和 Flink 会是同一个项目。Blink 开源只有一个目的,就是希望 Flink 做得更好。Blink 改进了什么?AI 前线:能不能重点介绍一下即将开源的 Blink 版本有哪些比较重要的新技术特性?与 Flink 最新发布版本相比,阿里的 Blink 做了哪些方面的优化和改进?蒋晓伟: 阿里巴巴实时计算团队不仅对 Flink 在性能和稳定性上做出了很多改进和优化,同时在核心架构和功能上也进行了大量创新和改进。过去两年多,有很多更新已经推回给社区了,包括 Flink 新的分布式架构等。目前我们的 Blink 版本跟社区版本还有几点差异,第一个是稳定性方面,我们做了一些优化,在某些场景会比社区版本更加稳定,特别是在大规模场景。另外还有一个比较大的不一样是我们全新的 Flink SQL 技术栈,它在功能上,特别是在批处理的功能上比社区版本强大很多。它支持现在标准 SQL 几乎所有的语法和语义。另外,在性能上,无论是在流式 SQL 还是批 SQL,我们的版本在性能上都有很大的优势。特别是在批 SQL 的性能方面,当前 Blink 版本是社区版本性能的 10 倍以上,跟 Spark 相比,在 TPCDS 这样的场景 Blink 的性能也能达到 3 倍以上。如果用户对批处理或者对 SQL 有着比较强的需求,我们这个版本会用户可以得到很多好处。Blink 在阿里内部的应用AI 前线:请介绍一下 Blink 在阿里内部的使用情况。目前 Blink 在阿里的大数据架构中扮演什么样的角色?在阿里内部主要用于哪些业务和应用场景?蒋晓伟: 现在阿里的大数据平台上,所有的实时计算都已经在使用 Blink;同时,除了实时计算以外,在一些流批一体化的场景也会用 Blink 来做批处理;我们在机器学习场景也有一个探索,叫做 Alink,这个项目是对 Flink Machine Learning Library 的改进,其中实现了大量的算法,都是基于 Flink 做实时机器学习的算法,Alink 在很多场景已经被证明在规模上有很大的优势。同时,我们在图计算场景也有一些探索。AI 前线:目前阿里内部有多少部门在使用 Blink?蒋晓伟: 前段时间我们刚刚做过统计,阿里的技术部门大约有 70% 都在使用 Blink。Blink 一直是在用户的反馈之中成长起来的,对于内部用户反馈的数据倾斜、资源使用率、易用性方面的问题,Blink 都做了针对性的改进。现在 Blink 用的最多的场景主要还是实时计算方面,阿里还有一些业务现在相对比较新,还没有进入实时计算的领域,等这些业务进入实时计算领域时也会使用 Blink。在批处理方面,阿里内部也有一个自研的批处理引擎叫做 MaxCompute,MaxCompute 也会拥抱 Flink 生态,在语法和语义上做和 Flink 兼容的工作。未来,整个阿里的计算体系和平台都会融入同一个生态。后续规划AI 前线:接下来阿里对于 Blink 还有哪些规划?包括技术改进、落地应用、更新维护、社区等几个方面。蒋晓伟: 从技术上说,今天我们公布了 Flink 在批处理上的成果,接下来,我们会对技术持续投入,我们希望每几个月就能看到技术上有一个比较大的亮点。下一波亮点应该是机器学习场景。要把机器学习支持好,有一系列的工作要做,包括引擎的功能、性能和易用性。这些工作我们已经在内部的讨论和进行之中,接下来几个月,大家应该会看到一些成果。我们也在和社区讨论一些事情。除了机器学习之外,我们在图计算方面也有一些探索,包括对增量迭代更好的支持。做完这些之后,可以认为 Flink 作为大数据的计算引擎已经比较完备了。同时,我们也重点去做 Flink 的生态,包括 Flink 与其他系统之间的关系、易用性等。Flink 要真正做好,不仅需要它本身功能强大,还需要把整个生态做得非常强大。这部分我们甚至会跟一些 ISV 合作,看看是不是能够在 Flink 之上提供更好的解决方案,进一步降低用户的使用门槛。在社区方面,我们希望能够把把 Blink 完全融入 Flink 社区,一起做 Flink 社区的运营,让 Flink 真正在中国、乃至全世界大规模地使用起来。在应用方面,实时流计算其实有很多很有潜力的应用场景,但有一些可能大家不是非常熟悉,我们会对这些场景做一些推广。以实时机器学习为例,它往往能够给我们带来比一般的机器学习更大的效果提升。去年,实时强化学习给我们在搜索上带来了 20% 以上的提升。除此之外,在安全领域(比如实时的 Fraud Detection)、监控报警方面,还有 IoT 领域,实时流计算都有非常广泛的应用场景。这些 Flink 现在可能已经做了,但是大家还没有意识到,Flink 能够给大家带来这样的商业上的好处。AI 前线:Blink 开源之后,后续阿里在这基础上做的变更和更新会以什么样的方式推回社区版本?蒋晓伟: 我们理想的方式是,阿里内部的版本是社区的 Flink 版本加上一些定制化的插件,不需要对 Flink 本身做修改,而是对 Flink 做增加。比如跟阿里内部系统交互的部分跟社区是不适用的,就会保持在内部,我们希望这些修改不动 Flink 代码,而是用插件的方式加在 Flink 上面。最终的方式就是,对于所有公司都有用的修改会在 Flink 代码本身做修改,使所有使用 Flink 的公司都能从中获利,而对接阿里内部系统的部分就只在阿里内部使用。下一代实时流计算引擎之争AI 前线:先在很多人提到实时流计算引擎,都会拿 Spark 和 Flink 来做对比,您怎么看待下一代实时流计算引擎之争?未来实时流计算引擎最重要的发展方向是什么?蒋晓伟:Spark 和 Flink 一开始 share 了同一个梦想,他们都希望能够用同一个技术把流处理和批处理统一起来,但他们走了完全不一样的两条路,前者是用以批处理的技术为根本,并尝试在批处理之上支持流计算;后者则认为流计算技术是最基本的,在流计算的基础之上支持批处理。正因为这种架构上的不同,今后二者在能做的事情上会有一些细微的区别。比如在低延迟场景,Spark 基于微批处理的方式需要同步会有额外开销,因此无法在延迟上做到极致。在大数据处理的低延迟场景,Flink 已经有非常大的优势。经过我们的探索,Flink 在批处理上也有了比较大的突破,这些突破都会反馈回社区。当然,对于用户来说,多一个选择永远是好的,不同的技术可能带来不同的优势,用户可以根据自己业务场景的需求进行选择。未来,在大数据方向,机器学习正在逐渐从批处理、离线学习向实时处理、在线学习发展,而图计算领域同样的事情也在发生,比如实时反欺诈通常用图计算来做,而这些欺诈事件都是实时地、持续不断地发生,图计算也在变得实时化。但是 Flink 除了大数据领域以外,在应用和微服务的场景也有其独特的优势。应用和微服务场景对延迟的要求非常苛刻,会达到百毫秒甚至十毫秒级别,这样的延迟只有 Flink 的架构才能做到。我认为应用和微服务其实是非常大的领域,甚至可能比大数据更大,这是非常激动人心的机会。上面这些都是我们希望能够拓宽的应用领域。AI 前线:在技术方面,Spark 和 Flink 其实是各有千秋,但在生态和背后支持的公司上面,Flink 是偏弱的,那么后续在生态和企业支持这块,阿里会如何帮助 Flink?蒋晓伟: 这次阿里举办 Flink Forward China 就是想推广 Flink 生态的重要举动之一。除了 Flink Forward China 大会,我们还会不定期举办各种线下 Meetup,投入大量精力打造中文社区,包括将 Flink 的英文文档翻译成中文、打造 Flink 中文论坛等。在垂直领域,我们会去寻找一些合作伙伴,将 Flink 包装在一些解决方案中提供给用户使用。AI 前线:关于开源项目的中立性问题。阿里现在在大力地推动 Flink 开源项目的应用和社区的发展,但业界其他公司(尤其是与阿里在其他业务上可能有竞争的公司)在考虑是否采用 Flink 的时候可能还是会对社区的中立性存在一些疑虑,对于这一点,阿里是怎么考虑的?蒋晓伟: 阿里本身会投入非常大的力量推动 Flink 社区的发展和壮大,但我们也非常希望有更多企业、更多人加入社区,和阿里一起推动社区发展,这次阿里承办 Flink Forward China 峰会就是想借此机会让更多公司参与进来。光阿里一家是无法把 Flink 生态做起来的。我希望大家能够看到我们在做的事情,然后消除这样的疑虑。我们会用自己的行动表明,我们是真的希望把 Flink 的社区做大,在这件事情上,我们并不会有私心。本文作者:阿里云头条阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 21, 2018 · 2 min · jiezi

蚂蚁金服 Service Mesh 渐进式迁移方案|Service Mesh Meetup 实录

摘要: Service Mesher Meetup 上海站演讲内容整理。小蚂蚁说:本文是基于在 Service Mesher Meetup 上海站的主题分享《蚂蚁金服 Service Mesh 渐进式迁移方案》内容整理,完整的分享 PPT 获取方式见文章底部。敖小剑,蚂蚁金服高级技术专家,十六年软件开发经验,微服务专家,Service Mesh 布道师,Servicemesher 社区联合创始人;龙轼,阿里巴巴技术专家、前京东 Hadoop 负责人、Hadoop 代码贡献者、现负责UC 基于 Kubernetes 自研的 PaaS 平台整体的稳定性。大家好,今天给大家带来的演讲主题是《蚂蚁金服 Service Mesh 渐进式迁移方案》,给大家介绍一下我们蚂蚁金服主站的 Service Mesh 迁移方案,在稍后的内容中我会给大家解释什么是“渐进式”。今天的演讲方式有些特殊,将会是两位讲师合作。我是敖小剑,来自蚂蚁金服中间件团队,另外一位讲师 龙轼 ,来自 UC 基础研发部。Service Mesh 演进路线今天的内容将会有四块主要内容:Service Mesh演进路线:介绍蚂蚁金服计划在主站落地Service Mesh的方案,由于涉及到大量的存量应用和超大规模,又要保证迁移过程的平滑,因此我们的落地方案相比社区方案要复杂的多。实现平滑迁移的关键:介绍在整个迁移方案中,为了实现平滑迁移的几个关键做法,然后今天我们将详细展开其他的一个关键点:DNS寻址方案。DNS寻址方案的演进:详细介绍Kubernetes/Istio/SOFAMesh一路演进过来的DNS寻址方式。DNS寻址方案的后续规划:介绍我们在DNS寻址方案上的后续规划。前两块内容将由我来为大家介绍,后两块内容将由我的同事 龙轼 为大家介绍。在展开内容之前,先看一下背景,Service Mesh在蚂蚁金服主站落地的背景:目标:需要满足我们对长期目标的认可,具体指服务间通讯走Service Mesh,而且是Istio这种带完整的控制平面的Service Mesh形态,基础设施要构建在k8s之上,而应用的形态要向微服务靠拢。现状:而现实是存在很多挑战,首先还有很多应用没有实现微服务化,而且我们的k8s普及程度也不够,还有非常多的应用没有运行在kubernets之上。Istio的成熟程度也稍显不足,不够稳定,更大的挑战的是Istio目前无法原生支持我们蚂蚁金服的规模,我们还在试图对Istio进行改进和扩展。最后,在落地时必须考虑的非常现实的一点:现有系统中为数众多的应用不可能一夜之间全部迁移。关键需求:因此在落地实施时,非常重要的需求是:要实现平滑迁移。简单说,微服务 + Service Mesh + kubernetes 是我们的目标,但是如何从现有体系出发,向目标平稳和坚实的迈进,必须给出可行的实践指导。今天演讲的内容,要给大家介绍的就是,在这样的背景下,我们蚂蚁金服选择的Service Mesh主站落地演进方案。这个方案预期会在2019年初全面铺开。主站落地方案的实施原则,这是我们在过去半年的实践中,总结归纳出来的行为指导:符合远期规划:一定要有清晰的长期目标,明确的知道未来的大方向。避免走弯路,避免浪费投资,理想状态是计划中的每一步都可以为下一步奠定坚实的基础。即使因为某些原因不得已妥协或绕行,也应该清晰的知道后面应该如何回归,谢绝中途推倒重来——代价太高,无法承受。循序渐进:认清现实,如此之大的变革,一定是需要分步进行,不要心存一步登天的幻想,现实可行的方式是小步快跑。将整个过程拆解为若干个大步骤,每一步的工作量和复杂度都控制在一个可以接受的范围内,以保证每一步都简单方便,切实可行。有可操作性:在操作层面上,要有足够的弹性,即每个步骤中的工作内容,都应该是可以分批进行。以步步为营的方式,逐步扩大战果,杜绝一刀切。在接下来的演进路线中,大家将会体会到这三个原则在实际落地时的指导作用。这个图的信息量有点大,描述的是 Service Mesh 和 k8s 落地可能的多种演进路线。我们先从最下面开始看,这是当前蚂蚁金服主站大多数应用的现状:即应用"部署在非k8s上",应用也"不是Service Mesh形态"。 然后看最上面,这是我们期望的蚂蚁金服主站未来的应用终极形态:应用"部署在k8s上",应用也迁移到了"Service Mesh形态"。这里有个特别的地方,我们将Service Mesh形态细分为两种模式:Sidecar模式:只有Sidecar,没有控制平面,和外部系统的各种集成都是在Sidecar中直接进行。这是第一代的Service Mesh,Linkerd/Envoy都是如此,华为基于ServiceComb演进而来的mesher,新浪微博的Mesh,包括我们蚂蚁金服基于MOSN开发的用于取代多语言客户端的Mesh方案。Istio模式:有完善的控制平面,可以提供强大的控制能力,而且从数据平面分离,这是第二代的Service Mesh,典型如Istio和Conkduit/Linkerd 2.0。之所以将Service Mesh形态细分,是因为我们有着这样一个特殊背景:目前的原生Istio无法支撑我们蚂蚁金服的规模,因此在改进完善Istio之前,我们不得不暂时在Sidecar模式下短暂停留。另外一个原因就是考虑到存量应用的迁移,多一个Sidecar模式作为中间缓冲,会让整个迁移过程平滑很多。现在我们来介绍图中展示的四条演进路线:左边的路线1,思路是先将应用迁移k8s部署,再迁移到Service Mesh形态。这条路线的最大好处,是过程中每个阶段的绝大多数投资都将最终得以保留,因为符合k8s+service mesh的远期目标。右边的路线2,思路是跳过k8s,先迁移到Service Mesh形态,一路演进到Istio模式,然后最后迁移到k8s。中间的路线3,直接一步到位,这个路线是Istio默认的方式,或者说Istio根本没有考虑过迁移的问题,默认客户已经有完善的k8s,然后将改造好的应用直接部署在Istio上。这个路线对于蚂蚁金服主站的复杂场景,当然是不现实的。(补充:只是对蚂蚁金服主站不合适,对于大多数公司,规模不是那么巨大,也没有历史负担,也有k8s基础,完全可行。)还有一条特别的路线4,走位飘忽,先和路线2一样迁移到Sidecar模式,然后走回路线1,上k8s,再在有k8s支持的情况下继续演进到Istio模式。下面我们来详细分析各条演进路线的优劣和实施条件。演进路线2,和路线1的核心差别,在于:是先上k8s,还是先上Service Mesh。而且路线2是在非k8s条件下一路演进Service Mesh到我们期望的终极形态Istio模式,这意味着过程中和最终目标有非常大的偏移。演进路线2的好处,在于第一步非常的自然:没有k8s的限制,因此不依赖基础设施,实施方便。毕竟,k8s普及度是个大问题。在原有的侵入式框架的客户端SDK基础上,通过包裹一个proxy,重用原有SDK的能力,可以非常快速的得到一个基本可用的Sidecar。除了多一个proxy外,没有引入太多的新概念和新思想,符合现有开发人员/运维人员的心智,容易接受因此,路线2特别容易落地,可以快速达成短期目标,直接拿到Service Mesh的部分红利,如:多语言支持,方便类库升级等。但是,这个路线的问题在于再往后走,开始完善Service Mesh的功能以向Istio模式靠拢时,由于没有k8s的底层支持,因此不得不做大量的工作来提供类k8s的功能。尤其是Istio的非k8s支持,官方方案基本上只是一个demo,完全不具备生产可用性,要完善好,工作量很大。而关键点在于,这些投入,在迁移到k8s时,又因为和k8s提供的功能重复而被放弃。因此,结合我们前面的原则(符合远期规划,不浪费投资),路线2对蚂蚁金服主站落地是不合适的。演进路线4是一个非常特殊的路线,可以理解为路线1(先上k8s再上Service Mesh)的短期妥协版本。因为路线1的前提条件是要先大规模铺开k8s,将现有应用迁移到k8s之后再继续往Service Mesh演进,这对于还没有普及k8s的公司来说是一个非常高的门槛,很容易因此受阻而无法启动。因此,如果暂时不具备k8s条件, 又不想就此止步,那么选择路线2是唯一的出路。而上面我们分析过,路线2虽然能够在第一步快速拿到短期红利,但是由于偏离长期目标后续发展会有问题。怎么办?路线4可以是这种场景下的一个折衷选择:在k8s没有铺开之前,第一步沿路线2走,先吃下非k8s下Sidecar模式快速落地的红利。然后第二步避开非k8s下继续演进到Istio模式的大坑,切换到路线1,回归长期目标。好处非常明显:在k8s未铺开前,先往前迈进一步,避免就此卡壳。和路线2一样,第一步可以快速的拿到短期红利。后续转为路线1后,因为符合远期规划,因此后续演进不存在投资浪费的问题缺点就是存在少量的投资浪费,毕竟非k8s下的Sidecar模式还是有些工作内容在迁移到k8s之后会有改动。不过,这个改动不会太大,和拿到的红利相比还是值得的。路线4在操作时,存在一个变数:现有应用在向Sidecar模式的Service Mesh迁移,是需要一定时间的。有一种可能,就是在迁移过程中,k8s的普及开始了。这个变数的发生,取决于Sidecar模式的Service Mesh普及快,还是k8s的普及快。对路线4的分析结果:这是(k8s没有普及的)特殊时期的选择。在对四条可能的演进路线分析完成之后,我们来具体介绍蚂蚁金服的最终选择。坦言说,在过去半年中,我们的演进路线有几次摇摆和修订,今天我们公布的路线,和过去几个月中我们通过 meetup/技术大会/博客文章 等方式透露出来的方式会有一些变化。主要原因是在过去的这半年中,一方面我们对Sercice Mesh的认知更加深入,另一方面是蚂蚁金服的k8s背景也在变化。首先,在今年年初,我们确认Service Mesh大方向时,k8s还没有在蚂蚁金服普及,而且也没有明确的时间表。因此,我们在一番调研之后,选择了两条腿走路的方式:在非k8s环境下,以Sidecar模式先进行少量落地,主要是替换掉原有的多语言客户端 (拿短期红利)。开发SOFAMesh,集成MOSN到Istio,增加对多种RPC协议的支持,增加对RPC服务模式的兼容(为最终目标做准备 )在今年6月底的杭州第一届Service Mesh 线下 meetup 中,我们公布了 SOFAMesh 项目,我当时做了一个演讲 大规模微服务架构下的Service Mesh探索之路 ,有兴趣的同学可以去回顾一下我们当时的背景/需求/设计方案。大概在今年九月,我们完成了对非k8s下运行istio的深入调研,得出的结论是要实现这个模式需要非常多的工作。而且,我们对Service Mesh的认知也更加深刻,明确了通过Service Mesh将传统中间件能力向以k8s为代表的基础设施层下沉的战略方向。期间,内部也明确了k8s普及的大方向,因此,综合这两个重要输入,我们选择放弃继续在路线2上继续演进(即 istio on 非k8s)的想法。关于这一点,有兴趣的同学可以去阅读我在10月份QCon大会上的演讲内容 长路漫漫踏歌而行:蚂蚁金服Service Mesh实践探索 。最近,k8s普及的时间表再一次明确提前,蚂蚁金服将会在短时间内开启k8s的大面积普及。因此,我们的演进路线再一次发生变化。目前最新的演进路线将会是这样:当前还没有开始迁移的应用(处于演进路线图最下方),将按照路线1的方式进行迁移:先迁移到k8s,再迁移到Sidecar模式的Service Mesh。目前部分已经迁移的应用(路线2/4的第一步,非k8s部署的 Sidecar 模式),将沿路线4迁移,和路线1会师。由于应用众多,因此预计到 k8s + Sidecar模式 的迁移工作会持续比较长时间,在此期间,我们会同步完善Istio,和Istio官方一起合作来实现Istio对超大规模部署的支持。最后一步,迁移到最终目标(当然这一步的方案依然有很多待定内容,继续努力)需要强调的是:这个演进路线针对的是蚂蚁金服主站的特殊场景,并不具体普适性。大家可以在理解我们演进路线背后的思路和权衡方式之后,再结合自身的实际情况进行决策。比如,我们在UC落地时,由于UC有完善的k8s支持,而且目前落地的规模没那么夸张,因此是直接从"部署在k8s上" + “不是Service Mesh形态”,直接迁移到终态的。预计在金融云落实时,也会是如此,因为客户也不会有如此规模。总结:前面我们介绍了当应用程序向Service Mesh和K8s迁移时的几种可能的演进路线,分析了各条路线的利弊。并以蚂蚁金服主站为例,介绍了我们迁移的背景和演进路线的选择思路,希望能够帮助大家更好的理解Service Mesh的落地实践,以便在未来设计自家的落地方案时能有所参考。实现平滑迁移的关键前面给大家介绍了蚂蚁金服主站的Service Mesh演进路线,期间谈到要实现现有应用的平滑迁移。今天的第二个内容,将给大家介绍平滑迁移实现中的几个关键做法。首先,第一个关键是尽量保证迁移前后服务间网络互通。以向k8s迁移为例,在非k8s环境,典型的服务间访问方式是这样:每个服务向注册中心注册。客户端发起访问前,通过注册中心得到目标服务的实例列表信息,如IP地址/端口等在向k8s迁移的过程中,我们的做法是保证k8s内外网络打通,即服务的IP地址(在k8s中是pod ip)是可以相互直接访问的。基于这个前提,服务在迁移到k8s的过程中,原有的服务注册/服务发现/发起请求等逻辑都无需修改,是不是在k8s内,是不是pod ip,对原有服务化体系完全是透明的。因此,向k8s的迁移可以做到对业务应用非常的平滑,基本感知。透明拦截在迁移过程中,可以起到非常关键的作用。以Service-A要访问Service-B,在应用向Sidecar模式的Service Mesh迁移前后,会有有四种排列组合场景:Service-A和Service-B都没有迁移到Serive Mesh:此时请求会直接从Service-A发送到Service-B,称为直连,这是应用在开始迁移到Service Mesh之前的标准工作方式。Service-A已经迁移到Service Mesh,Service-B还没有:此时Service-A发出来的请求,会被劫持,然后发送到和Service-A一起部署的Sidecar(称为Outbound Sidecar),此时链路中只有一个Sidecar,称为(客户端)单跳。Service-B已经迁移到Service Mesh,Service-A还没有:此时Service-A发出来的请求,在到达Service-B时,会被劫持到和Service-B一起部署的Sidecar(称为Inbound Sidecar),此时链路中也只有一个Sidecar,称为(服务器端)单跳。Service-A和Service-B都迁移到Serive Mesh:此时Service-A发出来的请求,会被两次劫持,分别进入Outbound Sidecar和Inbound Sidecar,此时链路中有两个Sidecar,称为双跳。这是Istio的标准工作模式,也是我们迁移完成之后的最终工作模式。在这四种场景中,所有的网络请求,请求报文都是完全一致的,即不管是否被劫持到Sidecar,对请求报文都没有影响,也就是对发出请求报文的客户端和接受请求报文的客户端都是透明的,完全无感之。因此,在迁移过程中,可以单个服务逐个迁移,甚至服务的单个实例逐个迁移,而无需修改应用本身。在展开第三个关键点之前,我们来探讨一下:在Service Mesh时代,理想的客户端应该是什么样子?图中我们列举了一个传统的侵入式框架的客户端所包含的功能,在侵入式框架中,大部分的功能都是由客户端实现,因此会包含非常多的功能,如服务发现、负载均衡等基本功能,加密、认证、路由等高级功能。在应用迁移到Service Mesh之后,这些功能都下沉到Service Mesh中。因此,Service Mesh下的客户端可以进行大幅度的简化,成为一个新的轻量级客户端。对于这个轻量级客户端,我们希望可以尽可能的做的轻薄通用:实现简单,不管哪个编程语言都可以做到轻松实现,因此跨语言就方便了。而且越简单之后升级的可能性就会越少,以避免升级客户端。那我们来继续看,这个轻量级客户端里面最后还能剩下什么内容?图中列出了三个,其中最重要的,也是必不可少的是目标服务的标识,即无论如何简化,最低限度应该告之要访问谁吧?然后是序列化,对于RPC类肯定需要提供编解码功能,不过对于HTTP/REST类很多语言直接内置了标准实现。然后链路追踪,需要做一点工作来传递诸如SpanID之类的参数,同样这块也有可能通过自动埋点来实现。因此,最理想最单薄的客户端,可能只保留最后一个信息:目标服务的标示。在侵入式框架下,目标服务的标示是和服务注册/服务发现是直接关联的,这个标示通常都是服务名,通过服务发现机制实现了一个服务名到服务实例的寻址方式。在Service Mesh机制下,由于服务发现机制被下沉到Service Mesh中,因此只要底层Service Mesh能支持,这个目标服务的标示可以不必拘泥于服务名。那么,问题来了,对客户端来说:最简单,最通用,支持最广泛的寻址方式是什么?是DNS!在我们的迁移方案中,我们考虑引入DNS寻址方式。除了前面说的DNS是支持度最好,使用最普遍的寻址方式,在所有的编程语言和平台上都可以支持之外,我们还希望将DNS寻址方式作为未来产品的长期方向:在SOFAMesh和SOFAMosn中,我们已经基于名为x-protocol的方式实现了DNS通用寻址方式,用来解决Dubbo/HSF/SOFA等传统SOA服务模型在Service Mesh下的访问问题 (备注: 具体内容请见我的博客文章 SOFAMesh中的多协议通用解决方案x-protocol介绍系列(1)-DNS通用寻址方案 )未来在我们的serverless产品中,我们希望可以为运行其上的Function提供DNS寻址支持。可能还会有其他更加广泛的使用场景。因此,在我们的演进过程中,对于客户端SDK,我们有这样一个思路:一方面简化原有的SDK,去除和Sidecar重复的内容(满足短期需求)。另一方面,考虑到必然有一次客户端SDK的更换过程,那么我们希望在简化的同时引入基于DNS的通用寻址方式,以便在未来的后续迁移和功能扩展中可以依托这个机制来实现 (符合长期目标)图中描述的是在Service Mesh下,客户端通过域名来指定要访问的目标服务,然后通过DNS解析机制来串联底层的服务注册/DNS记录更新/透明劫持传递原始信息/Sidecar查找路由目标等详细实现机制。这里仅做简单示意,我就不详细展开了。在接下来的内容中,我的同事,来自UC基础研发部的 龙轼 同学,将为大家详细的展开DNS寻址方案的细节实现。DNS寻址方案的演进大家好,我是来自UC基础研发部的龙轼。 感谢小剑老师给我们介绍了蚂蚁和UC共建的Service Mesh的演进路线和实现平滑迁移的关键。接下来由我来向大家分享下实现平滑迁移的关键中的DNS寻址方案的演进。大家可以看上面的所示的DNS寻址方案的演进,我们先了解下各个服务寻址方案的背景。从 SOA 的寻址,到 Kubernetes 的寻址,然后再到 Istio 的寻址,最后是我们的 SOFAMesh 的DNS寻址方案。它们的寻址方案有什么不同,我们将一一分析它们的细节和总体寻址方案的演进路线。现在大家可以先来看下 SOA 架构下基于服务注册和服务发现的寻址。我们可以看到图中的 SOA 其实是单进程多接口的,依赖于 SOA 的服务注册与服务发现的。接下来我们看下 Kubernetes 的 DNS 寻址方式,它的寻址方式其实是通过DNS 的。从图中我们可以看到部署到K8S 上面的userservice 服务会生成一条DNS记录指向K8S 的ClusterIP。我们在 Pod 里面发起请求时通过 DNS 的 SearchDomain 域名补全规则就会从 DNS 里面查询得到ClusterIP,我们可以看出 Kubernetes 的寻址方案是单进程单接口的。看完 Kubernetes 的服务发现之后我们继续来看 Istio 的服务发现。从图中我们可以看出之前的流程都和 K8S 一脉相承,不同的地方在于 Istio 里面有个 SideCar 它把ClusterIP 拿到之后根据 ClusterIP 从 VirtualHost 里面匹配到 Rule 规则 转发给目标的 Pod 地址。最后我们来看下 SOFAMesh 的 DNS 通用寻址方案。根据我们之前分析的 SOA 寻址方案和 Kubernetes 寻址方案,我们可以看出如果我们的微服务不经过拆分和改造想上 Service Mesh 的话我们需要支持SOA之前的那种单个Pod 多个接口的。从图中看就是我们需要支持 com.alipay.userservice.interface1, com.alipay.userservice.interface2 这些接口解析到 ClusterIP, 我们知道k8s 中的service 是不支持的。那该如何是好,我们只能在DNS 上做文章修改DNS的记录来实现这一功能。确定了这一方案之后我们来看下我们设计的DNS寻址方案实现细节。大家看这张图:我们用 CRD 定义了一个 RPCService 和之前的 Service 有同样的 selector 的标签。然后用 RPC Service Controller 对 RPCService 做 Watch,当 RPCService 有更新的时候我们就把接口就是上述的 com.alipay.userservice.interface1 的记录写入 CoreDNS 里面。而 interface 是通过 Pod 里面的 Register Agent 来获取 Dubbo 里面暴露的。好的,说完这个方案的细节之后。我们可以看出其实其他的问题都不大,但是要更新DNS的这个我们需要支持。一开始我们 K8S 集群里面是用 Kube-DNS 来做 DNS 寻址的,但我们看这张 Kube-DNS 的架构图。可以看出修改它成本是比较大的,而且所有的DNS 都在同一个域里面,这个风险系数很高。 如果一旦修改错误势必会影响到之前的 k8s 的 service,导致线上的故障。这个时候我们跟踪到社区的 CoreDNS 项目,我们来看下 CoreDNS 的具体的架构。 它采用作为 Web 服务器 Caddy 的服务器框架,延用了Caddy 中的插件机制,大大的增加了 CoreDNS 的灵活性。 它的插件机制也特别简单,把所有的插件注册进一个Map里面来,在调用的时候从Map拿出他们有共同接口的函数。有兴趣的同学可以看下 Caddy 的插件代码实现。它的 DNS 协议库采用是由 Google 工程师 Meikg 开发的 DNS 库,他同时也是 SkyDNS 的开发者。后端可以采用 UDP/TCP、TLS 或者 gRPC 作为后端数据查询。上面有个Google工程师用 gRPC 做了一个 CoreDNS 插件的后端数据查询例子,有兴趣的同学可以看下。OK,既然 CoreDNS 的 Plugins 这么强大,我们可不可以用它来实现我们刚才说到的 Renew DNS的机制。 答案很显然是可以。我们看下上面的图,实现CoreDNS 的插件很简单,只需要继承上面的接口就可以了。 CoreDNS 官网有具体的教程在教我们怎么写一个插件。这个就不具体的展开了。到了我们最关键的点了:我们应该怎么更新我们的DNS。其实这点 CoreDNS 社区里面已经有人提出需求用 REST API 的形式提供更新 DNS 的接口。互联网任务工程小组也早在 rfc2136 定义了标准的 DNS UPDATE。 Google Cloud 和AWS 都有相应的实现。CoreDNS 社区其实已经把接口实现了,但是后端存储是基于file 的,数据没有落地。 蚂蚁和UC 这边扩展了 ETCD 插件的接口,把对应 DNS UPDATE 接口给实现了,实现 DNS 数据写入ETCD 里面。从图中我们可以看到 rpc.cluster.local 这个域 和 k8s 域 cluster.local 是在不同的插件链上的。这样在k8s域中没有 dynapirest 插件,我们就不能对k8s域中的DNS进行更新,这样就把之前Kube-DNS改造之后会对k8s域里面造成影响给去除了,更加的安全。我们可以看下 CoreDNS 后端存储的接口,其实和我们之前对数据操作的接口是没有什么差别的。目前 CoreDNS 的 DynAPI 还在主库代码没合并的状态。之后 DynAPI 这个项目会独立成一个插件项目。我们可以看下 CoreDNS 社区的 DynAPI 插件进展。OK,我们来看下我们的DynAPI 实现DNS 更新的一个效果。从图中我们可以看出 record.json 里面的一个域名的更新。通过 DynAPI 我们成功把 record.json 的DNS 记录给更新进去并且dns正常工作了。到现在我们通过CoreDNS 的插件就把DNS 更新的需求给解决了。其实CoreDNS 官网还有许多有趣的插件,可以丰富 CoreDNS 的功能和提升 CoreDNS 的性能。 大家可以看下中间的 autopath 插件,他把我们多次的在 searchdomain 拼凑的 DNS 记录的查询在在服务器上给实现了。 避免了多次的 Client 端和 Server 端的数据交互。有兴趣的同学可以看下 A-Deep-Dive-into-CoreDNS-2018。我们把 CoreDNS 的功能开发完了,上线的话很多人关注它的性能。 我们这边做了一个简单的性能测试,可以看出 CoreDNS 和 Bind DNS 这种现在比较通用的DNS的性能还是有点差距的。但是,我们通过上面的图可以看到在一定的QPS 下,CoreDNS 的延时是很低的。 我们可以看到所有的延时都落在4ms 之内。为了解决QPS的问题,我们通过 Kubernetes 的 HPA 给 CoreDNS 进行横向的扩展。一开始我们只是通过CPU的维度给 CoreDNS 扩展,但发现波动有点大。 之后我们切换成通过QPS的维度来进行扩容。CoreDNS 将会在Kubernetes 1.13 之后成为 Kubernetes 的默认的DNS服务。我们将会紧跟社区实施我们的方案并且反馈给社区。DNS寻址方案的后续规划我们再来看下我们后续的一些规划。可以看到我们的 DynAPI 其实在安全上还是有欠缺的。我们后续会把 HTTP 加强成 HTTPS 协议来增强 DynAPI 的安全性。还有如果我们 CoreDNS 的后端变化的更新的 Watch 由于 Watch的范围过大的话,会返回过多的数据。这样会影响到 Watch 的性能,CoreOS 在 ETCD3.2 增加了proxy 可以让我们根据不同的 ETCD KeySpace 去Watch,这样大大的提高了Watch的性能。最后一个,我们建议在创建 Kubernetes 集群的时候把 idc 的信息给带进Kubernetes的后缀域名中。这样我们之后可以通过 kubernetai 插件把不同的 Kubernetes 集群的域名进行整合通过本 IDC 缓存提高跨 IDC DNS 的访问速度。总结最后我们总结下,总体方面小剑老师给我们讲了蚂蚁金服主站 Service Mesh 的渐进式演进路线和实现平滑迁移的几个关键。 具体细节方面我们通过CoreDNS 的单点突破解决了 SOFAMesh 的 DNS 寻址的问题。感谢大家,希望这次演讲能让大家有所收获。视频回放与资料下载地址:https://tech.antfin.com/activ…(点击阅读原文可跳转到该网页)相关链接:SOFA 文档: http://www.sofastack.tech/SOFA: https://github.com/alipaySOFAMosn:https://github.com/alipay/sof…SOFAMesh:https://github.com/alipay/sof…本文作者:平生栗子阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 11, 2018 · 3 min · jiezi

微服务架构实践:从零搭建网站扫码登录

微信扫码登录大家都是应用比较多的登录方式了,现在大的购物网站像京东、淘宝等都支持使用APP扫码登录网站了。今天就用APP扫码登录网站的实例来举例说明微服务架构的搭建过程。微服务架构应该是什么样子在这之前先看一看一个微服务架构落地以后应该是什么样子的。平常所有的微服务架构更多的是从框架来讲的像Dubbo,SpringCloud等,从整个SpringCloud的生态来讲它也只包含微服务的一部分。因为微服务的拆分不可避免的造成了系统的复杂性,团队间的合作管理和持续的交付等等,都是一项比较复杂的工程,如果没有好的团队管理规范和持续交付的流程等微服务是很难落地的。下面简单介绍一下上图中微服务架构的每一层的功能和作用:基础设施层,这一项除非自己搭建IDC,基本上现在的阿里云、腾讯云和百度云等都已经很好的支撑,特别是对于小的公司来说,更节省成本。平台服务层,对于现有的微服务能够快速动态部署那就是Docker了,再加上现有k8s等容器管理工具等,更是让微服务的部署如虎添翼,如果系统已经达到已经规模以后,可以考虑使用此种方式进行动态的扩容,一般情况下使用Docker就能解决部署问题了。支撑服务层,这一层跟微服务框架贴的非常近了,像SpringCloud已经自带了很多功能,像注册中心、配置中心、熔断限流和链路跟踪等,Dubbo也自带注册中心。业务服务层,这一层主要解决的是业务系统如何使用微服务进行解耦,各业务模块间如何进行分层交互等,形成了以基础服务模块为底层和以聚合服务为前端的“大中台小前台”的产品策略。网关服务层,这一层解决了权限控制、外部调用如何进行模块的负载均衡,可以实现在该层实现权限和流量的解耦,来满足不同的端的流量和权限不同的需求。接入层,该层主要是为了解决相同网关多实例的负载均衡的问题,防止单点故障灯。微服务开发框架,现在流行的微服务框架主要是SpringCloud和Dubbo,SpingCloud提供了更加完整的生态,Dubbo更适合内部模块间的快速高并发的调用。持续交付流水线,快速进行需求迭代,从提交代码到部署上线,能够快速的交付。工程实践与规范,这一项做不好,那整个微服务实施起来绝对是痛不欲生啊,基础模块如何定义,基础模块如何与其他模块解耦,如何进行版本的管理这个我在之前的使用Git和Maven进行版本管理和迭代的方法进行了说明。端到端的工具链,这里就是敏捷运维工具,从研发代码到最终上线到生产环境,任何一部都要有工具去实现完成,实现点一个按钮就能最终上线的系统。以上讲了实现微服务架构应该要做哪些事情,现在可以想想你的微服务架构到底落地到生成程度了,闲话少说,书归正传,今天是用APP扫码登录网站这个功能来进行举例说明应该从哪些方面进行微服务的落地实践。网站扫码登录功能这个功能是指在网站上选择使用二维码扫码登录,网站展示二维码,使用已经登录的应用APP扫码并确认登录后,网站就能登录成功,这既简单快捷,又提高了安全性。现在实现扫码登录网站的技术基本上有两种,一种就是轮询,另一种就是长连接,长连接又分为服务器端单向通信和双向通信两种,服务端单向通信只能由服务器端向客户端一直发送数据,双向通信是客户端和服务器端可以相互发送数据。像微信、京东和淘宝都是采用轮询的方式进行扫码登录的,一直使用轮询的方式在请求服务器端。今天我设计的这个扫码登录的功能,是采用的长连接能够双向通信的WebSocket的方式实现的。网站扫码实现流程1.用户在网站上登录时选择扫码登录。2.服务器端收到请求,生成一个临时的令牌,前端生成带令牌的链接地址的二维码,在浏览器上显示。3.PC端同时要与后台建立起websocket连接,等待后台发送登录成功的指令过来。4.用户用应用扫码,这个时候如果已经登陆过,后台就能获取到当前用户的token,如果没有登录到系统中,需要提前做登录。5.用户在应用APP上已经显示了是否确认登录的按钮。6.用户点击确认按钮,应用APP发起后端的api调用。7.后端接收到调用,根据临时名牌向websocket模块发送当前用户的token,pc端接收到登录成功,跳转到用户个人首页。如果用户点击了取消按钮,会根据uid向websocket模块发送取消登录的指令。技术的选型1.微服务框架的选择现在比较流行的是SpringCloud和Dubbo这两个框架,RPC的微服务框架还有Motan都不错,这里我使用SpringCloud和Dubbo这两个框架,使用SpringCloud实现网关和聚合服务模块并对外提供http服务,使用Dubbo实现内部模块间的接口调用。注册中心使用Zookeeper,Zookeeper能够同时支持SpringCloud和Dubbo进行注册。2.Websocket框架选择其实Spring现在已经具备websocket的功能了,但是我没有选择使用它,因为它只是实现了websocket的基本功能,像websocket的集群,客户端的管理等等,使用spring实现的话都得从零开始写。之前就一直使用netty-socketio做websocket的开发,它具备良好的集群、客户端管理等功能,而且它本身通知支持轮询和websocket两种方式,所以选它省事省时。3.存储的选择临时令牌存放在redis中,用来进行websocket连接时的验证,防止恶意的攻击,用户数据放在mysql中。4.源码管理工具和构建工具的选择使用Git作为代码管理工具,方便进行代码持续迭代和发布上线,使用Gitlab作为源码服务器端,可以进行代码的合并管理,使整个代码质量更容易把控。采用Maven做为构建工具,并使用nexus创建自己的Maven私服,用来进行基础服务版本的管理和发布。搭建Sonar服务器,Maven中集成Sonar插件进行代码质量的自动化检测。5.持续构建和部署工具采用Docker部署的方式,快速方便。采用Jekins做持续构建,可以根据git代码变更快速的打包上线。模块功能设计根据《微服务架构:如何用十步解耦你的系统?》中微服务解耦的设计原则:1.将Websocket作为服务独立出来只用来进行数据的通信,保证其功能的单一性,独立对外提供SocketApi接口,通过Dubbo的方式来调用其服务。2.将用户功能作为服务独立出来,进行用户注册和登录的功能,并对外提供UserApi接口,通过Dubbo的方式来调用。3.对外展示的功能包括页面和静态文件都统一到WebServer模块中,需要操作用户数据或者需要使用Websocket进行通信的都统一使用Dubbo调用。4.对于基本的权限认证和动态负载均衡都统一放到Gateway模块中,Gateway可以实现http的负载均衡和websocket的负载均衡。5.如果访问量非常大时,就考虑将Gateway分开部署,单独进行http服务和websocket服务,将两者的流量解耦。6.webserver端访问量大时,可以考虑将静态页面发布到CDN中,减少该模块的负载。开发规范解耦公共服务指定良好的开发管理规范,使用Git做好版本代码的分支管理,每个需求迭代使用单独的分支,保证每次迭代都可以独立上线,Maven私服中每次SocketApi和UserApi的升级都要保留历史版本可用,Dubbo服务做好多版本的兼容支持,这样就能将基础公共的服务进行解耦。总结微服务的引入不仅仅是带来了好处,同时也带来了系统的复杂性,不能只从框架和代码的角度来考虑微服务架构的落地,更要从整个管理的角度去考虑如何括地,否则使用微服务开发只会带来更多麻烦和痛苦。长按二维码,关注公众号煮酒科技(xtech100),输入数字11返回代码哟。

December 10, 2018 · 1 min · jiezi

构筑敏捷能力中心,打造下一代数字银行“操作系统”!

摘要: 构筑敏捷能力中心,打造下一代数字银行“操作系统”!小蚂蚁说:近年来,越来越多国内外领先银行全力投入数字化转型。数字化转型是技术与商业模式的深度融合,最终结果是商业模式的变革。银行数字化转型是一个逐步递进的旅程,敏捷能力中心的打造如同建设下一代数字银行“操作系统”,在银行数字化之旅中具有里程碑意义。银行业已进入全面数字化时代,数字化转型将从改善客户连接的1.0时代,进入到以敏捷能力为核心的数字化2.0时代。蚂蚁金服认为,打破过去独立分散的系统架构,铸造以分布式平台为支撑的金融敏捷能力中心,将成为银行机构全面数字化转型、提升客户服务能力的重要引擎。2018年11月29至30日,由《当代金融家》全媒体集团、鸿儒金融教育基金、蚂蚁金服主办的2018年(第七届)中国中小银行发展高峰论坛在广州举办,论坛围绕新时代中小银行金融科技与风险防控展开,来自监管层、股份制银行、国内城商行、农商行代表及相关机构领约300位专业人士出席峰会。在演讲中指出,银行数字化转型是一个逐步递进的旅程,敏捷能力中心的打造如同建设下一代数字银行“操作系统”,在银行数字化之旅中具有里程碑意义。他解释道,“敏捷能力中心从根本上解决企业的管理效率,以及服务终端、前台创新的问题,可助力银行不断快速响应、探索、挖掘、引领用户的需求,提升用户体验,降低服务成本,在全面数字化时代领先行业。”曾经,金融行业由于对可靠性和风险管理的要求高于一般行业,而后台修改的成本和风险较⾼,所以驱使他们会尽量选择保持后台系统稳定性的IT建设模式,把大量的业务逻辑(业务能力)直接部署在前台系统中,形成厚重的前台系统。这样便形成业务联系彼此割裂的状态,并未能很好地支撑前台快速创新响应用户的需求,降低了用户体验。随着IT技术的不断发展,曾经微服务、DevOps等技术也给出了技术上实现敏捷能力的“银弹”。但局部的方案未能从根本上解决全行级敏捷问题,银行的业务部门、研发中心、数据运维中心各自都是拿着拼图的一部分寻找方向。峰会上,蚂蚁金服结合自己的实践,从自身的实践总结出覆盖技术、数据、业务多个维度的敏捷能力中心,与广大银行业伙伴共享,以助力各家银行机构打造自身的“数字化操作系统”。据介绍,数字化时代敏捷能力中心包括以下几个方面:敏捷技术中心:把分布式架构体系涉及到的研发、测试、治理、运维、风险形成完整的支持全行应用的技术平台。除此之外还有三地五中心的灾备架构、免疫架构、防御资金安全和不断地、主动地发现故障等。这些技术能力体现蚂蚁技术敏捷中心不断追求的在分布式架构下的敏捷与自愈能力,将“不确定性变为确定性”。敏捷智能中心:把数据智能计算、数据研发、数据资产有机组合形成全行统一数据平台和金融智能应用,例如针对全行风险八大领域,构建全行级风险平台,实现风险管理统一化、风险技术平台化、风险数据规划化。敏捷业务中心:沉淀分布式架构下组件化、服务化的业务核心能力,向上提供平台化领域服务、开放式的编程接口来帮助快速构建存贷汇、互金等各类业务产品;同时封装了金融级分布式架构中的技术复杂性,降低分布式转型的学习曲线,提升分布式转型速度。纵观银行数字化发展历程,数字化1.0从移动端开始,着力于改善客户连接,提升业务触达能力。而刘伟光分析道,到数字化2.0时代,银行等企业机构重点在于通过分布式架构,获得数字化原生企业的标准技术栈能力,来建立与数字化原生企业相对标的三大核心竞争力:技术敏捷能力、数据智能驱动能力、业务敏捷能力,打造面向下一代数字化转型的数字银行“操作系统”。基于这些能力,银行可在未来的数字化3.0时代,建设多方位的生态合作新型银行模式:对内进行业务场景接入,对外通过API Bank向企业开放、建设基于API的应用生态市场模式,构建基于金融组件化操作系统的开放生态银行。本文作者:平生栗子阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 5, 2018 · 1 min · jiezi

一次性能优化:吞吐量从1提升到2500

性能优化,简而言之,就是在不影响系统运行正确性的前提下,使之运行地更快,完成特定功能所需的时间更短。压测也是检验一个架构设计是否合理的一个重要方法。项目介绍这个项目是一个线下支付的交易系统,使用线下设备发起支付。项目使用SpringMVC+Dubbo的微服务开发模式,其中SpringMvc作为Web端部署在tomcat上对外提供rest服务,其他模块使用dubbo开发,SpringMVC调用dubbo服务完成业务功能。优化目的这一次的性能优化,目的是在不调整业务逻辑的情况下通过压力测试的方式测试下单时接口的性能能达到多少,如果有性能问题,就要在不修改业务逻辑的情况下通过优化各项参数的方式(包括JVM优化、数据库连接数和Dubbo连接数)来提升整体性能。压测前的准备压力测试策略采用循序渐进的方式,逐渐增加并发量的方式,先以1个并发开始,慢慢增加,当达到瓶颈的时候就进行参数调整和优化。建立压测分支压测优化过程中,可能随时需要调整配置参数,可能会对一些配置参数进行修改或者对公共代码进行优化。为了不让其他研发人员的开发受到干扰,在git上基于release分支建立了feature_stress分支,专门用来压测过程中,参数配置调优使用,不影响其他研发人员的开发。搭建压测环境为了不不影响研发和测试人员的工作,单独申请了三台4C32G的虚拟机进行压力测试,一台部署tomcat,一台部署dubbo服务,一台部署mysql。为什么只申请单机部署的方式压测呢?因为本次测试的目的是看单台服务器的性能情况,优化的目的是将单台服务器的性能最大化。准备测试脚本本次测试选用jmeter作为测试工具进行压力测试,由测试人员模拟线下支付的流程写好测试脚本。初步压测很保守的,从1个并发开始压测,测试结果让人非常的惊喜,压测开始几分钟后,就出现大量的连接失败,无法继续测试。出现大量的内存溢出的异常。没出现异常时的吞吐量达到了1req/s。同时,通过jconsole控制台监控tomcat,发现其线程数最高到了2万多个。问题分析这个异常是创建本地线程失败抛出的异常,为什么有这么大量的线程呢?不合常理呀!于是查看对应的代码,原来这是一个自定义的一个人日志Appender,在这个Appender里使用了线程池,这个Appender本来的目的是使用多线程提升日志性能,并且将所有的日志都收集到一个文件中。代码类似如下:log4j.properties中直接将新的Appender添加到了rootLogger下:初步优化通过以上代码和日志配置文件就能看出来,每次日志输出都会创建线程,这就是线程为什么越来越多,最后导致无法创建新的本地线程的原因。为了不影响现有的功能,将LogAppender类append方法中的线程池创建的部分变成了类的属性,并固定只用8个线程:提交代码重新部署压测环境,再进行压测,吞吐量马上就上来了,达到了1700req/s,][7]深入调优经过上面的优化之后,整体的性能还不是很高,经过jconsole监控发现,线程数还是很高,虽然没有2万那么多了,但还是有3000多的线程,这么多的线程根本无法发挥机器的性能,时间都浪费在线程切换上了,通过查看线程栈发现大量的线程都是dubbo连接的线程,为什么如此之多呢?查看dubbo的配置文件,consumer的链接数都设置成了1000,于是将所有dubbo的consumer连接数均改为了64。同时将log4j.properties中配置了控制台输出的都关闭了。最终的优化后的测试结果,最高达到了2600req/s。总结性能优化需要从几个方面考虑:CPU是否有瓶颈,本项目没有大量的计算,所以CPU没有瓶颈。IO是否是瓶颈,线程太多或者连接太多都是瓶颈,本项目中并发时创建了大量的线程,达到了服务器的最高可用的连接数,导致内存溢出了,创建太多的线程也会让CPU把时间都浪费在线程切换上了。生产环境不要使用控制台输出,因为控制台输出是同步的,输出太多会对性能有很大的影响。如果出现吞吐量小的情况可以输出线程栈,看看到底是block在哪里了,是调用服务时间长还是读写数据库时间长。———— / END / ————

December 4, 2018 · 1 min · jiezi

微服务架构:如何用十步解耦你的系统?

导言:耦合性,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。高内聚低耦合,是软件工程中的概念,是判断设计好坏的标准,主要是面向对象的设计,主要是看类的内聚性是否高,耦合度是否低。SpringCloud和Dubbo都是现在比较成熟的微服务框架,如何使用两者构建搭建你的微服务系统呢?他们是如何将你的系统解耦的?又是怎么解耦的呢?请听我慢慢道来:第一步,解耦现有模块将现有耦合在一起的模块进行重新的设计,设计成可以独立部署的多个模块,使用微服务框架很容易做到,成熟的示例代码都特别多,这里不再多讲。下面是我的微服务实现的一个架构设计图。第二步,抽取公共模块架构设计原则之一就是反向依赖,只从上往下依赖,所以,我们将公共的重复功能的模块抽取出来。必须强调一点的是,公共模块必须足够的功能单一,不能有其他业务的逻辑判断在里面。在整个模块依赖关系里,应该是一棵树状结构的关系图,而不是一个网状的关系图。1)做好代码控制笔者之前就碰到过这种问题,模块划分完了,当需求变更的时候,研发人员根本不管是不是公共模块,只要能快速完成任务,哪里改的快就在哪里改。因此,这个需要内部要做好代码的权限管理,不应该开放所有的提交代码的权限给所有的人。后来我就将公共模块的合并代码的权限收回了,合并代码需要先提交申请,代码review过才能合并代码。这就保证了公共模块代码的功能单一。2)做好版本管理公共模块被多个模块模块使用,任何代码的修改都可能会导致到正在使用的模块无法使用。这个就需要做好各个模块的版本管理,我是使用maven进行版本管理的,定义一个总的父pom项目来进行各个模块的版本管理,任何被其他模块使用的开发包都要在父pom里进行版本管理。当新的需求来了以后,需要对公共模块进行修改时,要更新模块的版本号,同时更新父pom的版本号,需要使用公共模块新功能的模块就修改父pom的版本号,不需要使用公共模块新功能的模块就不用修改父pom的版本号,这样公共模块的新老版本都能使用,即使出现问题,也只会影响到使用新版本的模块。第三步,解耦迭代需求现在的代码迭代速度快,同时会面对多个需求,有的需求紧急,有的需求不紧急,而且紧急程度可能随时会调整,如果将所有的需求都放在一个分支,当只想上线其中几个需求的时候发现无法将不上线需求的代码拆分出来,是不是很尴尬,即使能拆分出来,代码修改过以后又要重新进行部署测试,很费时费力,所以要针对不同的需求重新建立研发分支,这样就将不同需求的分支解耦,保证想上哪个就上哪个,需要上多个需求的就将分支合并上线。第四步,配置解耦为每个模块每个环境配置一个配置文件,这样就可以把不同的环境的配置解耦,不用每次上线都更新一次。但是如果需要修改数据库配置,还是需要重新部署重启应用才能解决。使用微服务的配置中心就能解决这个问题了,比如使用ZooKeeper作为SpringCloud的配置中心,修改ZooKeeper中的节点数据就可以实时更新配置并生效。第五步,权限解耦当采用微服务架构把原来的系统拆分成多个系统以后,你会发现原来简单的问题,现在变的复杂了,比如功能的权限控制,原来是跟业务代码放到一起,现在如果每个业务模块都有功能权限的代码,将是一件非常麻烦的事情。那么解决办法就是将权限功能迁移出来,恰巧使用SpringCloudGateway就能完成这件事情,SpringCloudGateway能够进行负载均衡,各种路由拦截,只要将原来的权限控制代码迁移到Gateway里实现以下就可以了,权限配置管理界面和代码逻辑都不用变。如果是API接口呢,就需要将安全验证等功能放在Gateway里实现就好了。第六步,流量解耦当你的系统访问量越来越大的时候,你会发现每次升级都是一件非常麻烦的事情,领导会跟你说这个功能忙时不能停机影响用户使用呀,只能半夜升级呀,多么痛快的事情啊。有的时候运营人员也会发现,怎么我的后台访问怎么这么慢?问题出在哪里呢?问题就出在,所有的模块都用了一个Gateway,多端同时使用了相同的流量入口,当在举行大促时,并发量非常高,带宽占用非常大,那么其他的功能也会跟着慢下来。不能在举行大促时发券时,我线下支付一直支付不了,这是非常严重的事故了,客服电话会被打爆了。所以,必须要对流量进行拆分,各个端的流量不能相互影响,比如APP端、微信端、运营后台和商户后台等都要分配独立的Gateway,并接入独立的带宽,对于流量大的端可以使用弹性带宽,对于运营后台和商户后台就比较小的固定的带宽即可。这样就大大降低了升级时的难度,是不是再上线时就没那么紧张了?第七步,数据解耦系统刚上线的时候,数据量不大,所有的模块感觉都挺好的,当时间一长,系统访问量非常大的时候会发现功能怎么都变慢了,怎么mysql的cpu经常100%。那么恭喜你,你中招了,你的数据需要解耦了。首先要模块间数据解耦,将不同模块使用独立的数据库,保证各模块之间的数据不相互影响。其次就是冷热数据解耦,同一个模块运行时间长了以后也会积累大量的数据,为了保证系统的性能的稳定,要减少因为数据量太大造成的性能降低,需要对历史数据进行定期的迁移,对于完整数据分析汇总就在其他的库中实现。第八步,扩容解耦一个好的架构设计是要有好的横向扩展的能力,在不需要修改代码只通过增加硬件的方式就能提高系统的性能。SpringCloud和Dubbo的注册中心天生就能够实现动态添加模块的节点,其他模块调用能够实时发现并请求到新的模块节点上。第九步,部署解耦互联网开发在于能够快速的试错,当一个新的版本上线时,经常是需要先让一部分用户进行测试一下,这就是传说中的灰度发布,同一个模块先部署升级几台服务器到新版本,重启完成后流量进来以后,就可以验证当前部署的这几台服务器有没有问题,就继续部署其他的节点,如果有问题马上回滚到上一个版本。使用SpringCloudGateway的WeighRouterFilter就能实现这个功能。第十步,动静解耦当同一个模块的瞬间有非常高并发的时候,对,就是说的秒杀,纯粹的流量解耦还是不够,因为不能让前面的流量冲击后面真正的下单的功能,这个时候就需要更细的流量解耦,要将静态文件的访问通通抛给CDN来解决,动态和静态之间是通过定时器来出发的,时间未到之前一直刷新的是静态的文件,当时间到了之后,生成新的js文件,告诉静态页面可以访问下单功能了。总结在模块划分时,要遵循“一个模块,一个功能”的原则,尽可能使模块达到功能内聚。事实上,微服务架构短期来看,并没有很明显的好处,甚至短期内会影响系统的开发进度,因为高内聚,低耦合的系统对开发设计人员提出了更高的要求。高内聚,低耦合的好处体现在系统持续发展的过程中,高内聚,低耦合的系统具有更好的重用性,维护性,扩展性,可以更高效的完成系统的维护开发,持续的支持业务的发展,而不会成为业务发展的障碍。———— / END / ————

December 4, 2018 · 1 min · jiezi

微服务架构可视化平台实践

为什么需要架构可视化随着企业进行微服务架构改造,系统架构复杂度越来越高,架构变化日益频繁,微服务改造后的实际架构模型可能与预期已经产生了巨大差异,架构师或系统运维人员很难准确记忆所有资源实例的构成和交互情况;其次,系统架构在动态演化过程中可能引入了一些不可靠的因素,比如弱依赖变强依赖、局部容量不足、系统耦合过重等,给系统的稳定性带了极大的安全隐患。所以我们每次在面对系统改造、业务大促以及稳定性治理工作之前,都会通过梳理架构图的方式,呈现系统架构中个组件之间的交互方式,架构可视化能够清晰的协助我们识别架构中存在的问题以及建立高可用的系统。架构可视化后,可以给我们带来以下几点但不局限于此的优势:确定系统边界一张好的架构图,应该明确系统所包含的各个组件以及各个组件之间的核心调用关系,这些组件的集合就是系统的处理边界,系统架构的边界在一定程度上也反映了业务域的边界。架构问题识别基于高可用的架构准则,结合可视化的架构图,可以评估架构可能存在的安全风险,比如系统在容灾、隔离以及自愈维度下的健壮性。其次,一些架构链路可视化工具(比如鹰眼)在实际工作中确实大大提高了开发者排查与定位问题的效率。提高系统可用性有了系统架构的上下游依赖关系图,在故障发生时,开发人员可以借助依赖数据快速定位到问题的来源,极大缩短问题修复时间(MTTR)。借助架构图,我们还可以梳理出系统中存在的强弱依赖,在业务高峰期对弱依赖进行降级,或者针对系统依赖的各个组件进行故障模拟,以评测系统整体在面对局部故障的可靠性。常见架构可视化的做法我们熟知的架构图是静态的停留在PPT上的,很多时候我们的架构已经发生了非常大的变化,但是我们还在使用那张看上去很经典却早已过时的架构图。长时间使用与实际架构不符的架构图对线上架构的认知的危害是巨大的,我们需要在脑海中不断更新对系统架构的视图,以保持对系统架构的敏感度。每年的大促或者重大系统改造成为我们梳理系统架构、对架构进行重新认知的机会,此刻我们需要通过各种工具查看系统的各个组件分布以及不同组件的内部与外部的依赖关系,这种梳理架构图的方法是最常用的方式,权且称之为“手工绘制法”。手工经常干的事情,就有追求效率的同学使用计算机系统带来的自动化手段帮助自己做这件事情,比如我们常常看到的基于数据埋点的微服务可视化解决方案,这类架构可视化手段通常在分布式追踪、APM等监控领域使用较多,下图为某APM产品提供的应用维度架构可视化方案:我们称这种可视化方式为“埋点式感知法”,架构组件的识别是依赖关键的核心类检测与埋点,此种方案存在以下弊端:语言相关性:只要是系统埋点,与语言相关的特征基本就拜托不了,需要针对不同语言提供不同的依赖包;不易维护:因为是对核心类的检测,当组件包做了重大变更时,需要同步变更;不易扩展:因为是客户端识别方案,客户端一旦开放出去,新组件的支持只能等待用户更新组件;规模受限:客户端识别的另一个缺点是算法受限,服务端进行识别,可以借助大数据分析等手段更有效准确的识别;还有一种自动化架构感可视化方法,我们称之为“无界架构感知”,是一种语言无关性的架构识别方案,其采用采集用户主机上的进程和容器的元数据、监控数以及网路数据的最最基础的数据,在服务端构建架构图。我们设计架构可视化的理念为了最大限度上降低用户进行架构可视化的成本,我们采用了无界架构感知-应用无侵入的方式微服务进行可视化,通过采集进程数据与网络调用数据,构建进程间的网络调用关系,构建微服务的架构信息。用户只需要安装我们AHAS Agent探针,即可完成架构可视化操作;对于阿里云云原生系统,我们提供了自动化安装方式,而无需登录机器。核心本质软件架构可视化的核心点是寻找在软件体系结构中有意义和有效的元素视图以及这些元素之间的关系。我们认为一款优秀的软件架构可视化产品应该帮助用户排除掉不重要的信息,给用户呈现出对他们有价值的视图,特别是在微服务架构下庞大而复杂的调用关系链场景中。这里面的核心点是__有意义__和__有效__,要做到这两点,首先需要识别什么是有意义和有效的元素和关系,我们在此领域做的事情归纳起来就是“识别”,识别机器上的每个进程是什么,发生的网络调用远端是什么,唯有知晓了这些元素是什么我们才有理由和依据来判断是否对用户有意义以及其在用户架构中的重要程度。在梳理了大量架构图,我们发现用户关心的架构元素主要分为三类:自己的应用服务;应用对外部的资源依赖;服务器本身的信息。 应用对外部资源的依赖通常以其它应用和通用中间件或者存储服务两种形式存在。故我们将需要识别的进程分为:应用服务和常见的组件服务(比如redis、mysql等),这些组件服务又分为用户自建的服务和使用公有云提供的服务,特别是对于Cloud Native应用来说,云服务的识别显得格外重要。目前,我们提供了20种阿里云云服务的识别以及包含mysql、redis、Tomcat等常见的21种三方服务组件,此组件库还在不断扩张中,目的就是最大限度的知晓架构中的元素到底是什么。架构分层我们同样认为架构可视化的有效性跟人的认知层次有关,架构可视化的重点是确定该工具是否更好的支持自顶向下方法、自下而上方法或者两者的结合。开发者更关心应用维度上的架构,架构师或者管理者更关心整体系统架构。所以需要针对不用的使用者提供不同层次的架构可视化视角。理想的架构图需要支持宏观维度以及不断下钻下的微观视角,我们对架构进行了分层设计,目前分为进程层、容器层和主机层,后期我们可能会继续上扩或者下钻支持地域层或者服务层。架构回溯没有哪个系统的架构是一成不变的,系统架构会随着系统的版本迭代不断进行演化。所以对架构可视化操作,还需要具备随着时间的推移可对架构信息进行自动更新已经回溯的能力。在我们提供的架构感知产品中默认架构图会随着时间自动刷新,同时支持对历史的回溯,你可以选择历史中的某一刻查看架构信息,比如,重大版本的变更时,发布前与发布后的系统架构是否发生了违背一些高可用原则的问题,抑或排查是否出现了不该有的依赖问题。可见可得架构可视化解决了可见的问题,但当我们从架构图中发现了问题需要解决时,架构图还应该给我们提供便利的可交互操作入口,让我们可以完成问题发现与解决的闭环。比如通过架构感知监控到了某个应用的流量非常大,我们需要对应用进行限流或者预案,那么通过架构图,我们应该是可以完成我们期望执行的操作。在架构图中融入可以交互的运维操作,让我们从看到到操作,再到问题恢复后体现在图中,这就像计算机发展史上从命令行视图到窗口视图的转变。我们对架构可视化的定位__架构可视化不是目的,只是实现系统高可用性的手段__。借助架构感知采集到的架构数据,在识别了用户使用的组件(我们对mysql、redis、mq等的统称)后,我们借助这些组件以及与组件匹配的故障库,可以给用户自动推荐这些组件可能遇到的故障,配合我们提供的评测服务让用户更方便地对组件进行各种故障的模拟与演练,以提高系统的健壮性。其次,通过架构感知识别Java Application 应用,如果发现其负载较高,配合我们提供的限流降级(阿里巴巴开源的Sentinel商业版)功能,为服务的持续可用性保驾护航。我们对AHAS的定位是一款数据分析型的高可用保障产品,帮助云原生架构系统实现高可用能力的提升。架构可视化是我们给用户提供的高效运维和管控的窗口,我们期望通过丰富的云原生数据体系配合架构图的可视化以及可操作性,建立起以应用为中心的运维一体化平台。在未来,我们会加强与其它云服务的集成,比如监控、容器服务,以丰富架构感知的数据维度;其次,会在数据的深度挖掘和智能化消费上投入更多精力,真正让数据成为企业的核心价值,让数据成为保障业务的稳定性的利器。本文作者:心远阅读原文本文为云栖社区原创内容,未经允许不得转载。

November 30, 2018 · 1 min · jiezi

如何在一分钟内实现微服务系统下的架构可视化

为什么需要架构可视化随着企业进行微服务架构改造,系统架构复杂度越来越高,架构变化日益频繁,微服务改造后的实际架构模型可能与预期已经产生了巨大差异,架构师或系统运维人员很难准确记忆所有资源实例的构成和交互情况;其次,系统架构在动态演化过程中可能引入了一些不可靠的因素,比如弱依赖变强依赖、局部容量不足、系统耦合过重等,给系统的稳定性带了极大的安全隐患。所以我们每次在面对系统改造、业务大促以及稳定性治理工作之前,都会通过梳理架构图的方式,呈现系统架构中个组件之间的交互方式,架构可视化能够清晰的协助我们识别架构中存在的问题以及建立高可用的系统。架构可视化后,可以给我们带来以下几点但不局限于此的优势:确定系统边界一张好的架构图,应该明确系统所包含的各个组件以及各个组件之间的核心调用关系,这些组件的集合就是系统的处理边界,系统架构的边界在一定程度上也反映了业务域的边界。架构问题识别基于高可用的架构准则,结合可视化的架构图,可以评估架构可能存在的安全风险,比如系统在容灾、隔离以及自愈维度下的健壮性。其次,一些架构链路可视化工具(比如鹰眼)在实际工作中确实大大提高了开发者排查与定位问题的效率。提高系统可用性有了系统架构的上下游依赖关系图,在故障发生时,开发人员可以借助依赖数据快速定位到问题的来源,极大缩短问题修复时间(MTTR)。借助架构图,我们还可以梳理出系统中存在的强弱依赖,在业务高峰期对弱依赖进行降级,或者针对系统依赖的各个组件进行故障模拟,以评测系统整体在面对局部故障的可靠性。常见架构可视化的做法我们熟知的架构图是静态的停留在PPT上的,很多时候我们的架构已经发生了非常大的变化,但是我们还在使用那张看上去很经典却早已过时的架构图。长时间使用与实际架构不符的架构图对线上架构的认知的危害是巨大的,我们需要在脑海中不断更新对系统架构的视图,以保持对系统架构的敏感度。每年的大促或者重大系统改造成为我们梳理系统架构、对架构进行重新认知的机会,此刻我们需要通过各种工具查看系统的各个组件分布以及不同组件的内部与外部的依赖关系,这种梳理架构图的方法是最常用的方式,权且称之为“手工绘制法”。手工经常干的事情,就有追求效率的同学使用计算机系统带来的自动化手段帮助自己做这件事情,比如我们常常看到的基于数据埋点的微服务可视化解决方案,这类架构可视化手段通常在分布式追踪、APM等监控领域使用较多,下图为某APM产品提供的应用维度架构可视化方案:我们称这种可视化方式为“埋点式感知法”,架构组件的识别是依赖关键的核心类检测与埋点,此种方案存在以下弊端:语言相关性:只要是系统埋点,与语言相关的特征基本就拜托不了,需要针对不同语言提供不同的依赖包;不易维护:因为是对核心类的检测,当组件包做了重大变更时,需要同步变更;不易扩展:因为是客户端识别方案,客户端一旦开放出去,新组件的支持只能等待用户更新组件;规模受限:客户端识别的另一个缺点是算法受限,服务端进行识别,可以借助大数据分析等手段更有效准确的识别;还有一种自动化架构感可视化方法,我们称之为“无界架构感知”,是一种语言无关性的架构识别方案,其采用采集用户主机上的进程和容器的元数据、监控数以及网路数据的最最基础的数据,在服务端构建架构图。架构可视化还能怎么做为了最大限度上降低用户进行架构可视化的成本,我们采用了应用无侵入的方式微服务进行可视化,通过采集进程数据与网络调用数据,构建进程间的网络调用关系,构建微服务的架构信息。用户只需要安装我们AHAS Agent探针,即可完成架构可视化操作;对于阿里云云原生系统,我们提供了自动化安装方式,而无需登录机器。如何让架构可视化更有效我们同样认为架构可视化的有效性跟人的认知层次有关,架构可视化的重点是确定该工具是否更好的支持自顶向下方法、自下而上方法或者两者的结合。开发者更关心应用维度上的架构,架构师或者管理者更关心整体系统架构。所以需要针对不用的使用者提供不同层次的架构可视化视角。理想的架构图需要支持宏观维度以及不断下钻下的微观视角,我们对架构进行了分层设计,目前分为进程层、容器层和主机层,后期我们可能会继续上扩或者下钻支持地域层或者服务层。下图为一台阿里云ECS部署了微服务应用安装AHAS探针之后的可视化三层架构界面:应对架构的可变性没有哪家科技公司的系统架构是一成不变的,系统架构会随着系统的版本迭代不断进行演化。所以对架构可视化操作,还需要具备随着时间的推移可对架构信息进行自动更新已经回溯的能力。在我们提供的架构感知产品中默认架构图会随着时间自动刷新,同时支持对历史的回溯,你可以选择历史中的某一刻查看架构信息,比如,重大版本的变更时,发布前与发布后的系统架构是否发生了违背一些高可用原则的问题,抑或排查是否出现了不该有的依赖问题。架构可视化的核心软件架构可视化的核心点是寻找在软件体系结构中有意义和有效的元素视图以及这些元素之间的关系。我们认为一款优秀的软件架构可视化产品应该帮助用户排除掉不重要的信息,给用户呈现出对他们有价值的视图,特别是在微服务架构下庞大而复杂的调用关系链场景中。这里面的核心点是有意义和有效,要做到这两点,首先需要识别什么是有意义和有效的元素和关系,我们在此领域做的事情归纳起来就是“识别”,识别机器上的每个进程是什么,发生的网络调用远端是什么,唯有知晓了这些元素是什么我们才有理由和依据来判断是否对用户有意义以及其在用户架构中的重要程度。架构可视化中的元素识别在梳理了大量架构图,我们发现用户关心的架构元素主要分为三类:1. 自己的应用服务;2. 应用对外部的资源依赖;3. 服务器本身的信息。 应用对外部资源的依赖通常以其它应用和通用中间件或者存储服务两种形式存在。故我们将需要识别的进程分为:应用服务和常见的组件服务(比如Redis、MySQL等),这些组件服务又分为用户自建的服务和使用公有云提供的服务,特别是对于Cloud Native应用来说,云服务的识别显得格外重要。目前,我们提供了20种阿里云云服务的识别以及包含MySQL、Redis、Tomcat等常见的21种三方服务组件,此组件库还在不断扩张中,目的就是最大限度的知晓架构中的元素到底是什么。图中展示了通过识别服务识别出来的Nginx、Redis组件以及阿里云中的Mysql服务和AHAS服务有了架构可视化还能做什么架构可视化不是目的,只是实现系统高可用性的手段。借助架构感知采集到的架构数据,在识别了用户使用的组件(我们对MySQL、Redis、MQ等的统称)后,我们借助这些组件以及与组件匹配的故障库,可以给用户自动推荐这些组件可能遇到的故障,配合我们提供的评测服务让用户更方便地对组件进行各种故障的模拟与演练,以提高系统的健壮性。其次,通过架构感知识别Java Application 应用,如果发现其负载较高,配合我们提供的限流降级(阿里巴巴开源的Sentinel商业版)功能,为服务的持续可用性保驾护航。借助架构感知进行系统限流配置我们对AHAS的定位是一款数据分析型的高可用保障产品,帮助云原生架构系统实现高可用能力的提升。架构可视化是我们给用户提供的高效运维和管控的窗口,我们期望通过丰富的云原生数据体系配合架构图的可视化以及可操作性,建立起以应用为中心的运维一体化平台。在未来,我们会加强与其它云服务的集成,比如监控、容器服务,以丰富架构感知的数据维度;其次,会在数据的深度挖掘和智能化消费上投入更多精力,真正让数据成为企业的核心价值,让数据成为保障业务的稳定性的利器。本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。

November 30, 2018 · 1 min · jiezi

墙裂推荐:搜云库技术团队,整理一年的技术干货

今天整理了一下近大半年以来的一些文章,和我的预期一样,很多文章我都忘记自己曾经写过了,这个记录的过程让我也有了新的理解。希望大家,收藏,点赞,加转发。面试必备面试必备:深入Spring MVC DispatchServlet 源码分析面试必备:一文读懂Spring AOP面向切面编程面试必备:理解JWT鉴权的应用场景及使用建议面试必备:浅谈偏向锁、轻量级锁、重量级锁面试必备:一致性哈希算法的理解与实践面试必备:深入理解为什么要设计幂等性的服务面试必备:面试官最爱的volatile关键字面试必备:Rabbitmq延迟队列实现定时任务面试必备:HashMap源码解析JDK8面试必备:Dubbo服务消费者调用过程面试必备:Dubbo服务提供者发布过程面试必备:Dubbo中暴露服务的过程解析面试必备:Java中transient关键字的作用面试必备:JavaSQL注入危害这么大,该如何来防止呢?面试必备:Java虚拟机运行时数据区面试必备:Redis之数据持久化RDB与AOF面试必备:Redis持久化RDB和AOF优缺点是什么面试必备:Redis集群下的RedLock算法(真分布式锁) 实践面试必备:Redis服务器被攻击后该如何安全加固面试必备:Zookeeper的Leader选举过程面试必备:ZooKeeper和CAP理论及一致性原则面试必备:MySQL从删库到恢复,还用跑路吗?面试必备:MySQL/InnoDB中,乐观锁、悲观锁、共享锁、排它锁、行锁、表锁、死锁概念的理解面试必备:MySQL常用30种SQL查询语句优化方法面试必备:MySQL InnoDB B+树索引和哈希索引的区别? MongoDB 为什么使用B-树?面试必备:常用的分布式事务解决方案介绍有多少种?面试必备:对称加密,非对称加密,公钥和私钥面试必备:如何加密传输和存储用户密码Java并发Java并发:接口限流算法:漏桶算法&令牌桶算法Java并发:深入浅出AQS之共享锁模式源码分析Java并发:深入浅出AQS之独占锁模式源码分析Java并发:了解无锁CAS就从源码分析Java并发:分布式应用限流实践Java并发:Semaphore信号量源码分析Java并发:CAS源码分析面试题面试题:百度、腾讯、阿里、谷歌 面试题视频详解合集面试题:2018最新JAVA算法/数据结构面试题和答案面试题:70道Spring面试题与答案面试题:2018最新Redis面试题与答案面试题:50道多线程面试题与答案(二)面试题:50道多线程面试题与答案(一)面试题:Spring常见的一些面试题与答案面试题:300道Java面试题与答案面试题:40道常见面试题与答案面试题:20道数据库面试题与答案架构架构:应用消息中间件设计可以解决哪些实际问题?架构:搭建大众点评CAT实时应用监控平台架构:如何实现一个TCC分布式事务框架的一点思考架构:Dapper大规模分布式系统的跟踪系统架构:Dubbo 整合 Pinpoint 做分布式服务请求跟踪架构:理解大型分布式架构的演进历史、技术原理、最佳实践架构:解密 Redis 助力双十一背后电商秒杀系统架构:瞬间点击量过万,Redis热点Key的5种解决方案架构:通过案例读懂 RESTful 架构风格架构:一文读懂Apache Flink架构及特性分析架构:大数据推荐系统实时架构和离线架构架构:携程:日处理20亿数据,实时用户行为架构实践架构:什么是微服务架构架构:有赞服务化架构演进架构:微服务架构下静态数据通用缓存机制架构:小型系统如何“微服务”开发架构:Oracle推出开源轻量级 Java 微服务框架 Helidon搭建搭建:网站配置免费的HTTS证书搭建:Apache RocketMQ 单机环境搭建:MongoDB分片(sharding) / 分区 / 集群环境搭建:MongoDB 的安装与详细使用(二)搭建:MongoDB 的安装与详细使用(一)搭建:SolrCloud 集群服务搭建:Solr 单机服务搭建:RabbitMQ 3.6 单机服务搭建:RabbitMQ 3.6 集群服务搭建:离线部署 CDH 5.12.1 及部署Hadoop集群服务搭建:Mycat 读写分离数据库分库分表中间件及简单使用DockerDocker Compose 1.18.0 之服务编排详解Docker 部署 SpringBoot 项目整合 Redis 镜像做访问计数DemoDocker Registry企业级私有镜像仓库Harbor管理WEB UI, 可能是最详细的部署Docker Registry Server 搭建,配置免费HTTPS证书,及拥有权限认证、TLS 的私有仓库Docker Hub 仓库使用,及搭建 Docker RegistryDocker 容器常用操作命令讲解Docker 安装在之初窥 Dockerfile 部署 NginxSpring CloudSpring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息总线集成(RabbitMQ)Spring Cloud(十)高可用的分布式配置中心 Spring Cloud Config 中使用 RefreshSpring Cloud(九)高可用的分布式配置中心 Spring Cloud Config 集成 Eureka 服务Spring Cloud(八)高可用的分布式配置中心 Spring Cloud ConfigSpring Cloud(七)服务网关 Zuul Filter 使用Spring Cloud(六)服务网关 zuul 快速入门Spring Cloud(五)断路器监控(Hystrix Dashboard)Spring Cloud(四) 服务提供者 Eureka + 服务消费者 FeignSpring Cloud(三) 服务提供者 Eureka + 服务消费者(rest + Ribbon)Spring Cloud(二)Consul 服务治理实现Spring Cloud(一)服务的注册与发现(Eureka)Spring BootSpring Boot 中使用 RabbitMQSpring Boot 中使用 RocketMQSpring Boot 中使用 SolrCloudSpring Boot 中使用 MongoDB 增删改查Spring Boot 中使用 Dubbo 详解Spring Boot 中使用 LogBack 配置Spring Boot 中使用 Docker镜像push到DockerHub上Spring Boot 写的一个java开源图床其他的震惊!面对他人提问某著名程序员居然这样回复爆出惊天内幕!这就是java的优雅停机如何招聘完美的以太坊开发者ElasticSearch优化会员列表搜索软件做异常测试?必知的22个测试点总结!还没用上 JDK 11吧,JDK 12 早期访问构建版使用Mybatis 一级缓存清理无效引起的源码走读程序猿的十二条自我修养,你有吗?Twitter的分布式雪花算法 SnowFlake 每秒自增生成26个万个可排序的ID (Java版)Java 10 新特性解密,引入类型推断机制,2018 年 3 月 20 日发布 ...

November 23, 2018 · 1 min · jiezi

始于阿里,回归社区|阿里巴巴的开源之路

破土而出的生命力,源自理想主义者心底对技术的信念。开源曾经帮助 Redhat 在传统软件市场奠定了其行业地位。无独有偶,作为云计算时代的赶超者,谷歌也拿起了开源的武器,试图打乱 AWS 和 Azure 的节奏。目前,这一策略似乎正在奏效。如今云原生技术正席卷全球,云原生基金会在去年 KubeCon +CloudNativeCon NA 的现场宣布:其正在孵化的项目已达 14 个,入驻的厂家或产品已超过 300 家,并吸引了 2.2 万开发者参与项目代码贡献,其明星产品 Kubenetes 的 GitHub 上 Authors 和 Issues 量已排行开源领域的第二名。而 Kubenetes 正是 Google 开源的一个容器编排引擎。今年,KubeCon + CloudNativeCon 首次来到中国。在2018 KubeCon + CloudNativeCon的现场,阿里云研究员伯瑜向在场的开发者们宣布,CNCF 已将阿里巴巴云原生镜像分发系统 Dragonfly 接纳为其沙箱项目(Sandbox),并有机会成为国内首个从 CNCF 毕业的开源项目。目前已经毕业的两个项目,一个是 Kubernetes,另一个是 Prometheus。据悉,目前阿里巴巴已经有 8 个项目进入 CNCF 云原生全景图,分别是分布式服务治理框架 Dubbo、分布式消息引擎 RocketMQ、流量控制组件Sentinel、企业级富容器技术 PouchContainer、服务发现和管理 Nacos、分布式消息标准 OpenMessaging、云原生镜像分发系统 Dragonfly 和高可用服务 AHAS。时间回到 2016 年2016 年的那届双11,RocketMQ 创始人冯嘉和他的团队首次将低延迟存储解决方案应用于双11的支撑,经受住了流量的大考,整个大促期间,99.996%的延迟落在了 10ms 以内,完成了保障交易稳定的既定目标。对于读写比例几乎均衡的分布式消息引擎来说,这一技术上的突破,即便是放在全球范围内,也绝对是值得称赞的。另一边,在历时3个月的开源重塑后,冯嘉和他的团队启动了 RocketMQ 向Apache 软件基金会的捐赠之路,但迈出这一步并不容易。“当时国内的开源氛围还没有现在那么活跃,开源之后,很多设计、源码和文档的维护工作还不够理想,但我们就是想证明国内的开源项目和开源社区也可以在世界的开源舞台上发挥价值。”经过近一年的努力,在2017年9月25日,Apache 软件基金会官方宣布,阿里巴巴捐赠给 Apache 社区的开源项目 RocketMQ 从 Apache 社区正式毕业,成为 Apache 顶级项目(TLP),这是国内首个非 Hadoop 生态体系的Apache 社区顶级项目。值得一提的是,根据项目毕业前的统计,RocketMQ 有百分八十的新特性与生态集成来自于社区的贡献。2017 年,消息领域出现一件里程碑事件。分布式消息领域的国际标准 OpenMessaging 开源项目正式入驻 Linux 基金会,这是国内首个在全球范围发起的分布式计算领域的国际标准。消息通讯已经成为现代数据驱动架构的关键环节,但在全球范围内,消息领域仍然存在两大问题:一是缺乏供应商中立的行业标准,导致各种消息中间件的高复杂性和不兼容性,相应地造成了公司的产品低效、混乱和供应商锁定等问题。二是目前已有的方案框架并不能很好地适配云架构,即非云原生架构,因此无法有效地对大数据、流计算和物联网等新兴业务需求提供技术支持。这也是冯嘉和他的团队在开源 RocketMQ 过程中,开发者和合作伙伴经常会提到的问题:“在消息领域,市场上出现了各类不同的开源解决方案,这导致了用户更高的接入和维护成本,为了确保各个消息引擎间能正常通信,还要投入大量的精力去做兼容。”这时候,建立一套供应商中立,和语言无关的消息领域的事实标准,成为各社区成员共同的诉求。此后,在 2017 年 9 月,阿里巴巴发起 OpenMessaging 项目,并邀请了雅虎、滴滴出行、Streamlio共同参与,一年后,参与 OpenMessaging 开源标准社区的企业达10家之多,包括阿里巴巴、Datapipeline、滴滴出行、浩鲸科技、京东商城、青云 QingCloud、Streamlio、微众银行、Yahoo、中国移动苏州研发中心(按首字母排序),此外,还获得了 RocketMQ、RabbitMQ 和 Pulsar 3 个顶级消息开源厂商的支持。相比于开源一个分布式消息项目,一套开源标准能被各家厂商所接受,对整个国内开源领域而言,是更具有里程碑意义的事件。2017 年 9 月,Dubbo 重启开源。Dubbo 是阿里巴巴于 2012 年开源的分布式服务治理框架,是国内影响力最大、使用最广泛的开源服务框架之一,在 2016 年、2017 年开源中国发起的最受欢迎的中国开源软件评选中,连续两年进入 Top10 名单。2017 年 9 月 7 日,在 Github 将版本更新至 2.5.4,重点升级所依赖的 JDK 及其组件,随后连续发布了 11 个版本。并于2018年2月捐献给 Apache 软件基金会,希望借助社区的力量来发展 Dubbo,打消大家对于 Dubbo 未来的顾虑。项目重启半年后,Dubbo 项目负责人阿里巴巴高级技术专家北纬在接受媒体采访的时候,从战略、社区、生态和回馈四个方面谈了 Dubbo 重启开源背后的原因。“集团近几年开始将开源提到了新的战略高度,这次投入资源重启开源,核心是希望让开源发挥更大的社会价值,并和广大开发者一起,建立一个繁荣的Dubbo 生态,普惠所有使用 Dubbo 的人和 Dubbo 本身。”Dubbo项目组成员朱勇在今年上海的技术沙龙上分享Dubbo未来发展的过程中提到,其后续的规划是要解决好两个问题。第一个问题是重点关注技术趋势,例如云原生对Dubbo开源现状的影响。第二个问题是 Dubbo 本身定位的问题,除了保持技术上的领先性,还需要围绕 Dubbo 核心发展生态,和社区成员一起将 Dubbo 发展成一个服务化改造的整体解决方案。2017 年 11 月,阿里自研容器技术 PouchContainer 开源。在开源不到一年的时间里,PouchContainer 1.0 GA 版本发布,达到可生产级别。今年 8 月,PouchContainer 被纳入开源社区开放容器计划 OCI;9 月,被收录进高校教材《云计算导论》;11 月,PouchContainer 团队携蚂蚁金服容器团队、阿里云 ACS 团队,与容器生态 Containerd 社区 Maintainer进行技术交流,有望发展成 Containerd 社区 Maintainer 席位,代表国内企业在世界容器技术领域发声。PouchContainer 发展速度之快,超出了宏亮的想象。宏亮是 Docker Swarm 容器集群项目的核心代码维护者(Maintainer),并于2015 年 8 月出版了《Docker 源码分析》一书,对 Docker 架构和源代码进行了深入的讲解,该书在 Docker 领域迅速成为畅销书籍。2017 年,宏亮承担起阿里自有容器技术的对内支持和对外技术布道的工作,秉承初心,希望在竞争激烈的容器开源领域能抢下属于国内容器技术的一席之地。在团队的努力下,阿里集团内部已实现 100%的容器化,并已经开始涉及离线业务,实现在、离线业务的混合调度与部署。整个集团能实现 100%的容器化,离不开阿里内部自研的 P2P 分发技术,该项目取名为 Dragonfly,寓意点与点之间的文件分发能如蜻蜓般轻盈和迅速,解决传统文件发布系统中的大规模下载、远距离传输、带宽成本和安全传输的问题。日前,Dragonfly 正式进入 CNCF, 并成为国内第三个被列为沙箱级别(Sandbox Level Project)的开源项目,可见,CNCF 在其云原生的技术版图中正希望借助Dragonfly等优秀的镜像分发技术,以提升企业微服务架构下应用的交付效率。始于阿里,回归社区。今年夏天,国内开源领域,迎来了两位新成员。作为微服务和云原生生态下的两款重要开源框架/组件,Nacos主打云原生应用中的动态服务发现、配置和服务管理,Sentinel 则是聚焦在限流和降级两个方面。Nacos 和 Sentinel 均是在阿里近 10 年的核心业务场景下沉淀所产生的,他们的开源是对微服务和元原生领域开源技术方案的有效补充,同时也非常强调融入开源生态,除了兼容 Dubbo和Sentinel,也支持对Spring Cloud 和 Kubenetes 等生态,以增强自身的生命力。“阿里巴巴早在 2007 年进行从 IOE 集中式应用架构升级为互联网分布式服务化架构的时候,就意识到在分布式环境中,诸如分布式服务治理,数据源容灾切换、异地多活、预案和限流规则等场景下的配置变更难题,因为在一个大型的分布式系统中,你没有办法把整个分布式系统停下来,去做一个软件、硬件或者系统的升级。”阿里巴巴高级技术专家坤宇在 2017 QCon 的现场分享到。在配置变更领域,我们从2008年的无 ConfigServer 时代,借用硬件负载设备 F5 提供的 VIP 功能,通过域名方式来实现服务提供方和调用方之间的通信,逐步经历了 ConfigServer 单机版、集群版的多次迭代,不断提高其稳定性。曾写下支付宝钱包服务端第一行代码的阿里高级技术专家慕义,在今年深圳的技术沙龙现场回忆了阿里注册中心自研的 10 年路:“这期间,集团业务经历了跨越式的发展,每年翻番的服务规模,不断的给 ConfigServer 的技术架构演进带来更高的要求和挑战,使得我们有更多的机会在生产环境发现和解决一个个问题的过程中,实现架构的一代代升级。Nacos 便是在这样的背景下,经过几代技术人的技术攻坚所产生的。”我们希望 Nacos 可以帮助开发者获得有别于原生或其他第三方服务发现和动态配置管理解决方案所提供的能力,满足开发者们在微服务落地过程当中对工业级注册中心的诉求,缩短想法到实现的路径。巧的是,一边是 Nacos宣布开源,另一边是 Spring Cloud 生态下的服务注册和发现组件 Netflix Eureka 宣布闭源,勇敢者的游戏充满了变数,但在坤宇和他的团队看来,这场游戏自己可以走到最后,因为我们并不是一个人在战斗,Nacos 只是阿里众多开源项目中的一员,随后还会有更多的开源项目反哺给社区,形成生态,例如轻量级限流降级组件 Sentinel。7月29日,Aliware Open Source•深圳站现场,只能容纳 400 人的场地,来了 700 多位开发者。阿里巴巴高级技术专家子矜在现场宣布了轻量级限流降级组件 Sentinel 的开源。作为阿里巴巴“大中台、小前台”架构中的基础模块,Sentinel 经历了 10 年双 11 的考验覆盖了阿里的所有核心场景,也因此积累了大量的流量归整场景以及生产实践。Sentinel 的出现,离不开阿里历届高可用架构团队的共同努力。“在双11备战中,容量规划是最重要也是最具挑战的环节之一。从第一年开始,双11的 0 点时刻就代表了我们的历史最高业务访问量,它通常是日常流量的几十倍甚至上百倍。因此,如何让一个技术和业务持续复杂的分布式站点去更平稳支撑好这突如其来的流量冲击,是我们这 10 年来一直在解的题。”阿里巴巴高可用架构团队资深技术专家游骥在今年的双11结束后分享道。这 10 年,容量规划经历了人工估算、线下压测、线上压测、全链路压测、全链路压测和隔离环境、弹性伸缩相结合的 5 个阶段。2013 年双11结束后,全链路压测的诞生解决了容量的确定性问题。作为一项划时代的技术,全链路压测的实现,对整个集团而言,都是一件里程碑事件。随后,基于全链路压测为核心,打造了一系列容量规划相关的配套生态,提升能力的同时,降低了整个环节的成本、提升效率。随着容量规划技术的不断演进,2018 年起,高可用架构团队希望可以把这些年在生成环境下的实践,贡献给社区,之后便有了 Sentinel 的开源。一边是作为发起者。将自己生产环境实践下沉淀出来的架构和技术贡献给社区。另一边是作为参与者。基于一些开源项目或云平台,输出可以解决开发者当前工作中存在的痛点的解决方案,例如近期新开源的项目 Spring Cloud Alibaba 和 开发者工具 Alibaba Cloud Toolkit。相同的是,技术理想主义者都希望技术可以为让世界变得更好,这才是技术人的兴奋点。“让世界的技术因为阿里巴巴而变得更美好一点点”。这是阿里巴巴系统软件、中间件、研发效能事业部负责人毕玄邮件签名中的一句话。他正和一群技术理想主义者,与太平洋另一边的技术高手们正面PK,在这场躲不开的战役中,一起认真一把。本文作者:amber涂南阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

November 22, 2018 · 2 min · jiezi

始于阿里,回归社区:阿里8个项目进入CNCF云原生全景图

摘要: 一群技术理想主义者,与太平洋另一边的技术高手们正面PK,在这场躲不开的战役中,一起认真一把。破土而出的生命力,源自理想主义者心底对技术的信念。云原生技术正席卷全球,云原生基金会在去年KubeCon +CloudNativeCon NA的现场宣布:其正在孵化的项目已达14个,入驻的厂家或产品已超过300家,并吸引了2.2万开发者参与项目代码贡献,其明星产品Kubenetes 的GitHub 上Authors 和 Issues 量已排行开源领域的第二名。今年,KubeCon + CloudNativeCon 首次来到中国。在2018 KubeCon + CloudNativeCon的现场,阿里云研究员伯瑜向在场的开发者们宣布,CNCF已将阿里巴巴云原生镜像分发系统Dragonfly接纳为其沙箱项目(Sandbox),并有机会成为国内首个从CNCF毕业的开源项目。目前已经毕业的两个项目,一个是Kubernetes,另一个是Prometheus。据悉,目前阿里巴巴已经有8个项目进入CNCF云原生全景图,分别是分布式服务治理框架Dubbo、分布式消息引擎RocketMQ、流量控制组件Sentinel、企业级富容器技术PouchContainer、服务发现和管理Nacos、分布式消息标准OpenMessaging、云原生镜像分发系统Dragonfly和高可用服务AHAS。时间回到2016年2016年的那届双11,RocketMQ创始人冯嘉和他的团队首次将低延迟存储解决方案应用于双11的支撑,经受住了流量的大考,整个大促期间,99.996%的延迟落在了10ms以内,完成了保障交易稳定的既定目标。对于读写比例几乎均衡的分布式消息引擎来说,这一技术上的突破,即便是放在全球范围内,也绝对是值得称赞的。另一边,在历时3个月的开源重塑后,冯嘉和他的团队启动了RocketMQ向Apache 软件基金会的捐赠之路,但迈出这一步并不容易。“当时国内的开源氛围还没有现在那么活跃,开源之后,很多设计、源码和文档的维护工作还不够理想,但我们就是想证明国内的开源项目和开源社区也可以在世界的开源舞台上发挥价值。”经过近一年的努力,在2017年9月25日,Apache 软件基金会官方宣布,阿里巴巴捐赠给 Apache 社区的开源项目 RocketMQ 从 Apache 社区正式毕业,成为 Apache 顶级项目(TLP),这是国内首个非 Hadoop 生态体系的Apache 社区顶级项目。值得一提的是,根据项目毕业前的统计,RocketMQ有百分八十的新特性与生态集成来自于社区的贡献。2017年,消息领域出现一件里程碑事件分布式消息领域的国际标准OpenMessaging开源项目正式入驻Linux基金会,这是国内首个在全球范围发起的分布式计算领域的国际标准。消息通讯已经成为现代数据驱动架构的关键环节,但在全球范围内,消息领域仍然存在两大问题:一是缺乏供应商中立的行业标准,导致各种消息中间件的高复杂性和不兼容性,相应地造成了公司的产品低效、混乱和供应商锁定等问题。二是目前已有的方案框架并不能很好地适配云架构,即非云原生架构,因此无法有效地对大数据、流计算和物联网等新兴业务需求提供技术支持。这也是冯嘉和他的团队在开源RocketMQ过程中,开发者和合作伙伴经常会提到的问题:“在消息领域,市场上出现了各类不同的开源解决方案,这导致了用户更高的接入和维护成本,为了确保各个消息引擎间能正常通信,还要投入大量的精力去做兼容。”这时候,建立一套供应商中立,和语言无关的消息领域的事实标准,成为各社区成员共同的诉求。此后,在2017年9月,阿里巴巴发起OpenMessaging项目,并邀请了雅虎、滴滴出行、Streamlio共同参与,一年后,参与OpenMessaging开源标准社区的企业达10家之多,包括阿里巴巴、Datapipeline、滴滴出行、浩鲸科技、京东商城、青云QingCloud、Streamlio、微众银行、Yahoo、中国移动苏州研发中心(按首字母排序),此外,还获得了RocketMQ、RabbitMQ和Pulsar 3个顶级消息开源厂商的支持。相比于开源一个分布式消息项目,一套开源标准能被各家厂商所接受,对整个国内开源领域而言,是更具有里程碑意义的事件。2017年9月,Dubbo重启开源Dubbo 是阿里巴巴于2012年开源的分布式服务治理框架,是国内影响力最大、使用最广泛的开源服务框架之一,在2016年、2017年开源中国发起的最受欢迎的中国开源软件评选中,连续两年进入Top10名单。2017年9月7日,在Github将版本更新至2.5.4,重点升级所依赖的JDK及其组件,随后连续发布了11个版本。并于2018年2月捐献给 Apache 软件基金会,希望借助社区的力量来发展 Dubbo,打消大家对于 Dubbo 未来的顾虑。项目重启半年后,Dubbo 项目负责人阿里巴巴高级技术专家北纬在接受媒体采访的时候,从战略、社区、生态和回馈四个方面谈了Dubbo重启开源背后的原因。“集团近几年开始将开源提到了新的战略高度,这次投入资源重启开源,核心是希望让开源发挥更大的社会价值,并和广大开发者一起,建立一个繁荣的Dubbo生态,普惠所有使用 Dubbo 的人和Dubbo本身。”Dubbo项目组成员朱勇在今年上海的技术沙龙上分享Dubbo未来发展的过程中提到,其后续的规划是要解决好两个问题。第一个问题是重点关注技术趋势,例如云原生对Dubbo开源现状的影响。第二个问题是 Dubbo 本身定位的问题,除了保持技术上的领先性,还需要围绕 Dubbo 核心发展生态,和社区成员一起将 Dubbo 发展成一个服务化改造的整体解决方案。2017年11月,阿里自研容器技术PouchContainer开源在开源不到一年的时间里,PouchContainer 1.0 GA 版本发布,达到可生产级别。今年8月,PouchContainer 被纳入开源社区开放容器计划OCI;9月,被收录进高校教材《云计算导论》;11月,Pouch团队携蚂蚁金服容器团队、阿里云ACS团队,与容器生态 Containerd社区 Maintainer进行技术交流,有望发展成 Containerd 社区 Maintainer 席位,代表国内企业在世界容器技术领域发声。PouchContainer发展速度之快,超出了宏亮的想象。宏亮是 Docker Swarm 容器集群项目的核心代码维护者(Maintainer),并于2015年8月出版了《Docker 源码分析》一书,对 Docker 架构和源代码进行了深入的讲解,该书在Docker领域迅速成为畅销书籍。2017年,宏亮承担起阿里自有容器技术的对内支持和对外推广工作,秉承初心,希望在竞争激烈的容器开源领域能抢下属于国内容器技术的一席之地。在他和团队的努力下,阿里集团内部已实现100%的容器化,并已经开始涉及离线业务,实现在、离线业务的混合调度与部署。整个集团能实现100%的容器化,离不开阿里内部自研的P2P分发技术,该项目取名为蜻蜓 Dragonfly,寓意点与点之间的文件分发能如蜻蜓般轻盈和迅速,解决传统文件发布系统中的大规模下载、远距离传输、带宽成本和安全传输的问题。日前,Dragonfly 正式进入 CNCF, 并成为国内第三个被列为沙箱级别(Sandbox Level Project)的开源项目,可见,CNCF 在其云原生的技术版图中正希望借助蜻蜓等优秀的镜像分发技术,以提升企业微服务架构下应用的交付效率。始于阿里,回归社区。今年夏天,国内开源领域,迎来了两位新成员。作为微服务和云原生生态下的两款重要开源框架/组件,Nacos主打云原生应用中的动态服务发现、配置和服务管理,Sentinle则是聚焦在限流和降级两个方面。Nacos和Sentinel均是在阿里近10年的核心业务场景下沉淀所产生的,他们的开源是对微服务和元原生领域开源技术方案的有效补充,同时也非常强调融入开源生态,除了兼容Dubbo和Sentinel,也支持对Spring Cloud 和 Kubenetes等生态,以增强自身的生命力。“阿里巴巴早在 2007 年进行从 IOE 集中式应用架构升级为互联网分布式服务化架构的时候,就意识到在分布式环境中,诸如分布式服务治理,数据源容灾切换、异地多活、预案和限流规则等场景下的配置变更难题,因为在一个大型的分布式系统中,你没有办法把整个分布式系统停下来,去做一个软件、硬件或者系统的升级。”阿里巴巴高级技术专家坤宇在2017 QCon的现场分享到。在配置变更领域,我们从2008年的无 ConfigServer 时代,借用硬件负载设备F5提供的VIP功能,通过域名方式来实现服务提供方和调用方之间的通信,逐步经历了ConfigServer单机版、集群版的多次迭代,不断提高其稳定性。曾写下支付宝钱包服务端第一行代码的阿里高级技术专家慕义,在今年深圳的技术沙龙现场回忆了阿里注册中心自研的10年路:“这期间,集团业务经历了跨越式的发展,每年翻番的服务规模,不断的给ConfigServer的技术架构演进带来更高的要求和挑战,使得我们有更多的机会在生产环境发现和解决一个个问题的过程中,实现架构的一代代升级。Nacos便是在这样的背景下,经过几代技术人的技术攻坚所产生的。”我们希望Nacos可以帮助开发者获得有别于原生或其他第三方服务发现和动态配置管理解决方案所提供的能力,满足开发者们在微服务落地过程当中对工业级注册中心的诉求,缩短想法到实现的路径。巧的是,一边是 Nacos宣布开源,另一边是Spring Cloud生态下的服务注册和发现组件Netflix Eureka宣布闭源,勇敢者的游戏充满了变数,但在坤宇和他的团队看来,这场游戏自己可以走到最后,因为我们并不是一个人在战斗,Nacos只是阿里众多开源项目中的一员,随后还会有更多的开源项目反哺给社区,形成生态,例如轻量级限流降级组件 Sentinel。7月29日,Aliware Open Source•深圳站现场,只能容纳400人的场地,来了700多位开发者。阿里巴巴高级技术专家子矜在现场宣布了轻量级限流降级组件Sentinel的开源。作为阿里巴巴“大中台、小前台”架构中的基础模块,Sentinel经历了10年双11的考验覆盖了阿里的所有核心场景,也因此积累了大量的流量归整场景以及生产实践。Sentinel的出现,离不开阿里历届高可用架构团队的共同努力。“在双11备战中,容量规划是最重要也是最具挑战的环节之一。从第一年开始,双11的0点时刻就代表了我们的历史最高业务访问量,它通常是日常流量的几十倍甚至上百倍。因此,如何让一个技术和业务持续复杂的分布式站点去更平稳支撑好这突如其来的流量冲击,是我们这10年来一直在解的题。”阿里巴巴高可用架构团队资深技术专家游骥在今年的双11结束后分享道。这10年,容量规划经历了人工估算、线下压测、线上压测、全链路压测、全链路压测和隔离环境、弹性伸缩相结合的5个阶段。2013年双11结束后,全链路压测的诞生解决了容量的确定性问题。作为一项划时代的技术,全链路压测的实现,对整个集团而言,都是一件里程碑事件。随后,基于全链路压测为核心,打造了一系列容量规划相关的配套生态,提升能力的同时,降低了整个环节的成本、提升效率。随着容量规划技术的不断演进,2018年起,高可用架构团队希望可以把这些年在生成环境下的实践,贡献给社区,之后便有了Sentinel的开源。一边是作为发起者。将自己生产环境实践下沉淀出来的架构和技术贡献给社区。另一边是作为参与者。基于一些开源项目或云平台,输出可以解决开发者当前工作中存在的痛点的解决方案,例如近期新开源的项目Spring Cloud Alibaba 和 开发者工具 Alibaba Cloud Toolkit。相同的是,技术理想主义者都希望技术可以为让世界变得更好,这才是技术人的兴奋点。“让世界的技术因为阿里巴巴而变得更美好一点点”。这是阿里巴巴毕玄邮件签名中的一句话。他正和一群技术理想主义者,与太平洋另一边的技术高手们正面PK,在这场躲不开的战役中,一起认真一把。本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

November 20, 2018 · 1 min · jiezi

智能微服务的设计与开发(node.js)

设计目标基于koa2、关系数据库(暂时只支持mysql)建立的智能微服务快速开发框架,将同时支持graphql与rest标准,使用typescript语言编写,力求安全、高效。 相关开源项目(gels – 凝胶),希冀该项目能成为联结设计、开发,前端、后端的“强力胶水”,成为微服务快速开发的有力框架。 项目地址:https://github.com/zhoutk/gels设计思路中小型企业,更多的是注重快速开发、功能迭代。关系数据库为我们提供了很多有用的支持,我试图把数据库设计与程序开发有机的结合起来,让前端送到后端的json对象自动映射成为标准的SQL查询语句。我的这种ORM方式,服务端不需要写一行代码,只需完成关系数据库的设计,就能为前端提供标准服务接口。 我设计了一套数据库访问标准接口,在实践中已经得到很好的运用。我已经在es6, typescript, java, python & go中实现;下一步是对数据库支持的扩展,准备支持流行的关系数据库(Mssql, sqlite3, prostgres等),有选择支持一些nosql,比如:mongo。数据库接口设计事务元素接口,sql参数用于手动书写sql语句,id会作为最后一个参数被送入参数数组。export default interface TransElement { table: string; method: string; params: object | Array<any>; sql?: string; id?: string | number;}数据库操作接口,包括基本CURD,两个执行手写sql接口,一个批量插入与更新二合一接口,一个事务操作接口。实践证明,下面八个接口,在绝大部分情况下已经足够。export default interface IDao { select(tablename: string, params: object, fields?: Array<string>): Promise<any>; insert(tablename: string, params: object): Promise<any>; update(tablename: string, params: object, id: string|number): Promise<any>; delete(tablename: string, id: string|number): Promise<any>; querySql(sql: string, values: Array<any>, params: object, fields?: Array<string>): Promise<any>; execSql(sql: string, values: Array<any>): Promise<any>; insertBatch(tablename: string, elements: Array<any>): Promise<any>; transGo(elements: Array<TransElement>, isAsync?: boolean): Promise<any>;}BaseDao,为业务层提供标准数据库访问的基类,是自动提供标准rest微服务的关键import IDao from ‘./idao’let dialect = G.CONFIGS.db_dialect //依赖注入let Dao = require(./${dialect}Dao).default export default class BaseDao { private table: string static dao: IDao //以组合的模式,解耦业务层与数据库访问层 constructor(table?: string) { this.table = table || ’’ if (!BaseDao.dao) { BaseDao.dao = new Dao() } } async retrieve(params = {}, fields = [], session = {userid: ‘’}): Promise<any> { let rs try { rs = await BaseDao.dao.select(this.table, params, fields) } catch (err) { err.message = data query fail: ${err.message} return err } return rs } async create(params = {}, fields = [], session = {userid: ‘’}): Promise<any> { let rs try { rs = await BaseDao.dao.insert(this.table, params) } catch (err) { err.message = data insert fail: ${err.message} return err } let { affectedRows } = rs return G.jsResponse(200, ‘data insert success.’, { affectedRows, id: rs.insertId }) } async update(params, fields = [], session = { userid: ’’ }): Promise<any> { params = params || {} const { id, …restParams } = params let rs try { rs = await BaseDao.dao.update(this.table, restParams, id) } catch (err) { err.message = data update fail: ${err.message} return err } let { affectedRows } = rs return G.jsResponse(200, ‘data update success.’, { affectedRows, id }) } async delete(params = {}, fields = [], session = {userid: ‘’}): Promise<any> { let id = params[‘id’] let rs try { rs = await BaseDao.dao.delete(this.table, id) } catch (err) { err.message = data delete fail: ${err.message} return err } let {affectedRows} = rs return G.jsResponse(200, ‘data delete success.’, { affectedRows, id }) }}默认路由/op/:command,只支持POST请求,不鉴权,提供登录等特定服务支持login,登录接口;输入参数{username, password};登录成功返回参数:{status:200, token}/rs/:table[/:id],支持四种restful请求,GET, POST, PUT, DELELTE,除GET外,其它请求检测是否授权中间件globalError,全局错误处理中间件router,路由中间件logger,日志,集成log4js,输出系统日志session,使用jsonwebtoken,实现鉴权;同时,为通过的鉴权的用户生成对应的session用户登录成功后得到的token,在以后的ajax调用时,需要在header头中加入token keyrestful_api数据表库设计完成后,会自动提供如下形式的标准restful api,多表关系可用关系数据库的视图来完成。[GET] /rs/users[?key=value&…], 列表查询,支持各种智能查询[GET] /rs/users/{id}, 单条查询[POST] /rs/users, 新增记录[PUT] /rs/users/{id}, 修改记录[DELETE] /rs/users/{id}, 删除记录智能查询查询保留字:fields, page, size, sort, search, lks, ins, ors, count, sum, groupfields, 定义查询结果字段,支持数组和逗号分隔字符串两种形式查询示例: /rs/users?username=white&age=22&fields=[“username”,“age”]生成sql: SELECT username,age FROM users WHERE username = ? and age = ?page, 分页参数,第几页size, 分页参数,每页行数sort, 查询结果排序参数查询示例: /rs/users?page=1&size=10&sort=age desc生成sql: SELECT * FROM users ORDER BY age desc LIMIT 0,10search, 模糊查询切换参数,不提供时为精确匹配查询示例: /rs/users?username=i&password=1&search生成sql: SELECT * FROM users WHERE username like ? and password like ?ins, 数据库表单字段in查询,一字段对多个值,例:查询示例: /rs/users?ins=[“age”,11,22,26]生成sql: SELECT * FROM users WHERE age in ( ? )ors, 数据库表多字段精确查询,or连接,多个字段对多个值,支持null值查询,例:查询示例: /rs/users?ors=[“age”,1,“age”,22,“password”,null]生成sql: SELECT * FROM users WHERE ( age = ? or age = ? or password is null )lks, 数据库表多字段模糊查询,or连接,多个字段对多个值,支持null值查询,例:查询示例: /rs/users?lks=[“username”,“i”,“password”,null]生成sql: SELECT * FROM users WHERE ( username like ? or password is null )count, 数据库查询函数count,行统计,例:查询示例: /rs/users?count=[“1”,“total”]&fields=[“username”]生成sql: SELECT username,count(1) as total FROM userssum, 数据库查询函数sum,字段求和,例:查询示例: /rs/users?sum=[“age”,“ageSum”]&fields=[“username”]生成sql: SELECT username,sum(age) as ageSum FROM usersgroup, 数据库分组函数group,例:查询示例: /rs/users?group=age&count=["",“total”]&fields=[“age”]生成sql: SELECT age,count() as total FROM users GROUP BY age不等操作符查询支持支持的不等操作符有:>, >=, <, <=, <>, =;逗号符为分隔符,一个字段支持一或二个操作。 特殊处:使用"=“可以使某个字段跳过search影响,让模糊匹配与精确匹配同时出现在一个查询语句中一个字段一个操作,示例:查询示例: /rs/users?age=>,10生成sql: SELECT * FROM users WHERE age> ?一个字段二个操作,示例:查询示例: /rs/users?age=>,10,<=,35生成sql: SELECT * FROM users WHERE age> ? and age<= ?使用”=“去除字段的search影响,示例:查询示例: /rs/users?age==,22&username=i&search生成sql: SELECT * FROM users WHERE age= ? and username like ?高级操作新增一条记录url [POST]/rs/usersheader Content-Type: application/json token: eyJhbGciOiJIUzI1NiIsInR…输入参数 { “username”:“bill”, “password”:“abcd”, “age”:46, “power”: “["admin","data"]” }返回参数 { “affectedRows”: 1, “id”: 7, “status”: 200, “message”: “data insert success.” }execSql执行手写sql语句,供后端内部调用使用示例 await new BaseDao().execSql(“update users set username = ?, age = ? where id = ? “, [“gels”,“99”,“6”])返回参数 { “affectedRows”: 1, “status”: 200, “message”: “data execSql success.” }insertBatch批量插入与更新二合一接口,供后端内部调用使用示例 let params = [ { “username”:“bill2”, “password”:“523”, “age”:4 }, { “username”:“bill3”, “password”:“4”, “age”:44 }, { “username”:“bill6”, “password”:“46”, “age”:46 } ] await new BaseDao().insertBatch(‘users’, params)返回参数 { “affectedRows”: 3, “status”: 200, “message”: “data batch success.” }tranGo事务处理接口,供后端内部调用使用示例 let trs = [ { table: ‘users’, method: ‘Insert’, params: { username: ‘zhou1’, password: ‘1’, age: 1 } }, { table: ‘users’, method: ‘Insert’, params: { username: ‘zhou2’, password: ‘2’, age: 2 } }, { table: ‘users’, method: ‘Insert’, params: { username: ‘zhou3’, password: ‘3’, age: 3 } } ] await new BaseDao().transGo(trs, true) //true,异步执行;false,同步执行返回参数 { “affectedRows”: 3, “status”: 200, “message”: “data trans success.” }安装运行运行数据脚本SET NAMES utf8;SET FOREIGN_KEY_CHECKS = 0;– —————————— Table structure for users– —————————-DROP TABLE IF EXISTS users;CREATE TABLE users (id int(11) NOT NULL AUTO_INCREMENT,username varchar(255) DEFAULT NULL,password varchar(255) DEFAULT NULL,age int(11) DEFAULT NULL,power json DEFAULT NULL,PRIMARY KEY (id)) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;– —————————— Records of users– —————————-BEGIN;INSERT INTO users VALUES (‘1’, ‘white’, ‘123’, ‘22’, null), (‘2’, ‘john’, ‘456i’, ‘25’, null), (‘3’, ‘marry’, null, ‘22’, null), (‘4’, ‘bill’, ‘123’, ‘11’, null), (‘5’, ‘alice’, ‘122’, ‘16’, null), (‘6’, ‘zhoutk’, ‘123456’, ‘26’, null);COMMIT;SET FOREIGN_KEY_CHECKS = 1;配置文件示例,./src/config/configs.tsexport default { inits: { directory: { run: false, dirs: [‘public/upload’, ‘public/temp’] } }, port: 5000, db_dialect: ‘mysql’, dbconfig: { db_host: ’localhost’, db_port: 3306, db_name: ‘strest’, db_user: ‘root’, db_pass: ‘123456’, db_char: ‘utf8mb4’, db_conn: 10, }, jwt: { secret: ‘zh-tf2Gp4SFU>a4bh_$3#46d0e85W10aGMkE5xKQ’, expires_max: 36000 //10小时,单位:秒 },}在终端(Terminal)中依次运行如下命令git clone https://github.com/zhoutk/gelscd gelsnpm i -g yarnyarn global install typescript tslint nodemonyarn installtsc -w //或 command + shift + B,选 tsc:监视yarn start //或 node ./dist/index.js项目结构├── package.json├── src //源代码目录│ ├── app.ts //koa配置及启动│ ├── common //通用函数或元素目录│ │ ├── globUtils.ts │ ├── config //配置文件目录│ │ ├── configs.ts│ ├── db //数据封装目录│ │ ├── baseDao.ts│ ├── globals.d.ts //全局声明定义文件│ ├── index.ts //运行入口│ ├── inits //启动初始化配置目录│ │ ├── global.ts│ │ ├── index.ts│ │ ├── initDirectory.ts│ ├── middlewares //中间件目录│ │ ├── globalError.ts│ │ ├── logger.ts│ │ ├── router│ │ └── session.ts│ └── routers //路由配置目录│ ├── index.ts│ └── router_rs.ts├── tsconfig.json└── tslint.json相关资源地址凝胶(gels)项目: https://github.com/zhoutk/gels视频讲座资料: https://github.com/zhoutk/sifou个人博客: https://github.com/zhoutk/blog相关视频课程运用typescript进行node.js后端开发精要 这是视频2的先导课免费入口,数量有限,先到先得nodejs实战之智能微服务快速开发框架 视频2亮点:成熟项目经验,经过总结、提炼、精简、重构,带领大家一步步实现一个智能微服务框架,这是一个完整的实用项目从无到有的实现过程。课程内容与结构经过精心准备,设计合理、节奏紧凑、内容翔实。真实再现了思考、编码、调试、除 错的整个开发过程。购置了新的录屏软件和录音设备,去除了上个视频中的杂音,清晰度更高,视频比较长,有三个小时。 ...

November 16, 2018 · 5 min · jiezi

Oracle发布开源的轻量级 Java 微服务框架 Helidon

近日,Oracle推出了一个新的开源框架Helidon,该项目是一个用于创建基于微服务的应用程序的Java库集合。和Payara Micro、Thorntail(之前的WildFly Swarm)、OpenLiberty、TomEE等项目一样,该项目也加入了MicroProfile家族。Helidon最初被命名为J4C(Java for Cloud),其设计以简单、快速为目标,它包括两个版本:Helidon SE和Helidon MP。Helidon SE提供了创建微服务的三个核心API:Web服务器、配置和安全,用于构建基于微服务的应用程序,不需要应用服务器。Helidon MP支持用于构建基于微服务的应用程序的MicroProfile 1.1规范。Helidon的架构下面的架构图显示了Helidon SE和Helidon MP的关系。下图说明了Helidon SE和Helidon MP所属的微服务框架类别。Web服务器受NodeJS和其他Java框架的启发,Helidon的Web服务器是一个异步、反应性API,运行在Netty之上。WebServer接口包括对配置、路由、错误处理以及构建度量和健康端点的支持。快速入门示例Helidon提供了快速入门示例来演示Helidon SE和Helidon MP之间的区别。先借用官方示例,稍后我们手写一个示例。在GitHub上可以找到整个官方Helidon项目。https://github.com/oracle/helidon构建Docker镜像Helidon SE示例docker build -t quickstart-se targetHelidon MP示例docker build -t quickstart-mp target运行Docker镜像Helidon SE示例docker run –rm -p 8080:8080 quickstart-se:latestHelidon MP示例docker run –rm -p 8080:8080 quickstart-mp:latest测试这两个示例都支持相同的REST接口该示例是一个非常简单的“Hello World”问候语服务。响应使用JSON编码。例如:curl -X GET http://localhost:8080/greet{“message”:“Hello World!"}curl -X GET http://localhost:8080/greet/Joe{“message”:“Hello Joe!"}curl -X PUT http://localhost:8080/greet/greeting/Hola{“greeting”:“Hola”}curl -X GET http://localhost:8080/greet/Jose{“message”:“Hola Jose!"}动手写一个示例环境Helidon需要Java 8(或更高版本)和Maven。如果要构建和部署Docker容器,则需要Docker。如果要部署到Kubernetes,则需要kubectl和Kubernetes集群以下列表显示了最低版本| Java SE 8或Open JDK 8 || Maven 3.5 || Docker 18.02 | 使用Edge通道在桌面上运行Kubernetes || Kubectl 1.7.4 |Maven坐标将以下代码段添加到pom.xml文件中<dependency> <groupId>io.helidon.webserver</groupId> <artifactId>helidon-webserver</artifactId> <version>0.10.1</version></dependency><dependency> <groupId>io.helidon.webserver</groupId> <artifactId>helidon-webserver-netty</artifactId> <version>0.10.1</version></dependency><!– WebServer Jersey依赖–><dependency> <groupId>io.helidon.webserver</groupId> <artifactId>helidon-webserver-jersey</artifactId> <version>0.10.1</version></dependency>测试方法package com.souyunku.helidon.webserver.examples.jersey;import io.helidon.webserver.ServerRequest;import io.helidon.webserver.ServerResponse;import io.helidon.webserver.jersey.JerseySupport;import io.opentracing.SpanContext;import javax.inject.Inject;import javax.inject.Named;import javax.ws.rs.*;import javax.ws.rs.core.Context;import javax.ws.rs.core.HttpHeaders;import javax.ws.rs.core.Response;import javax.ws.rs.core.UriInfo;import java.util.stream.Collectors;@Path(”/")public class HelloWorld { @Inject private ServerRequest request; @Inject private ServerResponse response; @Inject @Named(JerseySupport.REQUEST_SPAN_CONTEXT) private SpanContext spanContext; @GET @Path(“hello”) public Response hello() { return Response.ok(“Hello World !”).build(); } @POST @Path(“hello”) public Response hello(String content) { return Response.accepted(“Hello: " + content + “!”).build(); } @POST @Path(“content”) public Response content(String content) { return Response.accepted(content).build(); } @GET @Path(“injection”) public Response webServerInjection() { return Response.ok(“request=” + request.getClass().getName() + “\nresponse=” + response.getClass().getName() + “\nspanContext=” + spanContext.getClass().getName()).build(); } @GET @Path(“headers”) public Response headers(@Context HttpHeaders headers, @QueryParam(“header”) String header) { return Response.ok(“headers=” + headers.getRequestHeader(header).stream().collect(Collectors.joining(”,”))) .build(); } @GET @Path(“query”) public Response query(@QueryParam(“a”) String a, @QueryParam(“b”) String b) { return Response.accepted(“a=’” + a + “’;b=’” + b + “’”).build(); } @GET @Path(“path/{num}”) public Response path(@PathParam(“num”) String num) { return Response.accepted(“num=” + num).build(); } @GET @Path(“requestUri”) public String getRequestUri(@Context UriInfo uriInfo) { return uriInfo.getRequestUri().getPath(); }}启动服务package com.souyunku.helidon.webserver.examples.jersey;import io.helidon.webserver.Routing;import io.helidon.webserver.ServerConfiguration;import io.helidon.webserver.WebServer;import io.helidon.webserver.jersey.JerseySupport;import org.glassfish.jersey.server.ResourceConfig;import java.io.IOException;import java.util.concurrent.CompletionStage;import java.util.concurrent.ExecutionException;import java.util.concurrent.TimeoutException;import java.util.logging.LogManager;/** * WebServer Jersey /public final class WebServerJerseyMain { private WebServerJerseyMain() { } /* * 运行Jersey WebServer示例。 * * @param args * @throws IOException */ public static void main(String[] args) throws IOException, InterruptedException, ExecutionException, TimeoutException { // 配置日志记录,以避免标准的JVM默认设置 LogManager.getLogManager().readConfiguration(WebServerJerseyMain.class.getResourceAsStream("/logging.properties”)); // 最简单方法启动在8080端口 startServer(ServerConfiguration.builder() .port(8080) .build()); } static CompletionStage<WebServer> startServer(ServerConfiguration serverConfiguration) { WebServer webServer = WebServer.create( serverConfiguration, Routing.builder() //在/jersey上下文根目录注册Jersey应用程序 .register("/jersey", JerseySupport.create(new ResourceConfig(HelloWorld.class))) .build()); return webServer.start() .whenComplete((server, t) -> { System.out.println(“Jersey WebServer started.”); System.out.println(“Try the hello world resource at: http://localhost:” + server.port() + “/jersey/hello”); }); // http://localhost:8080/jersey/hello }}响应:Jersey WebServer started.Try the hello world resource at: http://localhost:8080/jersey/hello测试浏览器访问http://localhost:8080/jersey/hello响应:Hello World !带参数访问http://localhost:8080/jersey/query?a=www.souyunku.com&b=www.ymq.io响应:a=‘www.souyunku.com’;b=‘www.ymq.io’更多就不演示了调用链监控 ZipkinWebServer包括Zipkin对OpenTracing的支持。启用后,WebServer会将其跟踪事件发送到Zipkin。Maven坐标WebServer Zipkin支持依赖<dependency> <groupId>io.helidon.webserver</groupId> <artifactId>helidon-webserver-zipkin</artifactId></dependency>配置跟踪支持要启用Zipkin集成,请Tracer在上 配置ServerConfiguration.Builder。zipkin是一个开放源代码分布式的跟踪系统,由Twitter公司开源,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。它的理论模型来自于Google Dapper 论文。配置OpenTracing TracerServerConfiguration.builder() .tracer(new ZipkinTracerBuilder.forService(“my-application”) .zipkin(“http://10.0.0.18:9411”) .build()) .build()官方文档:https://helidon.io/docs/latestHelidon 的 GitHub 项目地址:https://github.com/oracle/helidon本文测试代码GitHub:https://github.com/souyunku/DemoProjects/tree/master/helidon-examples往期精彩文章如何找到完美的以太坊区块链开发者大数据推荐系统实时架构和离线架构ElasticSearch优化会员列表搜索Rabbitmq延迟队列实现定时任务软件做异常测试?必知的22个测试点总结!Java SQL注入危害这么大,该如何来防止呢?还没用上 JDK 11吧,JDK 12 早期访问构建版使用Dubbo 整合 Pinpoint 做分布式服务请求跟踪Java并发:分布式应用限流实践Contact作者:鹏磊出处:http://www.ymq.io/2018/10/15/Helidon版权归作者所有,转载请注明出处Wechat:关注公众号,搜云库,专注于开发技术的研究与知识分享 ...

October 16, 2018 · 2 min · jiezi

8分钟丨教你玩转 API

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~本文由织云平台团队发表于云+社区专栏背景当下,业界越来越多公司在项目架构设计时,会采用微服务架构。微服务架构,可以让我们的产品有更好的扩展性,更好的伸缩性;但同时也会带来微服务的一系列问题,比如微服务接口怎样规范管理?怎样在多团队协作中开放与复用?等等。同时,业界也在逐渐的引入DevOps理念,来实现开发,测试,运维,运营更紧密的高效配合,提升产品迭代的效率,质量。这里,织云API平台将从“部门内微服务API开放复用”,“产品线API DevOps实践”来分享腾讯社交网络运营部踩过的坑和API平台在“开放”,“DevOps”的理解及实践。1API开放与复用部门长期运营,积累了很多优秀的系统/平台,各个系统/平台也很早的开放了自己的Open API 给其它团队做二次开发和使用。 作为开放接口使用方:要集成A平台的B服务时,你可能会遇到:找不到平台开放接口文档;从平台官网下载的接口文档好像未更新;接口文档定义太简单。看不懂;使用前,不清楚接口的质量现状(成功率,耗时等);出异常时,没法快速界定问题的边界。作为开放接口提供方:你在运营上可能会遇到:接入方很多,长久下来,自己都不清楚调用方是哪些?最近我的接口调用量大增,不清楚这些调用是否合理?旧接口要下线,但仍有请求。不方便快速找到调用者。2产品线API那些事儿织云,是腾讯SNG海量业务运维能力经验沉淀出的产品,它采用微服务架构。在微服务的开发,测试,交付,运营中,我们遇到这样子的问题:web工程师:版本迭代很紧,但是后台同学的接口迟迟出不来,我的工作delay很久了后台工程师:版本迭代很紧,写代码的时间都没有。哪来时间写用例。但每次修改代码,人工自测耗费很多时间。两位工程师:上次不是好说接口长xx样子吗?怎样现在变成这样子了?质量工程师:这个迭代,织云性能是否达标呢?看不见,摸不着,快慢主要凭感觉。运维工程师:客户反馈操作有异常。一个问题都转几手开发。我怎样快速定位问题根源客户:你们的XX能力很好。我们想基于它们接口做二次开发。有开放接口吗织云API平台,就是这种大背景下应运而生。API平台简介定义织云API平台,是一个以API服务管理和代理以基础,赋能接口开发,测试,上线运营,下线管理于一体的API管理与开放平台。应用场景功能介绍1、织云API平台,实现了API统一规范管理与开放。 2、以服务代理为基础,实现了安全认证,过载保护。 3、对于服务调用支持日志查询,数据画像,异常告警,链路分析等功能。 4、可以基于API平台实现基于织云所有能力的定制开发的能力。接口规范和接入成本接口规范屏蔽接口URI层级差异:API平台,统一采用三级结构,通过/平台/服务/接口的层次来管理所有接入API,屏蔽实际接口URI的层级差异;屏蔽接口响应结构差异:API平台,自动转换接口响应结构,屏蔽实际接口的结构差异化。大大简化了集成开发,特别是Web前端同学适配后台接口的复杂度。全局业务错误码:确保服务间的每个错误码都是唯一能溯源的。接入成本–零改造API平台在设计之前就考虑到用户接入的成本。以上规范,API平台都能自动屏蔽差异,自动转换,自动生成。用户接入零改造。注册API服务 — 示例现成的API接口现在我有一个容量的分析接口:查询模块容量持续高低负载数据接口。url: http://capacity/load/sustaine… method: get 入参:type=1&m1id=468095&m2id=468095&m3id=468095&m4id=468095 出参: [ { “m1id”: 1256, “m2id”: 1256010, “day_cnt”: 14, “m4id”: 468095, “avg_load”: 0.25, “type”: 1, “model_cnt”: 1, “m3id”: 11120 } ]创建接口对应的平台,服务操作相似。如创建服务:其中的英文缩写,将是最终API url中对应的服务名。注册接口 - 基础信息注册接口 - 定义请求示例自动生成入出参:在入参,出参示例部分,只须贴入:入参:type=1&m1id=468095&m2id=468095&m3id=468095&m4id=468095, 出参: [ { “m1id”: 1256, “m2id”: 1256010, “day_cnt”: 14, “m4id”: 468095, “avg_load”: 0.25, “type”: 1, “model_cnt”: 1, “m3id”: 11120 } ]API平台会自动帮我们解析结构(当前支持key/value, json结构等解析)用户,只须录入字段是否必填,以及中文说明即可。注册接口 - 定义接口返回码接口开放查看开放API接口列表页:在API平台注册接口后,可以在API平台列表中查询每个开放接口:明细面:在明细面,可以查看接口详情。以及自动生成的调用示例。自动生成接口文档 访问权限申请API平台的接口开放模式暂时有两种:全开放,须审核。全开放:用户须在API平台应用组进行登记注册,API平台会分配一个唯一的apikey给到用户。对于全开放的接口,用户访问时,只须header带上apikey即可。须审核:对于一些敏感数据接口,用户访问前,须进行权限申请,将请求所在的业务模块与当前接口进行绑定。API平台只允许目标业务模块下的IP访问目标接口。场景一:接口开发-无中生有应用前-出现的问题:1.开发耦合:项目迭代刚启动,经常会出现后台开发间,前后端开发间接口相互依赖,导致工作相互delay。2.相互“扯皮”:开发间当面对齐接口,经常出现今天说“一套”,实际输出“一套”。没有接口落地及佐证的地方。应用后-规范的工作流程,实现了并行开发:有了API平台,大家的工作流程规范是这样:1. 接口提供方,注册新接口到API平台;2. 提供方与接口使用方通过API平台对齐接口,达成两方最终接口;3. 使用方使用API平台提供的伪接口进行功能开发及联调;(不再阻塞)4. 接口提供方严格按最终接口参数实现真实接口。5. 接口提供方将测试接口录入API平台,模式从“伪接口”切换成“测试”,接口使用方可以“无感知”的切换成真实接口服务中去。不需要额外联调。场景二:接口测试-可视化用例+自动测试“ 写代码的时间都没有。哪来时间写用例。但每次修改代码,人工自测耗费很多时间。” 这种现象其实在开发中很普遍。有没有一种模式,可以让开发不用写代码就能快速实现接口单元测试用例?甚至让不写代码的测试同学来帮开发实现测试用例?API平台,提供了可视化用例在线编辑:用户只须录入预设值,即可生成用例。一键执行用例,查看测试结果。API平台也实现了依赖第三方环境API的接口本地化测试。关于API平台测试能力这一部分,后面我们再专门单独做介绍。场景三:质量运营安全认证分配apikey: 所有API访问,须在API平台注册,由平台分配唯一的apikey。用户每次请求须带上apikey方可访问;限制开放源:对于敏感API接口,接口使用方须在API平台登记请求来源业务模块,经审核后,方可访问。过载保护每个接口可以自定义访问频率。API平台可以对接口进行限频保护。接口巡检API平台可对线上服务接口进行自定义的主动探测与巡检。在用户察觉问题前发现问题与修复问题。异常告警若API服务出现异常,API平台会主动通知接口使用方与提供方。异常告警案例CMDB下发配置(16:30,17:30灰度),未切走流量,导致接口请求小部分异常。 告警短信:查看API日志: 发现:后台spp服务异常跟进原因: 调用链路分析应用场景应用前-问题场景:A业务页面提示xx保存失败–>A业务开发卷入排查(重现问题+分析)–>发现是公共B服务异常–> B开发卷入相似分析–> 发现是平台服务C异常–> 卷入C开发相似分析–> 确认是redis服务异常。这种问题,如果发生在客户环境,会有ABC三个开发同学要:申请登录客户环境(有时很繁琐很费时)–> 排查–> 内部反馈,流转问题单。有时排查分析时间还没有前后协调时间耗费得多。应用后-链路分析场景:API平台调用链路分析能力,方便不懂业务的运维同学,一键在线查看整个调用链,直达问题根节点:1.获取异常请求ID:前端页面或后台服务出现异常时,定位者可以从页面或日志中获取调用请求的ID,2.还原问题现场:根据请求ID,在API平台获取调用链,快速全方位的还原现场数据:链路中每个请求的入参,出参,耗时,返回码,异常日志等。告别登机子查日志-重试重现问题-大量开发介入-问题修复效率低慢的问题。API调用链路分析API平台根据起始请求,将接口间调用关系生成一棵调用树.我们可以一目了然的看到:1.请求的调用链路;2.每一层调用现场:服务调用方,服务提供方,接口返回码,耗时, 入参,出参, 异常日志(若有异常)利用API平台的调用树能力,我们可以:1、快速了解服务的调用关系,发现不合理调用;2、帮助售后快速定位问题;减少开发介入频率;3、现场复原:不须再重现;避免重现不了问题的定位4、web可视化分析:减少上机子查日志的次数。提升定位效率。案例一:发现不合理调用(1)问题现场devtest环境,执行工具市场工具异常.(2)获取requestId获取id, 输入查询(3)重现调用树+问题现场(4)发现原因/问题结论一(问题原因):命令通道接口-判断设备连通性:发现设备不可通。结论二:通过调用链,发现工具市场存在重复调用cmdb接口问题。工具市场下个迭代修复。案例二:CMDB异常(1)问题现场:执行工具市场时,只提示CMDB异常。但不知道原因。(2)查看API平台调用树:不需求上机子查日志啦。可见原因是DB连接异常。场景四:数据画像API平台有实时日志查询、实时数据画像、性能分析等数据画像能力。这里,针对成功率,耗时做下介绍: 对于运营者来说,我们很关心线上接口的成功率,耗时,这样将直接影响服务质量,用户体验。横向分析查看接口成功率分布及趋势 & 查看接口耗时分布及趋势。平均成功率,平均耗时,会在“平均数据”下掩盖了一些细微的问题。API平台画像,会采用分段模式,下钻一层看问题。纵向分析以“天+接口”纬度查看明细数据:性能优化案例刚接入API平台时,织云自动化服务,共有39个接口有调用记录。其中29个接口(66.7%)不达标(接口耗时超过500ms)。经开发性能后,慢接口大幅减少。小结织云API平台,是结合我们部门“接口开放”,“接口生产”需求、痛点和DevOps理念的一次新探索,新实践。在传统API网关的能力基础上,拓展到更多API周期阶段,实现API的DevOps赋能与管理。以上是API平台简单的介绍和分享,抛砖引玉,希望大家都能打造好自己的微服务管理与开放平台。共勉!· 分 · 割 · 线 · 啦 ·织云企业版预约体验织云社区版 V1.2下载问答无法从API获取数据?相关阅读模型剖析 | 如何解决业务运维的四大难题?混合云管理问题,你解决了么?Pick一下,工具上线前运维必备原则 【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识 ...

September 30, 2018 · 1 min · jiezi