Java微服务开发指南 -- 使用WildFly Swarm构建微服务

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 使用WildFly Swarm构建微服务     我们最后介绍一个新的微服务框架,它构建在支持分层且可靠的JavaEE技术栈上(使用JBoss WildFly 应用服务器),WildFly Swarm是一个完全兼容WildFly应用服务器,它基于可重用的组件,这里称为元件(fractions)来组成微服务应用。

使用WildFly Swarm构建微服务

    我们最后介绍一个新的微服务框架,它构建在支持分层且可靠的JavaEE技术栈上(使用JBoss WildFly 应用服务器),WildFly Swarm是一个完全兼容WildFly应用服务器,它基于可重用的组件,这里称为元件(fractions)来组成微服务应用。组装这些元件和你使用maven或者gradle去添加依赖一样简单,你只需要声明元件,WildFly Swarm将会帮助你完成后续的工作。

    应用服务器和JavaEE在企业级Java应用的领域耕耘了快20年了,WildFly(以前叫JBoss Application Server)作为一个开源的Java应用服务器在市场上出现,企业在JavaEE技术栈上的投入非常巨大(不论是开源还是专有的供应商),包括培训、工具开发、管理等方面。JavaEE通常都是能够帮助开发人员构建分层的应用,因为它提供了诸如:servlets/JSPtransactions、组件模型、消息以及持久化等技术。JavaEE应用在部署时,将会打包成为EARs(包括了WARs或者JARs以及配置),一旦你完成了打包,你就需要找到一个应用服务器,然后安装。你可以利用应用服务器的高阶特性,比如:动态部署或者重复部署(虽然这些在生产环境上用的比较少,但是在开发态比较有用),同时你的包也利用了应用服务器的特性,只会包含必要的jar包,变得非常轻,一般只会包含所需要的业务逻辑。虽然应用的包变小了,但是应用服务器却变得很臃肿,因为它不得不包含应用所有可能需要的依赖。应用服务器中的每个JavaEE组件都会极力优化自己的依赖,同时它们之间也会相互隔离。


chapter4-1.png

    应用服务器在一个实例中提供了管理、部署以及配置多个应用的唯一入口,一般情况下为了提高可用性,会在不同的节点上部署多个实例。当越来越多的应用部署到一个应用服务器实例上后,问题开始出现,一个进程,一个JVM,很容易出问题。如果遇到多个团队开发的不同应用,都部署在一个应用服务器上,不同的应用类型、应用开发周期的不同、不同应用对于性能和SLA的要求,将会让情况变得更糟。相比微服务架构所提供的快速响应变化、创新以及自治,JavaEE应用这种将所有应用部署在单点、共享的方式就显得过于笨拙,不仅仅如此,考虑在一个单点去管理和监控多个应用就显得非常复杂。单个JVM好管理,可是在一个JVM里面放置多个应用就不那么好管理了,当我们在这个单点上使用昂贵的工具进行检测和调试找问题的时候,你就会更加感受这种痛苦了。一个解决方式就是在一个应用服务器中只部署一个应用。

    虽然微服务不屑于JavaEE环境下的开发,但是不代表组件模型、APIs以及JavaEE技术没有价值。我们仍旧能够使用持久化、事务、安全以及依赖注入等特性,我们如何将JavaEE这些技术带入到微服务中呢?WildFly Swarm就是用来做这个的。

    WildFly Swarm会根据你的pom.xml或者gradle file计算决定你需要何种JavaEE依赖,比如:CDI、新消息或者servlet,然后会将应用打包为一个统一的jar(就像Spring Boot和Dropwizard一样),这样打包的应用就包含了最小化的JavaEE环境。这个过程叫拼装刚好够用的JavaEE环境,它能让你继续使用JavaEE的API,而自由的选择使用微服务的方式运行,或者部署到传统的应用服务器中。你甚至可以将一个已经存在的WAR工程,通过WildFly Swarm将其构建成为包含了元件的微服务,而这种强大的能力使得你可以迅速的将一个已有的项目转化成为一个微服务部署模式的应用。

开始

    一般有三种方式使用WildFly Swarm,第一种是创建一个空的maven或者gradle项目,然后手动的添加依赖和maven插件。另一种就是使用类似Spring Initializer的控制台 -- WildFly Swarm Generator web console,最后一种是使用jboss-forge。我们强烈的建议使用jboss-forge来进行工程的创建,从完整性上考虑,我们会创建一个简单的工程,同时jboss-forge有插件支持流行的Java IDE,比如:Eclipse、Netbeans和IDEA。

香草Java工程

    如果你有一个已经存在的Java工程,你可以通过修改一下pom.xml来让其变为一个WildFly Swarm,首先添加一个WildFly Swarm插件。

<plugin>
  <groupId>org.wildfly.swarm</groupId>
  <artifactId>wildfly-swarm-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>package</goal>
      </goals>
    </execution>
  </executions>
</plugin>

    如果项目想使用JavaEE的依赖,可以选择依赖WildFly DOM(bill of materials),在<dependencyManagement>元素下增加以下内容:

<dependencyManagement>
    <dependencies>
        <!-- JBoss distributes a complete set of Java EE 7 APIs
            including a Bill of Materials (BOM). A BOM specifies
            the versions of a "stack" (or a collection) of
            artifacts. We use this here so that we always get
            the correct versions of artifacts. -->
            <dependency>
              <groupId>org.wildfly.swarm</groupId>
              <artifactId>bom</artifactId>
              <version>${version.wildfly.swarm}</version>
              <type>pom</type>
              <scope>import</scope>
            </dependency>
    </dependencies>
</dependencyManagement>

    现在你可以添加其他的JavaEE元件(或者你可以进行使用自己的依赖,让WildFly Swarm自己侦测依赖),接下来让我们看看jboss-forge如何构建工程。

笔者尝试将hola-backend按照如上方式改成WildFly Swarm,但是结果并不如意
尝试改造已有的web工程,结果也不好,可以看到这种方式只是一种点缀

使用JBoss Forge

    jboss-forge是一个构建java项目的IDE插件和基于命令行的工具集,能够在Netbeans、Eclipse和IDEA中提供这些功能,帮助开发人员创建java项目、添加CDI beans,或者配置servlets。首先运行环境需要使用JDK/Java 1.8,在这个基础上进行安装 JBoss Forge

    一旦你安装了jboss-forge,你可以在命令行下通过键入:forge,启动它。

在mac下使用Homebrew可以安装它,运行:brew install jboss-forge就可以了

    你可以使用Tab键来获得提示并让命令自动完成,jboss-forge是一个基于模块化插件体系构建的工具,它支持其他用户对插件体系将进行扩展,你可以在这里找到扩展的插件addons contributed by the community,有很多插件可以选择,比如:AsciiDoctorTwitterArquillian以及AssertJ,我们先用jboss-forge安装WildFly Swarm。

[temp]$ addon-install --coordinate org.jboss.forge.addon:wildfly-swarm,1.0.0.Beta2
***SUCCESS*** Addon org.jboss.forge.addon:wildfly-swarm,1.0.0.Beta2 was installed successfully.

笔者查看了WildFly Swarm文档,推荐这么安装最新版:addon-install-from-git --url https://github.com/forge/wildfly-swarm-addon.git --coordinate org.jboss.forge.addon:wildfly-swarm

    进入jboss-forge后,可以使用project-new来进行项目的创建。接下来我们创建一个WildFly Swarm项目:hola-wildflyswarm,并且为这个应用添加REST以及WildFly Swarm的支持。

可以通过wildfly-swarm-run来启动项目,但是退出项目遇到点小问题


chapter4-2.png

    我们将工程导入到IDE中,可以看到一个应用的骨架,如果我们打开pom.xml,会看到相关的JavaEEAPIs以及WildFly Swarm插件。

<build>
  <finalName>hola-wildflyswarm</finalName>
  <plugins>
    <plugin>
      <groupId>org.wildfly.swarm</groupId>
      <artifactId>wildfly-swarm-plugin</artifactId>
      <version>${version.wildfly-swarm}</version>
      <executions>
        <execution>
          <goals>
            <goal>package</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
<properties>
  <failOnMissingWebXml>false</failOnMissingWebXml>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <version.wildfly-swarm>2017.6.1</version.wildfly-swarm>
</properties>
<dependencies>
  <dependency>
    <groupId>org.jboss.spec.javax.servlet</groupId>
    <artifactId>jboss-servlet-api_3.0_spec</artifactId>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>org.jboss.spec.javax.ws.rs</groupId>
    <artifactId>jboss-jaxrs-api_1.1_spec</artifactId>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <scope>provided</scope>
  </dependency>
</dependencies>
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.jboss.spec</groupId>
      <artifactId>jboss-javaee-6.0</artifactId>
      <version>3.0.3.Final</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.wildfly.swarm</groupId>
      <artifactId>bom-all</artifactId>
      <version>${version.wildfly-swarm}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

    记住,WildFly Swarm只会打包你需要的JavaEE框架,在这个例子中,我们首先添加了JAX-RS(rest-setup),所以WildFly Swarm会自动包含JAX-RS以及servlet元件,并将它们打包到你的应用中。

在WildFly Swarm中,有三个类型的类加载器,首先是启动它的SystemClassLoader,第二个是应用的类加载器,也就是用来执行用户代码的地方,最后一个是WildFly,有理由相信,WildFly Swarm利用了JBoss模块化技术,而这个技术的运用,使得应用代码只需要依赖标准的API,而具体的JavaEE实现和自己已经隔离开来

添加HTTP端点

    现在在jboss-forge下,使用rest-new-endpoint添加一个JAX-RS端点。

进入到hola-wildflyswarm目录下,执行forge

    在IDE中,可以看到已经创建了一个类HolaResource

@Path("/api/holaV1")
public class HolaResource {

    @GET
    @Produces("text/plain")
    public Response doGet() {
        return Response.ok("method doGet invoked").build();
    }
}

    我们可以通过在jboss-forge中运行wildfly-swarm-run将应用启动起来,打开浏览器访问:http://localhost:8080/api/holaV1,会看到如下页面。


chapter4-4.png

    是不是很快,我们做了些什么?我们使用jboss-forge构建了一个JAX-RS的web应用,它使用原生的JavaEE技术,能够以微服务的形式运行。

外部配置

    本文编写的时候,WildFly Swarm还没有一种方式进行外部配置,也没有一套配置框架,例如:Apache Commons Configuration或者Apache DeltaSpike Configuration组件。如果想要使用WildFly Swarm自己提供的配置功能,可以关注this JIRA thread。在本章中,将使用Apache DeltaSpike Configuration来完成配置。

翻译本文时,WildFly Swarm配置已经可以使用,访问这里:Swarm Config

Apache DeltaSpike Configuration是一个2014年的Duke选择奖获得者,也非常不错

    Apache DeltaSpike Configuration是一个CDI扩展的集合,用来简化诸如:配置、数据获取以及安全等方面,接下来就需要使用CDI扩展来将配置注入到代码中,而配置的来源能够是命令行、属性文件、JNDI或者环境变量。首先添加CDI的依赖。

<dependency>
   <groupId>org.wildfly.swarm</groupId>
   <artifactId>jaxrs-cdi</artifactId>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>org.apache.deltaspike.core</groupId>
   <artifactId>deltaspike-core-api</artifactId>
   <version>1.5.3</version>
</dependency>
<dependency>
   <groupId>org.apache.deltaspike.core</groupId>
   <artifactId>deltaspike-core-impl</artifactId>
   <version>1.5.3</version>
</dependency>

    由于使用了Apache DeltaSpike Configuration,使用它需要创建META-INF/apache-deltaspike.properties,在这个配置中放置我们需要的配置。


chapter4-3.png

    这样针对变量WF_SWARM_SAYING,就可以注入这个值了,下面创建HolaResource2

@Path("/api/holaV2")
public class HolaResource2 {

    @Inject
    @ConfigProperty(name = "WF_SWARM_SAYING", defaultValue = "Hola")
    private String saying;

    @GET
    @Produces("text/plain")
    public Response doGet() {
        return Response.ok(saying + " from WF Swarm").build();
    }
}

    可以看到如果没有WF_SWARM_SAYING配置,将会默认使用Hola,接着我们打包运行。

$ mvn clean package
$ java -jar target/hola-wildflyswarm-swarm.jar

    打开浏览器,访问:http://localhost:8080/api/holaV2,可以看到以下内容。


chapter4-5.png

    我们停止应用,然后导出一个环境变量,然后再启动应用。

$ export WF_SWARM_SAYING=Yo
$ java -jar target/hola-wildflyswarm-swarm.jar

    打开浏览器,再次访问:http://localhost:8080/api/holaV2,可以看到内容已经变化。


chapter4-6.png

暴露应用Metrics和信息

    暴露应用的Metrics十分简单,只需要添加一个依赖一个maven坐标即可,添加坐标:

<dependency>
    <groupId>org.wildfly.swarm</groupId>
    <artifactId>monitor</artifactId>
</dependency>

    它将启动WildFly管理以及监控功能,从监控的角度看,WildFly Swarm暴露了一些基本的Metrics:

  • /node
    当前部署节点的信息
  • /heap
    堆信息
  • /threads
    Java的线程信息

    当然也可以自定义添加一些端点用于检查微服务是否运作正常,你可以检测集群中哪台机器上的微服务是否工作正常,如果想了解详细的信息可以查看WildFly Swarm documentation

调用其他服务

    在微服务环境下,服务之间是会进行相互调用的,如果我们想使用之前的服务,就需要使用JAX-RS客户端,就像之前在Spring Boot微服务下调用books接口一样。


chapter4-7.png

    接下来创建一个类型GreeterResource,使用JAX-RS客户端访问hola-backend,由于使用了JAX-RS,所以与hola-dropwizard的代码有些类似。

@Path("/api")
public class GreeterResource {

    @Inject
    @ConfigProperty(name = "GREETING_BACKEND_SERVICE_HOST",
            defaultValue = "localhost")
    private String backendServiceHost;
    @Inject
    @ConfigProperty(name = "GREETING_BACKEND_SERVICE_PORT",
            defaultValue = "8080")
    private int backendServicePort;

    @Path("/greeting/{bookId}")
    @GET
    public String greeting(@PathParam("bookId") Long bookId) {
        String backendServiceUrl = String.format("http://%s:%d",
                backendServiceHost, backendServicePort);
        System.out.println("Sending to: " + backendServiceUrl);
        Client client = ClientBuilder.newClient();
        Map map = client.target(backendServiceUrl).path("hola-backend").path("rest").path("books").path(
                bookId.toString()).request().accept("application/json").get(Map.class);

        return map.toString();
    }
}

    在hola-wildflyswarm目录下,执行mvn clean package,完成应用的打包。在运行应用前,需要指定hola-backend服务端的位置,我们可以通过环境变量指定。

$ export GREETING_BACKEND_SERVICE_HOST="11.239.175.192"
$ java -jar target/hola-wildflyswarm-swarm.jar

    打开浏览器访问:http://localhost:8080/api/greeting/1,可以看到如下展示。


chapter4-8.png

小结

    通过本章内容,介绍了WildFly Swarm的基本使用方式,以及同Dropwizard和Spring Boot的对比,了解到如何暴露REST端点、配置、Metrics以及调用外部服务。快速的介绍WildFly Swarm不能面面俱到,下面是深入了解它的一些资源。

由于使用了jboss-module模块化系统启动应用,WildFly Swarm启动的速度慢于Spring Boot和Dropwizard,但是其隔离的体现,使得应用的jar包非常简单,旧有的JavaEE迁移会有优势,官方更新速度很快,但是小问题也很多

目录
相关文章
|
1天前
|
存储 Java API
Java语法基础:构建编程世界的基石
Java语法基础:构建编程世界的基石
|
1天前
|
运维 监控 Docker
构建高效微服务架构:从理论到实践构建高效自动化运维体系:Ansible与Docker的完美融合
【5月更文挑战第31天】 在当今软件开发的世界中,微服务架构已经成为了实现可伸缩、灵活且容错的系统的关键策略。本文将深入探讨如何从零开始构建一个高效的微服务系统,涵盖从概念理解、设计原则到具体实施步骤。我们将重点讨论微服务设计的最佳实践、常用的技术栈选择、以及如何克服常见的挑战,包括服务划分、数据一致性、服务发现和网络通信等。通过实际案例分析,本文旨在为开发者提供一套实用的指南,帮助他们构建出既健壮又易于维护的微服务系统。
|
1天前
|
Kubernetes Cloud Native 开发者
构建高效云原生应用:Kubernetes与微服务架构的融合
【5月更文挑战第31天】 在数字化转型和技术迭代的大潮中,企业对于敏捷、可扩展的IT基础设施需求日益增长。云原生技术以其独特的优势成为推动这一进程的关键力量。本文深入探讨了如何通过结合Kubernetes容器编排和微服务架构来构建和维护高效、可靠的云原生应用。我们将剖析这种技术整合的必要性,揭示其背后的原理,并讨论在实际部署过程中可能遇到的挑战及解决方案。通过案例分析和最佳实践的分享,旨在为开发者和架构师提供一套行之有效的云原生应用构建指南。
|
1天前
|
敏捷开发 Kubernetes Cloud Native
构建高效云原生应用:容器化与微服务架构的融合
【5月更文挑战第31天】 随着云计算技术的不断演进,云原生应用已成为企业数字化转型的核心。本文深入探讨了如何通过容器化技术和微服务架构的有效结合,构建高效、弹性和可扩展的云原生应用。我们将分析容器化的基本概念、优势以及它如何促进微服务架构的实施,同时提供策略和最佳实践,帮助企业实现敏捷开发和持续部署,优化资源利用,并提高系统的可靠性。
|
2天前
|
缓存 监控 开发者
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第30天】在软件开发的世界中,微服务架构已经成为一种流行且高效的设计模式,它通过将大型应用程序分解成一组小的、独立的服务来提高可伸缩性和灵活性。本文深入探讨了微服务的核心概念、优势以及如何在后端开发中实现一个健壮的微服务架构。我们将讨论关键的设计原则、技术选型和常见的挑战,并提供解决方案和最佳实践以指导开发者构建出能够适应快速变化需求的系统。
|
2天前
|
消息中间件 监控 架构师
构建高效微服务架构:从理论到实践
【5月更文挑战第30天】 在当今快速迭代和竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性和独立部署能力受到企业的青睐。然而,随着服务的增多,确保系统的高效性和稳定性成为开发团队必须面对的挑战。本文将深入探讨构建高效微服务架构的关键策略,包括服务划分、通信机制、数据一致性和容错处理,并通过具体实例分析如何在不牺牲系统性能的前提下实现服务的解耦与自治。文章旨在为开发人员和架构师提供一套实用的方法论,帮助他们在设计和维护微服务系统时做出明智的决策。
|
2天前
|
Kubernetes 开发者 Docker
构建高效微服务架构:Docker与Kubernetes的协同应用
【5月更文挑战第30天】 在当今软件开发领域,微服务架构已成为实现系统模块化、提升可维护性及扩展性的关键策略。本文深入探讨了如何通过Docker容器化技术和Kubernetes集群管理,共同构建一个既高效又可靠的后端微服务环境。我们将剖析Docker和Kubernetes的核心功能,以及它们如何相辅相成,支撑起现代化的云原生应用程序部署和管理。文章还将提供具体实践案例,帮助开发者理解将理论应用于实际开发过程中的步骤和考虑因素。
|
2天前
|
消息中间件 Java 数据库
构建高效可靠的微服务架构:后端开发的终极指南
【5月更文挑战第30天】 随着现代软件开发的复杂性日益增加,微服务架构已成为组织解决庞大系统问题的有效手段。本文将深入探讨如何构建一个既高效又可靠的微服务系统,涉及关键组件的选择、网络通信的最佳实践以及保证系统稳定性的策略。通过一系列实际案例与性能分析,我们将揭示后端开发在设计微服务时必须考虑的核心要素,并提供一套综合性解决方案,以指导读者实现强大的后端架构。
|
2天前
|
监控 数据管理 开发者
构建高效微服务架构:后端开发的现代实践
【5月更文挑战第30天】 在当今软件开发领域,微服务架构已成为提高系统可维护性、扩展性和开发效率的关键方案。本文深入探讨了构建高效微服务架构的策略,包括服务划分原则、通信机制、数据管理以及持续集成与部署的最佳实践。通过分析具体案例和最新技术趋势,文章旨在为后端开发者提供一套全面的指导,帮助他们在不断变化的技术环境中保持竞争力。
|
2天前
|
监控 关系型数据库 持续交付
构建高效微服务架构:后端开发的最佳实践
【5月更文挑战第30天】随着现代应用的复杂性日益增加,微服务架构已成为众多企业和开发者的首选。本文将深入探讨如何构建一个高效的微服务系统,包括关键的设计原则、技术栈选择、以及确保系统稳定性和扩展性的实践方法。我们将通过实际案例分析,揭示后端开发中实现敏捷性和可维护性的策略,为追求卓越的软件工程师提供实用的指导。