平台Java技术实践
当前位置:以往代写 > 其他教程 >平台Java技术实践
2019-06-14

平台Java技术实践

平台Java技术实践

  Java自1995年问世以来,已历经20多年岁月。20年来,IT技术风起云涌,Java始终以其可移植性、跨平台性、生态系统完备性等特点成为最主流的开发语言之一。事实上,Java无处不在,已经渗入到大家的日常生活中,从你的每一次购物到每一笔支付,都有Java技术的身影,国内外的主流网站大部分都是由Java技术支撑。

  搜狗商业平台负责搜狗广告业务,涵盖搜索、网盟、无线、品牌等业务线,面向几十万广告主和广告代理商,提供十亿级以上在线广告管理及相关支持,提供近百亿的在线报告。其中,基于Java的业务系统在70%以上。从底层缓存、会话、调度、通信交互,到提供给客户的API接口,从数据库访问、离线大规模数据处理到实时计算,都依托于Java技术。在我们内部长期的实践过程中,Java技术已经逐步自发地形成了一个生态系统。

  Java生态圈非常庞大而丰富,我们在长期的实践过程中,自主或基于Java开源组件进行二次开发和优化,构建了搜狗商业平台完整的Java技术框架,如图1所示。

  

平台Java技术实践_Java编写_Java技术_二次开发

 

  图1搜狗商业平台Java技术栈

  在基础组件层,我们直接使用了一些业界著名的框架和类库,比如IoC框架Spring、日志Log4J等;同时也基于一些框架进行了二次开发,比如基于Redis提供了分布式会话和分布式缓存,有效地解决单机内存及I/O瓶颈问题。在数据存储层,我们数据存储主要使用关系数据库MySQL、文档数据库MongoDB、分布式存储HDFS以及自行研发的DFS文件系统。在数据访问层,基于MySQL数据库和MongoDB数据库,分别提供了一套分库分表框架,使得其支持海量数据存储,同时也分别提供了ORM框架,使得能够很容易地完成数据库中的数据到对象的映射。在数据计算层,离线计算方案主要使用了HadoopMapReduce框架,流式计算方案主要使用了Kafka和Storm。在接口交互层,提供了三种框架,分别支持Thrift、WebServices和HTTP/JSON三种交互方式。在基础服务层,提供了认证、授权、配置、分布式任务调度、消息、图片、短信和邮件等多种基础服务。

  下面分别介绍我们在数据库分库分表框架、分布式任务调度平台和分布式RPC框架上的实践。

  数据库分库分表框架:Compass

  互联网领域针对大数据存储,基于NoSQL的数据库越来越多,然而,在一致性、事务性、可靠性等方面,特别是在较复杂的业务场景中,关系数据库仍起着不可替代的作用。在关系数据库领域,MySQL数据库基本上主导了市场。然而,互联网面临着用户多、数据量大等的挑战,一组MySQL数据库集群无法支撑如此大的PV及I/O,因此对单表的数据量以及每台机器的数据分布需要做一定的预估。在我们的实践中,对于单表的数据量有一些约束。一般说来,对于定长的记录,单表数据量最好不超过800W,极限不超过1000W;对于不定长记录,单表数据量最好不超过500W,极限不超过800W,否则在较复杂的业务场景中,可能会引起性能下降。

  对于大规模数据的存储和访问,一般都采用分库分表的方案解决。主流互联网公司都提供了各自的解决方案,比如淘宝分布式数据层TDDL、百度Dbproxy等。我们也研发了数据库分库分表框架Compass,支持和满足内部的一些需求。

  一般来说,数据库分布分表框架的设计有两种方案:独立中间件层方式和嵌入式应用框架方式。独立中间件层方式采用独立的部署,后端数据库对应用程序是透明的,其扩容对应用的可用性不会有明显的影响。嵌入式应用框架方式是独立的类库,应用需要显式地配置后端的单个或者多个数据库。独立中间件层方式的开发和维护成本都较高,且多了一层网络开销;嵌入式应用框架方式数据库配置较为复杂一些,但其开发维护成本低,并且对单元化架构的支持也不错,因此Compass选用了嵌入式应用框架方式。

  

平台Java技术实践_Java编写_Java技术_二次开发

 

  图2分布分表框架Compass架构图

  Compass系统架构如图2所示。基础数据源层可以选用开源的数据库连接池方案,比如包括C3P0、Proxool、TomcatJDBC、DBCP等。在我们的实践中主要使用C3P0。代理数据源层主要负责数据库分库分表的处理,包括分库数据源、主从数据源、心跳监控和管理接口四大模块。

  分库数据源和主从数据源都实现了Java中标准的javax.sql.DataSource接口,提供基于Spring注解的配置方式,对应用屏蔽底层数据源的差异,从而简化应用配置及应用在不同数据源之间迁移(包括普通数据源迁移至主从数据源、主从数据源迁移至分库数据源),降低数据库扩容成本。由于采用标准的javax.sql.DataSource接口,在JDBC封装层支持方面,我们目前可以兼容业界大部分的ORM框架,比如Hibernate、Mybatis、iBatis和JDBC等。同时由于采用对DataSource层进行分区路由,因此对于依赖javax.sql.DataSource接口的框架或应用均无影响。

#p#分页标题#e#

  分库数据源中包含路由选择器。路由选择器可以通过自定义路由选择策略选择合适的底层数据源,并将获取数据库连接的请求代理到此底层数据源。路由选择策略可通过多种方式实现:1.取模;2.分段;3.Hash;4.特殊路由策略等。在我们的实践中主要是对客户的物料进行管理,路由选择策略是通过客户ID取模实现,同时针对个别大客户使用特殊路由策略的方式,从而保证表中数据的均衡性。

  对于每次获取数据库连接的请求,主从数据源根据当前的事务属性等上下文相关信息以及自身可用的底层数据库连接池信息,返回底层数据源的连接。它主要包括主从选择和代理连接。主从选择可以支持读写分离、支持多从单主模式,并支持自定义反主从延时策略,更好地保证主从库数据的一致性;在负载均衡方面,我们除了支持内置的随机、权重、轮询、响应时间等负载均衡策略外,还支持自定义扩展负载均衡策略。代理连接主要是提供了一系列的策略对SQL进行拦截,完成分表等功能。在SQL解析与替换方面,目前我们内置了供如MyBatis之类的ORM框架的SQL占位符替换基于SQL语法树解析的SQL结构替换等方式,还支持自定义扩展解析和替换策略。在主从选择择中,反主从延时策略是解决主从延迟可选插件,它是通过将一段访问时间内的读请求路由到主库上来完成的,目前可以基于常见的分布式缓存和内存方式提供反主从延迟标记的管理,并支持自定义扩展。

  心跳监控主要对底层数据源的健康性进行监控。一般说来,底层数据源连接池都已经提供了心跳监控,例如C3P0能够监控数据库连接是否有效,检查数据库空闲连接以及数据库是否有效,并提供了一系列的策略来处理上述问题;然而,主从数据源以及分库数据源(特别的)需要对底层的数据源的数据库连接以及数据库是否可用进行监控,并在底层数据源不可用时提供策略进行处理(例如:对主从选择策略中的参数进行调整)。因此,数据源代理层仍需对底层数据源进行监控,并根据底层数据源是否可用进行选库或者负载均衡策略上的调整。同时心跳监控中也支持故障移除、故障恢复等功能,并能针对不同的数据库类型进行自定义监控扩展,并支持一定的JMX监控接口监控数据库连接池(C3P0/DBCP/Proxool等,支持自定义扩展),可以更好地监控其运行状况。

  管理接口主要提供访问次数(读写)以及执行时间、数据库连接数(活跃、空闲等状态)的监控管理,并通过JMX、Thrift等手段暴露服务。

  数据聚合层提供了数据聚合可选插件,目前支持继承已实现聚合的JdbcTemplate进行全库聚合和操作,并可采用多线程方式提高数据访问效率。

  元信息收集层主要提供了一系列的工具收集主从选择的标识、反延时标识、路由选择标识,提供给代理数据源层的路由选择器和主从选择器进行路由选择和主从选择。

  当然,Compass中间件在分布式数据库事务(在事务管理方面,我们继续沿用Spring事务管理机制,保证同库事务性)、跨节点join问题上依然没有很好的处理方法,在跨节点count/orderby/groupby等聚合问题上的实现也有待更优雅的支持。特别是针对全库聚合或者查询,其线程资源和内存资源占用都相对较高。这也是任何数据库中间层解决方案都未能完全解决的事情,只能依赖于在业务上进行精巧的设计,尽量避免这些问题。

  此外,Compass分库分表框架也大大提升了易用性:

  最小代码侵入:内置路由标识(Envidence)默认策略,不改变上层ORM框架实现; 简化配置:在配置中采用了大量的默认策略和机制,使得配置达到最简单; 最小接入成本:支持与目前现有的数据库访问框架并存,支持逐个数据库集群灰度切换。目前,Compass中间件已经接入了所有业务线应用,无论是从功能还是性能,与业界数据库中间件均保持统一水准,在易用性方面更是极大地简化了数据源配置和降低代码侵入,很好地支撑了目前10+亿级的物料存储和管理。

  分布式任务调度平台:凌云

#p#分页标题#e#

  随着业务的发展,各开发团队经常需要编写大量定时任务来进行相关的业务处理,如导入导出数据、报表计算、汇总统计等。最常见的定时任务可通过Linux系统中的Crontab来在指定时间点触发任务执行。然而,随着任务量逐渐增多,基于Crontab的任务管理方式存在诸多弊端:

  任务配置管理成本较高。每增加或修改一个任务,都需要修改Crontab,增加人力管理成本; 无法支持任务依赖。Crontab不支持任务间依赖; 手工配置出错风险高。手动修改Crontab缺少正确性校验机制,有一定出错风险; 不支持任务可视化。Crontab任务只能通过Linux终端查看,没有统一的管理界面查看任务详情及历史运行记录; 存在单点风险。任务每次触发后只能在一台机器上执行,若机器故障,任务将无法执行; 监控不完善。Crontab任务失败后,需要为任务单独增加相应的监控。

  为此,我们研发了搜狗分布式任务调度平台:凌云,将各种类型的任务统一到该平台进行配置和管理,并支持以下特性:

  将任务的管理、调度与执行解耦合; 任务调度节点和任务执行节点可水平扩展,避免单点; 各任务隔离执行,独立平滑上线,互不影响; 支持复杂任务依赖,一个任务可有多个前驱和多个后继; 任务失败自动报警、任务超时自动报警。

  

平台Java技术实践_Java编写_Java技术_二次开发

 

  图3凌云分布式任务调度平台

  其架构如图3所示。任务执行节点(TaskNode)是执行任务的服务器集合,这些服务器可划分为多个域,域主要保证不同业务间的隔离性。每个任务都需要指定所属的域,任务触发后,将会分配给其所属域中的一台服务器执行。任务执行节点负责具体任务的执行,每个任务执行节点上部署着一个任务代理(基于Thrift的HTTP服务),用于与调度集群交互并启动子进程执行具体任务。任务分为Java任务和Shell脚本任务(其中Hadoop任务属于一种Shell脚本任务),两者都是以子进程的形式由任务代理启动。

  任务代理与任务调度集群的交互主要包括接收任务分发请求、处理任务状态轮询请求、任务结束后回调任务调度集群等。任务代理通过获取任务子进程的退出码判断任务是否正常结束,退出码0表示正常完成任务,非0表示出现异常,任务代理会将退出码返回给任务调度集群。

  任务调度集群底层基于Quartz集群模式。Quartz是由Java编写的强大的企业级任务调度框架,提供了非常好的伸缩性、高可用性及负载均衡机制。我们在Quartz的基础上进行了扩展,支持任务的定时触发、依赖执行、失败重试及异常报警等。任务调度集群提供基于Thrift的HTTP服务,包括两方面功能:1.对任务管理中心开放任务管理和调度的相关接口,管理员对任务的调度配置会更新到任务调度集群中;2.对任务代理开放任务状态回调接口,任务在执行节点上运行完毕后,任务代理会通过此接口回调调度器告知其任务的运行结果。

  课课家认为任务的依赖执行可以非常方便地实现任务之间的前后顺序衔接,尤其是对于存在跨组数据依赖的情形,通过配置任务之间的依赖关系,即可实现数据获取的及时性和有效性。

    关键字:

在线提交作业