如何使用 Java 构建微服务?
【编者按】微服务背后的大理念是将大型、复杂且历时长久的应用在架构上设计为内聚的服务,这些服务能够随着时间的流逝而演化。本文主要介绍了利用 Java 生态系统构建微服务的多种方法,并分析了每种方法的利弊。
快速预览
-
在 Java 生态系统中构建微服务的策略主要有:container-less, self-contained 和 in-container;
-
Container-less 微服务把应用程序及其所有依赖打包成单一的 jar 文件;
-
Self-contained 微服务也会将应用及其依赖打包成单一的Jar文件,但它还包含可能含有第三方库的嵌入式框架;
-
In-container 微服务会打包一个完整的 Java EE 容器,并且它的服务是在 Docker image 中实现。
基于微服务的架构设计是架构师和程序员们面临的一项新挑战。然而,随着语言及工具的不断更新,架构师们完全有能力征服这样的挑战。 Java 也不例外,本文探讨了使用Java生态系统来构建微服务的几种不同方式。
介绍
本文不会讨论微服务的好与坏,也不会建议你提前为微服务设计应用程序,或当它们出现在你庞大的应用中时,是否应该剥离这些微服务。
本文介绍的方法并不是唯一的,但应该可以达到抛砖引玉的效果。尽管本文的重点是使用 Java 生态系统来构建微服务,但这些概念同样可以转移到其它语言和技术中。
笔者把本文用到的方法命名为 container-less、self-contained 和 in-containe。这些名称或许不是非常正式,但足以区分相互间的差别。接下来,笔者会详细描述每种方法。
Container-less
在此方法中,开发者会将 JVM 之上的任何事物视为应用程序的一部分。
container-less 方法会启用所谓的单 jar 部署(也可称作“fat jar部署”),这也就意味着,应用程序及其所有依赖都会被打包成单一的jar文件,并且作为独立的Java进程运行。
$ java -jar myservice.jar
该方法的第一个优点就是当对应用的规模进行伸缩时,服务很容易按需求快速启动和停止;另一优点是方便部署,你只需要传递一个 jar 文件即可。
该方法的缺点就是库的兼容性。对于事务支持这类问题,你需要自己来实现,或必须引入第三方库才能实现。而后,如果你需要更多支持,例如持续性问题的支持,你就需要解决第三方库之间的兼容性问题。
Self-contained
另一种单 jar 部署就是使用一个嵌入式框架来构建服务。在此方法中,框架提供了所需服务的实现方法,开发者可以选择在项目中包括哪些服务。
你可能会认为这个方法与 container-less 完全一样,但笔者认为,两者的区别在于,self-contained 方法会提供一套相互兼容的第三方库。所以,该方法不存在库兼容性问题。
该方法可能涉及 Spring Boot、Wildfly Swarm 之类的工具。
Spring Boot
在Java中, Spring Boot 和 Spring Cloud Netflix 项目对构建微服务提供了很好的支持。 Spring Boot 允许你选择各种 Spring 工具和其它流行的工具,然后把它们和你的应用打包成一个 jar 文件。 Spring Initializr 提供了一个简单的复选框列表来完成上面这些事。一个简单的Hello World服务示例如下: Gist Snippet
Wildfly Swarm
在 Java EE 中,和 Spring Boot 相对应是 Wildfly Swarm 。它允许你根据自己的需求挑选 Java EE 规范,然后把它们和你的应用程序打包成一个 jar 文件。这里有一个简单的 Hello World 示例: Gist Snippet。
self-contained 方法的优点是你可以自主选择用于服务运行的项目。
这种方法的缺点是配置更加复杂,由于它在实际的服务中构建所需的容器功能,由此产生的 jar 文件也会稍大一些。
In-container
虽然在 Java EE 容器中部署微服务的开销似乎很大,然而,一些开发者认为,微服务中的“微”并不表示该服务的小或者简单。
在这些案例中,将 Java EE 容器作为所需平台似乎是合适的。因此,你唯一需要的依赖就是 Java EE API 。注意,由于该依赖的实现是由容器提供的,因此该依赖项已经满足了,这也就意味着所产生的 war 文件是非常精简的,该服务的实现与上面 Wildfly Swarm 的例子是一样的: Gist Snippet。
该方法的优点是,容器通过标准 API 提供了经过测试和验证的标准功能的实现。因此,开发者可以完全聚焦于业务功能,并在应用代码之外维护底层代码。
另一个优点是,应用程序代码不依赖 Java EE 应用服务器,无论该应用部署到 GlassFish、 WildFly、 WebLogic、 WebSphere 还是任何与 Java EE 兼容的其他实现系统。
该方法的缺点是你需要把服务部署到容器中,这样就增加了部署的复杂性。
Docker
现在来谈谈 Docker 。通过把 Java EE 容器和服务实现打包到 Docker 镜像,你可以得到与单一 jar 部署相似的结果。唯一的不同是服务打包在 Docker 镜像中,而不是在 jar 文件中。
Dockerfile
FROM jboss/wildfly:9.0.1.Final
ADD myservice.war /opt/jboss/wildfly/standalone/deployments
在 Docker 引擎中启动 Docker 镜像可以唤醒服务:
$ docker run -it -p 8081:8080 myorganization/myservice
Snoop
细心的读者可能已经在先前的 Spring Boot 代码段中注意到了 @EnableEurekaClient 注解。该注解在 Eureka 中注册服务,使其能够被服务消费者发现。 Eureka 是 Spring Cloud Netflix 包的一部分,并且是一个极易使用和配置服务发现的解决方案。
Java EE 在外部并没有提供这样的功能,但是有一些开源解决方案可以使用,其中一个就是 Snoop, 它的功能与Eureka相似。要使 Java EE 微服务支持任务查找,唯一要做的是使用 @EnableSnoopClient 注解,如本例所示: Gist Snippet。
总结
在构建微服务时, Java 是一个非常好的选择。本文中介绍的任何一种方法都可以实现微服务。当然,最好的方法还是根据服务需求而定。对于简单的服务, container-less 或者 self-contained 服务就是不错的选择。不过,借助 in-container ,开发者可以更快更简单地实现更高级的服务。无论针对哪种服务,Java 生态系统都能提供行之有效的实现方法。
(编译自: https://dzone.com/articles/building-microservices-with-java )
OneAPM 为您提供端到端的 Java 应用性能解决方案,我们支持所有常见的 Java 框架及应用服务器,助您快速发现系统瓶颈,定位异常根本原因。分钟级部署,即刻体验, Java 监控从来没有如此简单。想阅读更多技术文章,请访问 OneAPM 官方技术博客。
本文转自 OneAPM 官方博客