java ee的小程序_Java EE应用程序的单片到微服务重构

java ee的小程序

您是否曾经想过将现有的Java EE单体应用程序重构为基于微服务的应用程序需要做什么?

该博客说明了一个简单的购物车示例如何转换为基于微服务的应用程序,以及围绕它的一些担忧。 整体和基于微服务的应用程序的完整代码库位于: github.com/arun-gupta/microservices 。

继续阅读以获取更多荣耀!

Java EE Monolith

Java EE整体应用程序通常定义为WAR或EAR档案。 该应用程序的全部功能都打包在一个单元中。 例如,在线购物车可能包含用户,目录和订单功能。 所有网页都在应用程序的根目录中,所有相应的Java类都在WEB-INF/classes目录中,资源在WEB-INF/classes/META-INF目录中。

让我们假设您的整体设计不是设计成一个分散的大泥巴 ,而应用程序是按照良好的软件体系结构构建的。 一些常见的规则是:

  • 分离关注点,可能使用Model-View-Controller
  • 使用定义明确的API的高内聚和低耦合
  • 不要重复自己(干)
  • 接口/ API和实现是分开的,并且遵循Demeter定律 。 类不会直接调用其他类,因为它们恰好位于同一存档中
  • 使用域驱动设计将与域/组件相关的对象保持在一起
  • YAGNI或您不需要它:不要构建您现在不需要的东西

这是一个简单的购物车整体WAR存档的样子:

javaee-monolithic

此整体应用程序具有:

  • 网页,例如.xhtml文件,用于用户,目录和订单组件,打包在归档的根目录中。 这些网页还打包了在不同网页之间共享的所有CSS和JavaScript资源。
  • 这三个组件的类在WEB-INF/classes目录中的单独软件包中。 多个类使用的所有实用程序/公共类也都打包在这里。
  • 每个组件的配置文件打包在WEB-INF/classes/META-INF目录中。 该应用程序的任何配置文件(例如分别连接和填充数据存储的persistence.xmlload.sql也都打包在此处。

它具有众所周知的体系结构,IDE友好,易于共享,简化测试,易于部署等常见优点 。 但同时也具有诸如敏捷性受限,持续交付的障碍,技术堆栈“卡住”,技术债务增加等缺点 。

即使微服务如今已成为热门,但整体还是不错的。 即使那些对您不起作用的企业,也可能不会从迁移到微服务中获得很多或立即的收益。 其他方法(如更好的软件工程和体系结构)可能会有所帮助。 微服务既不是免费的午餐也不是灵丹妙药,它需要大量的投资才能成功,例如服务发现,服务复制,服务监视,容器,PaaS,弹性等等。

除非您的系统过于复杂而无法作为一个整体进行管理,否则甚至不要考虑使用微服务。

微服务高级版

Java EE的微服务架构

好了,我已经听说了所有这些内容,但是想知道之前/之后的内容,即整体代码库的外观以及重构后的微服务代码库的外观。

首先,让我们看一下整体架构:

javaee-microservices

此体系结构中的关键部分是:

  • 在将用户,订单和目录组件打包为单独的WAR文件的情况下,应在功能上分解应用程序。 每个WAR文件应具有该组件所需的相关网页( #15 ),类和配置文件。
    • Java EE用于实现每个组件,但是对堆栈没有长期承诺,因为不同的组件使用定义良好的API( #14 )相互通信。
  • 每个档案都有自己的数据库,即不共享数据存储。 这允许每个微服务发展和选择最合适的数据存储类型-关系,NoSQL,平面文件,内存中或其他。
  • 每个组件都将向服务注册中心注册。 这是必需的,因为每个服务的多个无状态实例可能在给定的时间运行,并且它们的确切端点位置仅在运行时才知道( #17 )。 Netflix Eureka , Etcd , Zookeeper是该领域的一些选项( 更多详细信息 )。
  • 如果组件需要相互通信(这很常见),则可以使用预定义的API进行通信。 实现同步的REST或实现异步通信的Pub / Sub是实现此目的的常用方法。在我们的案例中,Order组件发现用户和目录服务,并使用REST API与它们进行对话。
  • 该应用程序的客户端交互是在另一个应用程序(在本例中为Shopping Cart UI)中定义的。 该应用程序主要从服务注册表中发现服务并将它们组合在一起。 它应该主要是一个哑代理,在其中调用不同组件的UI页面以显示界面( #18 )。可以通过提供标准CSS / JavaScript资源来实现常见的外观。

该应用程序相当琐碎,但至少强调了一些基本的体系结构差异。

整体与微服务

下面比较了基于单体和基于微服务的应用程序的一些统计信息:

特性 整体式 微服务
档案数量 1个 5
  • 合同(JAR,〜4 KB)
  • 顺序(WAR,〜7 KB)
  • 用户(WAR,〜6 KB)
  • 目录(WAR,〜8 KB)
  • Web UI(WAR,27 KB)
网页 8 8(见下文)
配置文件 4
  • web.xml
  • template.xhtml
  • persistence.xml
  • load.sql
每个档案3个
  • persistence.xml
  • load.sql
  • web.xml
类文件 12 26
  • 每个档案的服务注册
  • 服务发现类
  • 每个档案的应用程式类别
档案总大小 24 KB 〜52 KB(总计)

  • 整体应用程序的代码库位于: github.com/arun-gupta/microservices/tree/master/monolith/everest
  • 支持微服务的应用程序的代码库位于: github.com/arun-gupta/microservices/tree/master/microservice

问题和待办事项

以下是将整体重构为基于微服务的应用程序时遇到的问题和TODO:

  • Java EE已经可以使用EAR封装对应用程序进行功能分解。 应用程序的每个组件都可以打包为WAR文件,并捆绑在EAR文件中。 他们甚至可以通过这种方式共享资源。 现在这不是真正的微服务方式,但这可能是使您入门的过渡步骤。 但是,请注意, @FlowScoped bean没有在EAR中正确激活( WFLY-4565 )。
  • 使用JSF资源库模板提取所有模板文件。
    • 目前,所有网页都在everest模块中,但它们应该位于每个组件中( #15 )。
  • 将整体数据库拆分为多个数据库需要为每个应用程序使用单独的persistence.xml和DDL / DML脚本。 同样,需要相应地创建迁移脚本,例如使用Flyway。
  • 必须为所有组件创建一个REST接口,该接口需要被另一个组件访问。
  • UI仍在单个Web应用程序中。 而是应将其包含在已分解的WAR( #15 )中,然后再次在哑代理中进行组合。 闻起来像portlet吗?
  • 在PaaS中部署多个WAR文件( #12 )
  • 每个微服务都应易于部署在容器中( #6 )

这是单片应用程序的类的完整列表:

./target/classes/org/javaee7/wildfly/samples/everest/cart/Cart.class
./target/classes/org/javaee7/wildfly/samples/everest/cart/CartItem.class
./target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItem.class
./target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItemBean.class
./target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItemType.class
./target/classes/org/javaee7/wildfly/samples/everest/checkout/Order.class
./target/classes/org/javaee7/wildfly/samples/everest/checkout/OrderBean.class
./target/classes/org/javaee7/wildfly/samples/everest/checkout/OrderItem.class
./target/classes/org/javaee7/wildfly/samples/everest/checkout/Shipping.class
./target/classes/org/javaee7/wildfly/samples/everest/uzer/Uzer.class
./target/classes/org/javaee7/wildfly/samples/everest/uzer/UzerBean.class
./target/classes/org/javaee7/wildfly/samples/everest/uzer/UzerItem.class

这是基于微服务的应用程序的类的完整列表:

./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/ApplicationConfig.class
./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItem.class
./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItemREST.class
./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItemType.class
./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/ServiceRegistration.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/cart/Cart.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/cart/CartItem.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogBean.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItem.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/checkout/Order.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/checkout/OrderBean.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/checkout/OrderItem.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/checkout/Shipping.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/ServiceDiscovery.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/ServiceDiscoveryStatic.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/ServiceDiscoveryURI.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/ServiceDiscoveryZooKeeper.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/uzer/UzerBean.class
./everest/target/classes/org/javaee7/wildfly/samples/everest/uzer/UzerItem.class
./order/target/classes/org/javaee7/wildfly/samples/everest/order/ApplicationConfig.class
./order/target/classes/org/javaee7/wildfly/samples/everest/order/Order.class
./order/target/classes/org/javaee7/wildfly/samples/everest/order/OrderItem.class
./order/target/classes/org/javaee7/wildfly/samples/everest/order/OrderREST.class
./user/target/classes/org/javaee7/wildfly/samples/everest/uzer/ApplicationConfig.class
./user/target/classes/org/javaee7/wildfly/samples/everest/uzer/UserREST.class
./user/target/classes/org/javaee7/wildfly/samples/everest/uzer/Uzer.class
  • 同样,完整的代码库位于github.com/arun-gupta/microservices 。

未来话题

本系列中的一些未来主题将是:

  • 微服务是否需要容器?
  • 如何使用容器部署多个微服务?
  • 如何轻松监控所有这些服务?
  • A / B测试
  • 使用微服务和容器进行连续部署

您还想看些什么?

请享用!

翻译自: https://www.javacodegeeks.com/2015/06/monolithic-to-microservices-refactoring-for-java-ee-applications.html

java ee的小程序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337786.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab工程计算及应用 课程名称,《 MATLAB 工程计算及应用》教学大纲课程名称MATLAB 工程计算及应用.pdf...

《MATLAB 工程计算及应用》教学大纲课程名称 MATLAB 工程计算及应用 课程编号 02T5071课程英文名称 Applications of MATLAB课程性质 选修 学时和学分 32(上机 10)/1 适用专业 工科各专业大纲执笔人 蔡哓君、郭炜 审核人 蔡晓君 先修要求 高等数学、线性代数一、课程基本目的&a…

C语言数据结构:什么是树?什么是二叉树?

点击蓝字关注我们前言在之前的数据结构学习中,我们学习了顺序表、链表、栈、队列这几种结构它们都是用链表或者数组的方式来实现的,主要考察我们对结构体的运用今天让我们来学习一个新的数据结构,也就是下面这副图里面的树啊不好意思&#xf…

git hok json_从战中反弹:将Git提交信息作为JSON返回

git hok json在某些情况下,我们必须知道部署到远程服务器的Web应用程序的确切版本。 例如,客户可能想知道我们是否已经在服务器X上部署了错误修复程序。 当然,我们可以尝试使用“传统”方法找到该问题的答案。 问题是: 没有人不…

oracle plsql异常,【Oracle篇】异常处理和PLSQL

一、所有的PL/SQL异常都具有以下几个基本特征: 错误类型:表示了错误是ORA错误还是PLS错误 错误代号:一串表示错误代号的数字 错误文本:错误消息文本,包括错误代号 二、PL/SQL会产生两种类型的错误 : ORA错误…

如何把CPP源程序改写成C语言?

点击蓝字关注我们曾经参与过公司的bpp项目,就是bluetooth print profile。由于使用了hpijs的开源包,但是是C++的。由于C++解释器比C语言解释器占用的存储空间要大500k左右。为了节省有限的存储空间&#xf…

php cdi_使用Fabric8在CDI管理的bean中注入Kubernetes Services

php cdi序幕 我在Kubernetes中最喜欢的是发现服务的方式。 为什么? 主要是因为用户代码不必处理注册,查找服务,也没有网络意外(如果您曾经尝试过基于注册表的方法,那么您就会知道我在说什么) 。 这篇文章…

oracle日志恢复启用命令,oracle 日志恢复数据详解

1:首先查找redo,如果redo有可供恢复的信息,就那redo中的信息进行恢复,此时一般在恢复时,类似如下:SQL> recover database;Media recovery complete.2:如果在redo中没有找到可供恢复的信息,or…

9 个很酷的 CMD 命令

点击蓝字关注我们ipconfig功能:查询本机IP地址操作方法:只要在在打开的cmd命令界面中输入“ipconfig”就可以了。msg功能:向对方电脑发送一条文本提示操作方法:首先你要知道对方的IP地址,接下来输入命令“msg /server:…

使用java进行婚礼庆祝_#102030:在30天内运行20 10K,庆祝Java 20年

使用java进行婚礼庆祝1995年5月23日是技术史上的重要时刻。 业界似乎并未意识到当天发布的语言会在未来几年内完全改变技术的格局。 Java将在今年的同一天庆祝20岁生日。 Java 20年,哇! 回顾20年前的存储器时代,思考一下Java的发明时间/方式…

oracle 插入出错_使用sqlca打印错误原因,ORACLE-Proc:SQLCA

SQL 通信区是用下列语句描述的:EXEC SQL INCLUDE SQLCA;此部分提供了用户运行程序的成败记录和错误处理。SQLCA的组成SQLCA是一个结构类型的变量,它是ORACLE 和应用程序的一个接口。在执行 Pro*C程序时, ORACLE 把每一个嵌入SQL语…

这几行 C++ 代码,真的骚!

点击蓝字关注我们事情是这么一回事:国外有个大佬在StackExchange上发起了一个叫做 Tweetable Mathematical Art 的比赛。参赛者需要用C编写代表三原色的RD、GR、BL三个函数,每个函数都不能超过 140 个字符。每个函数都会接到 i 和 j 两个整型参数&#x…

sts集成jboss_JBoss BPM Travel Agency演示与现代BPM数据集成

sts集成jboss不久前,我们启动了一个规模较大的JBoss Travel Agency演示项目,以展示JBoss BPM Suite的一些更有趣的功能。 我们提供了一系列视频 ,不仅向您展示了如何安装它,项目中各种规则和流程工件的含义,还向您介绍…

详解C语言的C#数组

点击蓝字关注我们数组是一种存储相同类型元素的固定大小顺序集合。数组用于存储数据集合,但一般会将数组视为存储在连续存储器位置的相同类型的变量的集合。如果要存储表示100名称学生的分数,需要独立地声明100整数变量。例如:number0.number…

jdk注解_我们正在下注:这个注解很快就会出现在JDK中

jdk注解Yahor最近提出的Stack Overflow问题引起了我的兴趣: 如何在Java 8编译时确保方法签名“实现”功能接口 。 这是一个很好的问题。 让我们假设以下名义类型: FunctionalInterface interface LongHasher {int hash(long x); }该类型强加了清晰的合同…

oracle的连接函数,Oracle各种连接函数总结

1.前言Oracle可用连接函数会介绍以下几个Oracle列转行函数 Listagg()strcat()wmsys.wm_concat()2.Oracle列转行函数 Listagg()2.1最基础的用法:LISTAGG(XXX,XXX) WITHIN GROUP( ORDER BY XXX)用法就像聚合函数一样,通过Group by语句,把每个Gr…

抽象工厂模式设计模式_21世纪的设计模式:抽象工厂模式

抽象工厂模式设计模式这是我的演讲的第二部分,“ 21世纪的设计模式” 。 此模式在Java代码中到处都有使用,尤其是在更多“企业”代码库中。 它涉及一个接口和一个实现。 该界面如下所示: public interface Bakery {Pastry bakePastry(Toppi…

对 C 语言指针最详尽的讲解

点击蓝字关注我们指针对于C来说太重要。然而,想要全面理解指针,除了要对C语言有熟练的掌握外,还要有计算机硬件以及操作系统等方方面面的基本知识。所以本文尽可能的通过一篇文章完全讲解指针。为什么需要指针?指针解决了一些编程…

app http routes.php,Laravel:我的应用程序没有被路由(Laravel : My app doesn't get routed)

Laravel:我的应用程序没有被路由(Laravel : My app doesnt get routed)我正在运行我的第一个laravel应用程序,在接下来的几个小时中遇到依赖项安装错误。对不起它可能是一个小错误,但似乎我无法找到。图片较暗,电脑坏了。应用程序…

ssm 返回json配置_摆脱困境:将运行时配置作为JSON返回

ssm 返回json配置如果需要确定部署到远程服务器的Spring Web应用程序的运行时配置,则需要读取从远程服务器找到的属性文件。 这很麻烦。 幸运的是,有更好的方法。 这篇博客文章描述了我们如何 启动我们的Web应用程序时,将运行时配置写入日志…

为什么 Android 必须在主线程更新 UI ?

点击蓝字关注我们为什么Android必须在主线程更新UI?站在各位大牛的肩膀上,谢谢!正常情况下,Android需要在UI线程更新UI,然鹅,在特殊情况下,子线程也能更新UI不在讨论之列,这篇文章主…