转自:https://juejin.im/post/5b59324ef265da0f69703f40,这是一篇很是好的讲解后端技术体系的文章,能让你对后端技术体系有个大概的轮廓。
这边我推荐我看过的一本书 曾宪杰《大型网站系统与Java中间件实践》,对于后端的一些服务如何从单机到分布式讲解是很是深刻的,让你可以对后端各个层次的中间件框架有着进一步的理解。ios
一、后端技术体系框架

二、统一请求入口-API网关
在移动 APP 的开发过程当中,一般后端提供的接口须要如下功能的支持:git
- 负载均衡
- API 访问权限控制
- 用户鉴权
通常的作法,使用 Nginx 作负载均衡,而后在每一个业务应用里作 API 接口的访问权限控制和用户鉴权,更优化一点的方式则是把后二者作成公共类库供全部业务调用。但从整体上来看,这三种特性都属于业务的公共需求,更可取的方式则是集成到一块儿做为一个服务,既能够动态地修改权限控制和鉴权机制,也能够减小每一个业务集成这些机制的成本。这种服务就是 API 网关,能够选择本身实现。也可使用开源软件实现,如 Kong 和 Netflix Zuul。API 网关通常架构以下图所示:github
可是以上方案的一个问题是因为全部 API 请求都要通过网关,它很容易成为系统的性能瓶颈。所以,能够采起的方案是:去掉 API 网关,让业务应用直接对接统一认证中心,在基础框架层面保证每一个 API 调用都须要先经过统一认证中心的认证,这里能够采起缓存认证结果的方式避免对统一认证中心产生过大的请求压力。web
三、统一认证中心
统一认证中心,主要是对 APP 用户、内部用户、APP 等的认证服务,包括数据库
- 用户的注册、登陆验证、Token 鉴权
- 内部信息系统用户的管理和登陆鉴权
- APP 的管理,包括 APP 的 secret 生成,APP 信息的验证(如验证接口签名)等。
之因此须要统一认证中心,就是为了可以集中对这些全部APP都会用到的信息进行管理,也给全部应用提供统一的认证服务。尤为是在有不少业务须要共享用户数据的时候,构建一个统一认证中心是很是必要的。此外,经过统一认证中心构建移动APP的单点登陆也是水到渠成的事情:模仿 Web 的机制,将认证后的信息加密存储到本地存储中供多个 APP 使用。编程
四、单点登陆系统
目前不少大的在线 Web 网站都是有单点登陆系统的,通俗的来讲就是只须要一次用户登陆,就可以进入多个业务应用(权限能够不相同),很是方便用户的操做。而在移动互联网公司中,内部的各类管理、信息系统甚至外部应用一样也须要单点登陆系统。后端
目前,比较成熟的、用的最多的单点登陆系统应该是耶鲁大学开源的CAS, 能够基于 https://github.com/apereo/cas/tree/master/cas-server-webapp 来定制开发的。api
基本上,单点登陆的原理都相似下图所示:缓存

五、统一配置中心
在 Java 后端应用中,一种读写配置比较通用的方式就是将配置文件写在 Propeties、YAML、HCON 等文件中,修改的时候只须要更新文件从新部署便可,能够作到不牵扯代码层面改动的目的。统一配置中心,则是基于这种方式之上的统一对全部业务或者基础后端服务的相关配置文件进行管理的统一服务, 具备如下特性:安全
- 可以在线动态修改配置文件并生效
- 配置文件能够区分环境(开发、测试、生产等)
- 在 Java 中能够经过注解、XML 配置的方式引入相关配置
百度开源的 Disconf 和携程的 Apollo 是能够在生产环境使用的方案,也能够根据本身的需求开发本身的配置中心,通常选择 Zookeeper 做为配置存储。
六、服务治理框架
对于外部 API 调用或者客户端对后端 API 的访问,可使用 HTTP 协议或者 RESTful(固然也能够直接经过最原始的socket来调用)。但对于内部服务间的调用,通常都是经过 RPC 机制来调用的。目前主流的 RPC 协议有:
- RMI
- Hessian
- Thrift
- Dubbo
这些 RPC 协议各有优劣点,须要针对业务需求作出最好的选择。
这样,当你的系统服务在逐渐增多,RPC 调用链愈来愈复杂,不少状况下,须要不停的更新文档来维护这些调用关系。一个对这些服务进行管理的框架能够大大减小所以带来的繁琐的人力工做。
传统的 ESB(企业服务总线)本质就是一个服务治理方案,但 ESB 做为一种 proxy 的角色存在于 Client 和 Server 之间,全部请求都须要通过 ESB,使得 ESB 很容易成为性能瓶颈。所以,基于传统的ESB,更好的一种设计以下图所示:

如图,以配置中心为枢纽,调用关系只存在于 Client 和提供服务的 Server 之间,就避免了传统 ESB 的性能瓶颈问题。对于这种设计,ESB 应该支持的特性以下:
- 服务提供方的注册、管理
- 服务消费者的注册、管理
- 服务的版本管理、负载均衡、流量控制、服务降级、资源隔离
- 服务的容错、熔断
阿里开源的 Dubbo 则对以上作了很好的实现,也是目前不少公司都在使用的方案;当当网的扩展项目 Dubbox 则在 Dubbo 之上加入了一些新特性。目前,Dubbo 已经被阿里贡献给 Apache,处于incubating 状态。在运维监控方面,Dubbo 自己提供了简单的管理控制台 dubbo-admin 和监控中心 dubbo-monitor-simple。Github 上的 dubboclub/dubbokeeper 则是在其之上开发的更为强大的集管理与监控于一身的服务管理以及监控系统。
此外,Netflix 的 Eureka 也提供了服务注册发现的功能,其配合 Ribbon 能够实现服务的客户端软负载均衡,支持多种灵活的动态路由和负载均衡策略。
七、统一调度中心
在不少业务中,定时调度是一个很是广泛的场景,好比定时去抓取数据、定时刷新订单的状态等。一般的作法就是针对各自的业务依赖 Linux 的 Cron 机制或者 Java 中的 Quartz。统一调度中心则是对全部的调度任务进行管理,这样可以统一对调度集群进行调优、扩展、任务管理等。Azkaban 和 Yahoo 的 Oozie 是 Hadoop 的流式工做管理引擎,也能够做为统一调度中心来使用。固然,你也可使用Cron或者Quartz来实现本身的统一调度中心。
- 根据 Cron 表达式调度任务
- 动态修改、中止、删除任务
- 支持任务分片执行
- 支持任务工做流:好比一个任务完成以后再执行下一个任务
- 任务支持脚本、代码、url等多种形式
- 任务执行的日志记录、故障报警
对于 Java 的 Quartz 这里须要说明一下:这个 Quartz 须要和 Spring Quartz 区分,后者是 Spring 对 Quartz 框架的简单实现也是目前使用的最多的一种调度方式。但其并无作高可用集群的支持。而 Quartz 虽然有集群的支持,可是配置起来很是复杂。如今不少方案都是使用 Zookeeper 来实现 Spring Quartz 的分布式集群。
此外,当当网开源的 elastic-job 则在基础的分布式调度之上又加入了弹性资源利用等更为强大的功能。
八、统一日志服务
日志是开发过程必不可少的东西。打印日志的时机、技巧是很能体现出工程师编码水平的。毕竟,日志是线上服务可以定位、排查异常最为直接的信息。
一般的,将日志分散在各个业务中很是不方便对问题的管理和排查。统一日志服务则使用单独的日志服务器记录日志,各个业务经过统一的日志框架将日志输出到日志服务器上。
能够经过实现 Log4j 或者 Logback 的 Appender 来实现统一日志框架,而后经过 RPC 调用将日志打印到日志服务器上。
九、业务应用和后端基础框架
业务应用分为:在线业务应用和内部业务应用。
- 在线业务应用:直接面向互联网用户的应用、接口等,典型的特色就是:请求量大、高并发、对故障的容忍度低。
- 内部业务应用:主要面向公司内部用户的应用。好比,内部数据管理平台、广告投放平台等。相比起在线业务应用,其特色: 数据保密性高、压力小、并发量小、容许故障的发生。
业务应用基于后端的基础框架开发,针对 Java 后端来讲,应该有如下几个框架:
- MVC 框架:统一开发流程、提升开发效率、屏蔽一些关键细节的 Web/后端框架。典型的如 SpringMVC、Jersey 以及国人开发的 JFinal 以及阿里的 WebX。
- IOC 框架:实现依赖注入/控制反转的框架。Java 中最为流行的 Spring 框架的核心就是 IOC 功能。
- ORM 框架:可以屏蔽底层数据库细节,提供统一的数据访问接口的数据库操做框架,额外地可以支持客户端主从、分库、分表等分布式特性。MyBatis 是目前最为流行的 ORM 框架。此外,Spring ORM 中提供的 JdbcTemplate 也很不错。固然,对于分库分表、主从分离这些需求,通常就须要本身实现,开源的则有阿里的 TDDL、当当的 sharding-jdbc(从datasource层面解决了分库分表、读写分离的问题,对应用透明、零侵入)。此外,为了在服务层面统一解决分库分表、读写分离、主备切换、缓存、故障恢复等问题,不少公司都是有本身的数据库中间件的,好比阿里的 Cobar、360的 Atlas(基于MySQL-Proxy)、网易的 DDB 、美团的 zebra等;开源的则有 MyCat(基于Cobar)和 Kingshard ,其中 Kingshard 已经有必定的线上使用规模。MySQL 官方也提供了 MySQL Proxy, 可使用 lua 脚本自定义主从、读写分离、分区这些逻辑,但其性能较差,目前使用较少。
- 缓存框架:对 Redis、Memcached 这些缓存软件操做的统一封装,可以支持客户端分布式方案、主从等。通常使用 Spring 的 RedisTemplate 便可,也可使用 Jedis 作本身的封装,支持客户端分布式方案、主从等。
- JavaEE 应用性能检测框架:对于线上的JavaEE应用,须要有一个统一的框架集成到每个业务中检测每个请求、方法调用、JDBC 链接、Redis 链接等的耗时、状态等。Jwebap 是一个可使用的性能检测工具,但因为其已经不少年没有更新,有可能的话建议基于此项目作二次开发。
通常来讲,以上几个框架便可以完成一个后端应用的雏形。
十、缓存、数据库、搜索引擎、消息队列
缓存、数据库、搜索引擎、消息队列这四者都是应用依赖的后端基础服务,他们的性能直接影响到了应用的总体性能,有时候你代码写的再好也许就是由于这些服务致使应用性能没法提高上去。
- 缓存: 缓存一般被用来解决热点数据的访问问题,是提升数据查询性能的强大武器。在高并发的后端应用中,将数据持久层的数据加载到缓存中,可以隔离高并发请求与后端数据库,避免数据库被大量请求击垮。目前经常使用的除了在内存中的本地缓存,比较广泛的集中缓存软件有 Memcached 和 Redis。其中 Redis 已经成为最主流的缓存软件。
- 数据库:数据库能够说是后端应用最基本的基础设施。基本上绝大多数业务数据都是持久化存储在数据库中的。主流的数据库包括传统的关系型数据库(MySQL、PostgreSQL)以及最近几年开始流行的 NoSQL(MongoDB、HBase)。其中 HBase 是用于大数据领域的列数据库,受限于其查询性能,通常并不用来作业务数据库。
- 搜索引擎:搜索引擎是针对全文检索以及数据各类维度查询设计的软件。目前用的比较多的开源软件是 Solr 和 Elasticsearch,都是基于 Lucence 来实现的,不一样之处主要在于 termIndex 的存储、分布式架构的支持等。Elasticsearch 因为对集群的良好支持以及高性能的实现,已经逐渐成为搜索引擎的主流开源方案。
- 消息队列:数据传输的一种方式就是经过消息队列。目前用的比较广泛的消息队列包括为日志设计的 Kafka 以及重事务的 RabbitMQ 等。在对消息丢失不是特别敏感且并不要求消息事务的场景下,选择 Kafka 可以得到更高的性能;不然,RabbitMQ 则是更好的选择。此外,ZeroMQ 则是一种实现消息队列的网络编程 Pattern 库,位于 Socket 之上,MQ 之下。
十一、文件存储
无论是业务应用、依赖的后端服务仍是其余的各类服务,最终仍是要依赖于底层文件存储的。一般来讲,文件存储须要知足的特性有:可靠性、容灾性、稳定性,即要保证存储的数据不会轻易丢失,即便发生故障也可以有回滚方案,也要保证高可用。在底层能够采用传统的 RAID 做为解决方案,再上一层,目前 Hadoop 的 HDFS 则是最为广泛的分布式文件存储方案,固然还有 NFS、Samba 这种共享文件系统也提供了简单的分布式存储的特性。
此外,若是文件存储确实成为了应用的瓶颈或者必须提升文件存储的性能从而提高整个系统的性能时,那么最为直接和简单的作法就是抛弃传统机械硬盘,用 SSD 硬盘替代。像如今不少公司在解决业务性能问题的时候,最终的关键点每每就是 SSD。这也是用钱换取时间和人力成本最直接和最有效的方式。在数据库部分描述的 SSDB 就是对 LevelDB 封装以后,利用 SSD 硬盘的特性的一种高性能 KV 数据库。
至于 HDFS,若是要使用上面的数据,是须要经过 Hadoop 的。相似 xx on Yarn 的一些技术就是将非 Hadoop 技术跑在 HDFS 上的解决方案。
十二、数据基础设施
数据是最近几年很是火的一个领域。从《精益数据分析》到《增加黑客》,都是在强调数据的非凡做用。不少公司也都在经过数据推进产品设计、市场运营、研发等。这里须要说明的一点是,只有当你的数据规模真的到了单机没法处理的规模才应该上大数据相关技术,千万不要为了大数据而大数据。不少状况下使用单机程序 +MySQL 就能解决的问题非得上 Hadoop 即浪费时间又浪费人力。
这里须要补充一点的是,对于不少公司,尤为是离线业务并无那么密集的公司,在不少状况下大数据集群的资源是被浪费的。所以诞了 xx on Yarn 一系列技术让非 Hadoop 系的技术能够利用大数据集群的资源,可以大大提升资源的利用率,如 Dockeron Yarn。
数据高速公路
接着上面讲的统一日志服务,其输出的日志最终是变成数据到数据高速公路上供后续的数据处理程序消费的。这中间的过程包括日志的收集和传输。
-
收集:统一日志服务将日志打印在日志服务上以后,须要日志收集机制将其集中起来。目前,常见的日志收集方案有:Scribe、Chukwa、Kakfa 和 Flume。对好比下图所示:

-
传输:经过消息队列将数据传输到数据处理服务中。对于日志来讲,一般选择 Kafka 这个消息队列便可。
此外,这里还有一个关键的技术就是数据库和数据仓库间的数据同步问题,即将须要分析的数据从数据库中同步到诸如 Hive 这种数据仓库时使用的方案。可使用 Apache Sqoop 进行基于时间戳的数据同步,此外,阿里开源的 Canal 实现了基于 binlog 增量同步,更加适合通用的同步场景,可是基于 Canal 仍是须要作很多的业务开发工做。
离线数据分析
离线数据分析是能够有延迟的,通常针对的是非实时需求的数据分析工做,产生的也是延迟一天的报表。目前最经常使用的离线数据分析技术除了 Hadoop 还有 Spark。相比 Hadoop,Spark 性能上有很大优点,固然对硬件资源要求也高。其中,Hadoop 中的 Yarn 做为资源管理调度组件除了服务于 MR 还能够用于 Spark(Spark on Yarn),Mesos 则是另外一种资源管理调度系统。
对于 Hadoop,传统的 MR 编写很复杂,也不利于维护,能够选择使用 Hive 来用 SQL 替代编写 MR。而对于 Spark,也有相似 Hive 的 Spark SQL。
此外,对于离线数据分析,还有一个很关键的就是数据倾斜问题。所谓数据倾斜指的是 region 数据分布不均,形成有的结点负载很低,而有些却负载很高,从而影响总体的性能。处理好数据倾斜问题对于数据处理是很关键的。
实时数据分析
相对于离线数据分析,实时数据分析也叫在线数据分析,针对的是对数据有实时要求的业务场景,如广告结算、订单结算等。目前,比较成熟的实时技术有 Storm 和 Spark Streaming。相比起Storm,Spark Streaming 其实本质上仍是基于批量计算的。若是是对延迟很敏感的场景,仍是应该使用 Storm。除了这二者,Flink 则是最近很火的一个分布式实时计算框架,其支持 Exactly Once的语义,在大数据量下具备高吞吐低延迟的优点,而且可以很好的支持状态管理和窗口统计,但其文档、API管理平台等都还须要完善。
实时数据处理通常状况下都是基于增量处理的,相对于离线来讲并不是可靠的,一旦出现故障(如集群崩溃)或者数据处理失败,是很难对数据恢复或者修复异常数据的。所以结合离线+实时是目前最广泛采用的数据处理方案。Lambda架构就是一个结合离线和实时数据处理的架构方案。
此外,实时数据分析中还有一个很常见的场景:多维数据实时分析,即可以组合任意维度进行数据展现和分析。目前有两种解决此问题的方案:ROLAP 和 MOLAP。
- ROLAP:使用关系型数据库或者扩展的关系型数据库来管理数据仓库数据,以Hive、Spark SQL、Presto为表明。
- MOLAP:基于数据立方体的多位存储引擎,用空间换时间,把全部的分析状况都物化为物理表或者视图。以Druid、Pinot和Kylin为表明,不一样于ROLAP(Hive、Spark SQL), 其原生的支持多维的数据查询。
如上一小节所述,ROLAP的方案大多数状况下用户离线数据分析,知足不了实时的需求,所以 MOLAP 是多维数据实时分析的经常使用方案。对于其中经常使用的三个框架,对好比下:

其中,Druid相对比较轻量级,用的人较多,比较成熟。
数据即席分析
离线和实时数据分析产生的一些报表是给数据分析师、产品经理参考使用的,可是不少状况下,线上的程序并不能知足这些需求方的需求。这时候就须要需求方本身对数据仓库进行查询统计。针对这些需求方,SQL上手容易、易描述等特色决定了其多是一个最为合适的方式。所以提供一个 SQL 的即席查询工具可以大大提升数据分析师、产品经理的工做效率。Presto、Impala、Hive 都是这种工具。若是想进一步提供给需求方更加直观的 ui 操做界面,能够搭建内部的 Hue。

1三、故障监控
对于面向用户的线上服务,发生故障是一件很严重的事情。所以,作好线上服务的故障检测告警是一件很是重要的事情。能够将故障监控分为如下两个层面的监控:
- 系统监控:主要指对主机的带宽、CPU、内存、硬盘、IO等硬件资源的监控。可使用 Nagios、Cacti 等开源软件进行监控。目前,市面上也有不少第三方服务可以提供对于主机资源的监控,如监控宝等。对于分布式服务集群(如 Hadoop、Storm、Kafka、Flume 等集群)的监控则可使用Ganglia。此外,小米开源的 OpenFalcon 也很不错,涵盖了系统监控、JVM监控、应用监控等,也支持自定义的监控机制。
- 业务监控:是在主机资源层面以上的监控,好比 APP 的 PV、UV 数据异常、交易失败等。须要业务中加入相关的监控代码,好比在异常抛出的地方,加一段日志记录。
监控还有一个关键的步骤就是告警。告警的方式有不少种:邮件、IM、短信等。考虑到故障的重要性不一样、告警的合理性、便于定位问题等因素,有如下建议:
- 告警日志要记录发生故障的机器 IP,尤为是在集群服务中,若是没有记录机器 IP,那么对于后续的问题定位会很困难。
- 要对告警作聚合,不要每个故障都单独进行告警,这样会对工程师形成极大的困扰。
- 要对告警作等级划分,不能对全部告警都作一样的优先级处理。
- 使用微信作为告警软件,可以在节省短信成本的状况下,保证告警的到达率。
故障告警以后,那么最最关键的就是应对了。对于创业公司来讲,24小时待命是必备的素质,当遇到告警的时候,须要尽快对故障作出反应,找到问题所在,并能在可控时间内解决问题。对于故障问题的排查,基本上都是依赖于日志的。只要日志打的合理,通常状况下是可以很快定位到问题所在的,可是若是是分布式服务,而且日志数据量特别大的状况下,如何定位日志就成为了难题。这里有几个方案:
- 创建ELK(Elasticsearch + Logstash + Kibana)日志集中分析平台,便于快速搜索、定位日志。搭配 Yelp 开源的 Elastalert 能够实现告警功能。
- 创建分布式请求追踪系统(也能够叫全链路监测系统),对于分布式系统尤是微服务架构,可以极大的方便在海量调用中快速定位并收集单个异常请求信息,也能快速定位一条请求链路的性能瓶颈。惟品会的 Mercury、阿里的鹰眼、新浪的 WatchMan、Twitter 开源的 Zipkin 基本都是基于 Google 的 Dapper 论文而来,大众点评的实时应用监控平台 CAT 则在支持分布式请求追踪(代码侵入式)的基础上加入了细粒度的调用性能数据统计。此外,Apache 正在孵化中的 HTrace 则是针对大的分布式系统诸如 HDFS 文件系统、HBase 存储引擎而设计的分布式追踪方案。而若是你的微服务实现使用了 Spring Cloud,那么 Spring Cloud Sleuth 则是最佳的分布式跟踪方案。还须要提到的是,Apache 孵化中的 SkyWalking 是基于分布式追踪的一个完备的APM(应用性能监测)系统,其最大的一个特色就是基于 Java agent + instrument api,对业务代码无任何侵入,Pinpoint则是相似的另外一个已经用于生产环境的 APM 系统。