Java框架研发思考(java做框架)
csdh11 2025-03-28 16:02 19 浏览
这次应CSDN之邀为Java20周年写稿,多谢大家能够记得我,本是想写一篇具体实战技术的文章,但这些技巧也许在其20岁成年之时已经代表不了什么新潮流,尽管20岁年龄的人类还是属于追求潮流的一代。回顾这些年的Java之路,特别是开发Jdon这个Java开源框架的前后经历,我想也许有必要和大家分享其中的得与失,供后来者借鉴。
彭晨阳
下面我大概谈谈Jdon框架的开发经历和我的思想转变发展过程。
最初开发Jdon框架的想法是因为Web流行导致的三层直至多层架构对开发流程的影响。现代多层架构将后端架构分解为多个层次,灵活性得到提高,因为你维护拓展任何一个层都很少影响其他层,这也是设计模式或面向对象思想的最初初衷吧。但灵活性也是有副作用的,副作用是带来了复杂性,简单的数据增删改查四个功能需要经过三层,那么就可能产生12道工序的开发。
因此,我希望能够在不牺牲多层架构基础上提高快速开发的能力,于是需要集成表现层、业务层和持久层等现有框架的集成整合能力,当时表现层框架是Struts1.x,业务层框架是Spring,Spring其实是一个业务容器,集成了依赖注入DI和AOP;而当时我对另外一个轻量反转注入微容器PicoContainer比较熟悉;在持久层选择上,当时有Hibernate等ORM选择,但考虑到这些ORM可能会绑架业务实体对象,而我设计的业务层框架容器不应该像Spring那样只包含服务,而且也应该业务实体对象。
这种想法也让我开发的Jdon框架完全不同于当时各种开发框架,同时可能走上另类的道路,就是今天大部分开发路线都是服务和实体分离,实体由数据库管理,而我的设计思路是让实体对象常驻在内存Inmemory中,虽然在性能上有很大提升,但是在数据完整性与一致性方面完全脱离了关系数据库的ACID支持。
为了体现这种业务服务和业务实体合并在一个容器中的特点,我还需要寻找理论上的支持,当时恰逢DDD领域驱动设计思想的诞生,通过简单接触,发现其分析设计理念完全符合我理想中的设计,DDD对业务需求的分析是从面向对象OO分析方法开始,与传统的基于关系数据库的E-R模型分析方法不同,DDD强调从需求中找出有界上下文与微服务,还有实体与值对象两种数据模型,DDD的实体模型对象不同于关系数据库的实体,它不但包含数据,还包含改变这些数据的方法行为,也就是将可变的状态用对象方法封装起来,将改变状态的方法行为暴露给外界,这种设计理念与后来并发模型Actor模型非常类似。
基于并发的Actor模型在Erlang和Scala中都有实现,我非常想将这种Actor模型引入到框架中,用来作为DDD实体模型的落地实现,这时发现了Disruptor框架,其内部RingBuffer模型能够实现两个线程之间无锁通信,而之前Java世界基本都是基于有锁实现,Disruptor在LMAX系统中实现每秒600万的交易。于是我将Disruptor作为框架的业务层容器核心基础组件,服务与实体之间可以通过发送异步消息通信,不再使用传统的方法直接调用,因为这会造成两者的耦合,当然引入接口,也会和接口耦合,现在实体与服务之间通过消息通道耦合,发送者无论哪个消费者接收只管发送消息,消费者也无论哪个发送者发送的消息只管接收就可以了。后来我发现,其实这个并发模型更类似Go语言的Channel并发模型。
框架的并发性能通过引入常驻内存和异步消息机制得到了最大化提升,下一步需要关心数据的完整性和一致性。因为摆脱了关系数据库的ACID支持。这方面参考了分布式系统的CAP定理。有人可能会说,你只是一个开发框架,又不是分布式框架,怎么会使用到CAP呢?其实因为我们的实体模型数据常驻内存,而存储层如关系数据库或NoSQL也有一份同样的数据,很显然,数据已经被分布了,那么这两个地方的同一数据如何保证一致性?这个原理类似两台服务器之间同一种数据如何保证一致性一样,这就需要CAP定理了。
在这种数据分区分布的情况下,只能在高一致性和可用性之间作平衡,如果你使用在高可用性场合,比如追求高性能,低延迟,快速响应,大的吞吐量,那么可以牺牲一点高一致性,通过最终一致性来实现;当然如果你很注重数据一致性完整性,那么可以牺牲一点可用性的性能问题。
那么具体开发中如何平衡呢?
CQRS架构提供了这种动态平衡,CQRS是一种读写分离的架构,数据的读取查询需要快速高性能,因此可用性为第一;而数据的保存修改等写操作,数据安全为第一;数据完整性很重要,那么高一致性为第一。
上面讨论了Jdon框架的并发性能和数据一致性问题,那么,Jdon框架的扩展性如何?所谓扩展性Scalable或称为可伸缩性是指水平分布扩展的能力,通过增加后端服务器就能线性提高系统的处理能力,这时引入了EventSourcing概念(简称ES)。
ES是一种不同于传统数据存储的思路。通常,我们是将实体对象中可变的状态直接保存到关系数据库对应的数据表中,比如订单实体模型的状态有未付款已付款和已出货三种状态,这些可变的状态保存在数据表字段中。
前面我们提到,实体模型对象与由数据表翻译过来的实体数据对象是有区别的,关键是前者包含改变状态的方向行为,也就是说,订单对象包含付款与出货两个方法,如果这两个方法被调用,那么订单的状态就会改变,比如付款方法一旦被调用完成,那么订单状态从未付款变为了已付款。这时问题来了,因为传统数据保存的是订单的当前状态,那么数据表中订单表的状态用已付款覆盖了未付款,曾经存在过的未付款这个状态就被覆盖了,如果订单状态一旦出错,我们无法追踪当前状态是由之前哪个状态切换过来,那么这时如果我们将订单对象的付款方法调用行为作为数据保存起来,就会能够追溯状态变化的历史。
前面说过,订单实体对象的方法调用是通过异步消息触发的,而不是使用普通代码直接调用的,这点Jdon框架已经通过内置的Disruptor实现了,因此,在ES架构中,我们只要将异步消息事件作为数据保存到数据库中即可。当然,ES架构不只是为了方便调试追溯历史,更重要的是易于分布扩展,如果我们将异步消息事件保存到一个消息系统中,比如ApacheKafka中,那么通过Kafak能够在分布式服务器之间执行原始节点相同的操作,从而保证整个分布式系统中相同数据类型的数据的高一致性。LinkedIn成功案例见:http://www.jdon.com/47156。
通过以上我个人对Jdon框架开发设计规划经历,我们发现Java世界已经形成了一个巨大生态系统,从“量子世界”(CPU并发)统一到整个“宇宙世界”(分布式架构),我们能够通过一个小小的框架直接贯穿。
作者简介:彭晨阳Jdon.com创办者和版主。软件开发设计咨询从业20年,10余年Java开发经验,拥有ERP、大型游戏、互动电视三网合一等架构经验。独立咨询顾问,个人擅长复杂系统的软件架构和领域建模。流行新技术思想的传道者,主持解道网站跟踪国际最新软件架构思想和设计技术。首个国内Java开源框架项目Jdon框架的设计者。
本文选自程序员电子版2015年5月B刊,该期更多文章请查看这里。2000年创刊至今所有文章目录请查看程序员封面秀。欢迎订阅程序员电子版(含iPad版、Android版、PDF版)。
相关推荐
- 探索Java项目中日志系统最佳实践:从入门到精通
-
探索Java项目中日志系统最佳实践:从入门到精通在现代软件开发中,日志系统如同一位默默无闻却至关重要的管家,它记录了程序运行中的各种事件,为我们排查问题、监控性能和优化系统提供了宝贵的依据。在Java...
- 用了这么多年的java日志框架,你真的弄懂了吗?
-
在项目开发过程中,有一个必不可少的环节就是记录日志,相信只要是个程序员都用过,可是咱们自问下,用了这么多年的日志框架,你确定自己真弄懂了日志框架的来龙去脉嘛?下面笔者就详细聊聊java中常用日志框架的...
- 物理老师教你学Java语言(中篇)(物理专业学编程)
-
第四章物质的基本结构——类与对象...
- 一文搞定!Spring Boot3 定时任务操作全攻略
-
各位互联网大厂的后端开发小伙伴们,在使用SpringBoot3开发项目时,你是否遇到过定时任务实现的难题呢?比如任务调度时间不准确,代码报错却找不到方向,是不是特别头疼?如今,随着互联网业务规模...
- 你还不懂java的日志系统吗 ?(java的日志类)
-
一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...
- 谈谈枚举的新用法--java(java枚举的作用与好处)
-
问题的由来前段时间改游戏buff功能,干了一件愚蠢的事情,那就是把枚举和运算集合在一起,然后运行一段时间后buff就出现各种问题,我当时懵逼了!事情是这样的,做过游戏的都知道,buff,需要分类型,且...
- 你还不懂java的日志系统吗(javaw 日志)
-
一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...
- Java 8之后的那些新特性(三):Java System Logger
-
去年12月份log4j日志框架的一个漏洞,给Java整个行业造成了非常大的影响。这个事情也顺带把log4j这个日志框架推到了争议的最前线。在Java领域,log4j可能相对比较流行。而在log4j之外...
- Java开发中的日志管理:让程序“开口说话”
-
Java开发中的日志管理:让程序“开口说话”日志是程序员的朋友,也是程序的“嘴巴”。它能让程序在运行过程中“开口说话”,告诉我们它的状态、行为以及遇到的问题。在Java开发中,良好的日志管理不仅能帮助...
- OS X 效率启动器 Alfred 详解与使用技巧
-
问:为什么要在Mac上使用效率启动器类应用?答:在非特殊专业用户的环境下,(每天)用户一般可以在系统中进行上百次操作,可以是点击,也可以是拖拽,但这些只是过程,而我们的真正目的是想获得结果,也就是...
- Java中 高级的异常处理(java中异常处理的两种方式)
-
介绍异常处理是软件开发的一个关键方面,尤其是在Java中,这种语言以其稳健性和平台独立性而闻名。正确的异常处理不仅可以防止应用程序崩溃,还有助于调试并向用户提供有意义的反馈。...
- 【性能调优】全方位教你定位慢SQL,方法介绍下!
-
1.使用数据库自带工具...
- 全面了解mysql锁机制(InnoDB)与问题排查
-
MySQL/InnoDB的加锁,一直是一个常见的话题。例如,数据库如果有高并发请求,如何保证数据完整性?产生死锁问题如何排查并解决?下面是不同锁等级的区别表级锁:开销小,加锁快;不会出现死锁;锁定粒度...
- 看懂这篇文章,你就懂了数据库死锁产生的场景和解决方法
-
一、什么是死锁加锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。任何事务都需要获得相应对象上的锁才能访问数据,读取数据的事务通常只需要获得读锁(共享锁),修改数据的事务需要获...
- 一周热门
- 最近发表
- 标签列表
-
- mydisktest_v298 (34)
- document.appendchild (35)
- 头像打包下载 (61)
- acmecadconverter_8.52绿色版 (39)
- word文档批量处理大师破解版 (36)
- server2016安装密钥 (33)
- mysql 昨天的日期 (37)
- parsevideo (33)
- 个人网站源码 (37)
- centos7.4下载 (33)
- mysql 查询今天的数据 (34)
- intouch2014r2sp1永久授权 (36)
- 先锋影音源资2019 (35)
- jdk1.8.0_191下载 (33)
- axure9注册码 (33)
- pts/1 (33)
- spire.pdf 破解版 (35)
- shiro jwt (35)
- sklearn中文手册pdf (35)
- itextsharp使用手册 (33)
- 凯立德2012夏季版懒人包 (34)
- 反恐24小时电话铃声 (33)
- 冒险岛代码查询器 (34)
- 128*128png图片 (34)
- jdk1.8.0_131下载 (34)