背景
在Java EE 7发布之后,Java EE的发展变得缓慢起来,没有及时满足用户对于云原生开发的需求(虽然有诸如以Spring为首的传统开发框架,但笨重、臃肿带来的启动高耗时、资源高消耗等缺点越发明显)。Java开发人员迫切的需要一种可扩展、轻量级、可移植的平台,来构建云原生应用程序和微服务架构,并能够提高应用程序的可伸缩性、弹性和可靠性。为了解决这些问题,一些Java EE的开发者和厂商开始探索如何在Java EE的基础上(3.0完全移除了对Java EE的依赖)构建轻量级、可移植的云原生应用程序。MicroProfile应运而生,成为Java开发者构建云原生应用的首选框架之一。
关于
MicroProfile是一组Java企业版(Java EE)规范的扩展,专为微服务架构设计,目标是为开发云原生应用程序提供一个轻量级、可移植的平台。它由几个主要的开发者和厂商组成,包括IBM、Red Hat、Tomitribe、Payara和其他几个公司,旨在帮助开发人员在轻量级的微服务架构中使用Java EE技术。MicroProfile规范覆盖了多个领域,包括RESTful Web服务、配置、安全、度量、事件、健康检查和分布式跟踪等,它们都是独立的,并可以根据需要进行组合和使用。MicroProfile还提供了一个可移植的运行时平台,可以在多种云环境和容器化平台上运行,包括Docker、Kubernetes、OpenShift和Cloud Foundry等。总之,MicroProfile为Java开发人员提供了一种可扩展、轻量级、可移植的平台,用来构建云原生应用程序和微服务架构,提高应用程序的可伸缩性、弹性和可靠性。
特点
- 小巧轻便:MicroProfile专为微服务设计,提供了一个轻量级的API。开发者可以根据需要选择适合的模块,这有助于提高开发速度和效率,使开发者能够快速地开发微服务应用。
- 可扩展性:MicroProfile遵循模块化的设计原则,开发者可以根据需要选择和使用不同的MicroProfile规范。而且与其他开源项目和技术(如Kubernetes和Docker)集成性好,有助于构建强大的企业微服务解决方案。例如,如应用性能监控、容器编排和持续交付等,使得Java开发人员可以更加高效地开发、测试和部署微服务应用程序。
- 标准化:MicroProfile是基于Java EE / Jakarta EE技术栈构建的,这意味着开发者可以使用一系列现有的开源实现,并且可以在不同的云平台和基础设施之间进行移植。例如,如微服务链路追踪、事件驱动架构和响应式编程等,使得Java应用程序可以更好地适应现代的微服务场景。
- 云原生支持:MicroProfile专注于云原生应用程序开发,提供了许多与云原生应用程序开发相关的API和规范。例如,支持多种微服务部署模式,包括容器化部署、Serverless部署和边缘计算等,使得Java应用程序可以更加灵活地适应不同的部署环境。 社区支持:MicroProfile是一个活跃的开源项目,得到了包括IBM、Red Hat、Payara、Tomitribe等在内的多家企业和组织的支持。
特性
- 规范
- MicroProfile Config:提供了一种统一的配置方法,为应用提供外部配置支持。
- MicroProfile Fault Tolerance:提供容错功能,如熔断器、重试、超时和容错策略。
- MicroProfile Health Check:提供健康检查API,用于监控微服务的运行状况。
- MicroProfile Metrics:提供度量API,用于收集和导出微服务的性能数据。
- MicroProfile JWT Propagation:提供对JSON Web Token(JWT)的支持,用于安全地传递用户身份信息。
- MicroProfile OpenAPI:提供OpenAPI规范的支持,用于描述、生成和文档化RESTful API。
- MicroProfile OpenTracing:提供对分布式追踪的支持,用于监控和诊断微服务之间的调用关系。
- MicroProfile Rest Client:提供类型安全的REST客户端API,用于简化微服务之间的通信。
- 能力
- 除上述标准的规范外,MicroProfile还提供了如下的能力
- MicroProfile Reactive Streams:提供响应式编程API,可以编写具有高响应性、可伸缩性和弹性的应用程序。
- Service Discovery: 用于发现注册到服务注册中心的微服务实例。
- Client Side Load Balancing API:在客户端实现负载均衡,从而将请求发送到可用的微服务实例。
- Circuit Breaker API:在微服务出现故障或异常时,可以中断失败的请求,从而避免过多的资源消耗。
示例
- MicroProfile Config
// 注入配置值
@Inject
@ConfigProperty(name = "app.message", defaultValue = "Hello World")
private String message;
// 使用配置值
@GET
public String getMessage() {
return message;
}
- MicroProfile Fault Tolerance
@GET
@Timeout(500) // 设置超时时间为500毫秒
@Retry(maxRetries = 3) // 最大重试次数为3次
@CircuitBreaker(requestVolumeThreshold = 5, failureRatio = 0.5, delay = 2000) // 熔断器配置
public String getRemoteData() {
// 调用远程服务
}
- MicroProfile Health Check
@ApplicationScoped
@Liveness // 标记为Liveness Health Check
public class ServiceLivenessCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
// 检查服务状态
return HealthCheckResponse.up("Service is running");
}
}
- MicroProfile Metrics
@GET
@Timed(name = "timeCheck", unit = MetricUnits.MILLISECONDS) // 记录方法执行时间
public String timedMethod() {
// 执行操作
return "Method execution time is recorded";
}
- MicroProfile JWT Propagation
@Path("/secure")
public class SecuredResource {
@Inject
private JsonWebToken jwt;
@GET
@RolesAllowed("admin") // 仅允许具有admin角色的用户访问
public String getSecureData() {
return "Secure data for " + jwt.getName();
}
}
- MicroProfile OpenAPI
@GET
@Operation(summary = "Get a greeting message")
@APIResponse(description = "The greeting message", content = @Content(mediaType = "text/plain"))
public String hello() {
return "Hello, World!";
}
- MicroProfile OpenTracing
@Path("/tracing")
public class TracingResource {
@GET
public String getTracedData() {
// 获取数据
return "Data with tracing";
}
}
- MicroProfile Rest Client
// 定义一个接口用于访问外部服务
@Path("/external")
@RegisterRestClient
public interface ExternalServiceClient {
@GET
@Path("/data")
String fetchData();
}
// 使用ExternalServiceClient
@Inject
@RestClient
private ExternalServiceClient externalServiceClient;
@GET
public String getData() {
return externalServiceClient.fetchData();
}
- MicroProfile Reactive Streams
import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;
public class ReactiveExample {
public static void main(String[] args) {
Function<Integer, Integer> addOne = i -> i + 1;
CompletionStage<Integer> result = ReactiveStreams.of(1, 2, 3)
.map(addOne)
.reduce(0, Integer::sum)
.run();
result.thenAccept(System.out::println);
}
}
- MicroProfile Ribbon
@ApplicationScoped
public class MyService {
@Inject
@LoadBalanced
private RestTemplate restTemplate;
public String callService() {
return restTemplate.getForObject("http://my-service/sample", String.class);
}
}
- MicroProfile Circuit Breaker
import org.eclipse.microprofile.faulttolerance.*;
@ApplicationScoped
public class ExampleService {
@CircuitBreaker(requestVolumeThreshold = 4, failureRatio = 0.5, delay = 2000)
public String retrieveData() {
// Code to retrieve data from an external service
}
@Fallback(fallbackMethod = "fallbackMethod")
public String fallback() {
// Code to provide a fallback response when the circuit is open
}
public String fallbackMethod() {
// Code to provide an alternate fallback response
}
}
审视
- 根据MicroProfile的标准与规范,一个合格的微服务需要具备以下能力:
- 配置管理:提供可插拔的配置API和扩展点,简化应用程序配置的管理。
- RESTful服务:提供构建RESTful服务所需的API和注解。
- 服务注册与发现:方便服务的发现和协调,提供服务注册和发现的API。
- 安全性:提供安全性相关的API和注解,例如JWT身份验证和基于角色的访问控制。
- 指标监控:提供收集和呈现应用程序指标的API和注解,以便进行性能优化和故障排除。
- 分布式跟踪:提供跟踪应用程序请求和响应的API和注解,以便进行故障排除和性能优化。
- 高可用性:提供与容器编排平台集成的API和注解,以实现在多个节点上运行服务并提供高可用性。
- 异步消息传递:提供异步消息传递的API和注解,以实现异步通信和事件驱动架构。
- 根据云原生架构的特点,微服务需要具备以下能力:
- 弹性伸缩性:微服务需要具备快速、自动地响应负载变化的能力,以满足不同的业务需求。
- 容错与容灾:微服务需要具备自我修复、自我保护的能力,以保证系统的可靠性和稳定性。
- 可观测性:微服务需要具备实时监控、日志记录和性能分析的能力,以便及时发现和解决问题。
- 安全性:微服务需要具备身份验证、权限控制和数据保护等安全机制,以保障用户数据和系统安全。
- 自动化运维:微服务需要具备自动化部署、自动化测试和自动化运维的能力,以提高开发效率和系统稳定性。
- 服务发现与注册:微服务需要具备服务发现和注册的能力,以便其他微服务可以快速找到和使用它提供的服务。
- 云原生编排:微服务需要具备自动化编排和调度的能力,以便在容器化、Serverless等云原生环境中高效地运行。
- 事件驱动架构:微服务需要具备异步消息传递和事件驱动架构的能力,以便实现松耦合、高效性和伸缩性。
思考
- 哪些能力缺失?
- 哪些能力依赖三方库实现?
- 哪些能力是“历史遗留”产物?
- 哪些虽然能力有了,但是很“鸡肋”?
- 哪些能力是“闭门造车”、“各自为政”?
挑战
- 缺乏必要能力
- 云原生:缺乏云原生的能力,如容器化、弹性伸缩、自动化部署等,难以满足云环境下的高可用性、弹性和可靠性需求。
- 微服务治理:缺乏微服务治理的能力,如服务注册与发现、负载均衡、流量控制、熔断降级、安全等,难以解决微服务架构中的服务发现、调用和容错等问题。
- 安全能力:缺乏安全能力,如认证、授权、加密等,难以保障微服务系统的数据安全和隐私安全。
- 分布式跟踪和监控:缺乏分布式跟踪和监控的能力,难以对微服务系统进行全面的性能、调用链追踪和故障诊断。
- 自动化运维:缺乏自动化运维的能力,如自动化部署、自动化测试、自动化监控和自动化故障处理等,难以满足微服务系统的高效运维需求。
- 缺乏标准化
- 通讯协议不统一:使用不同的通讯协议,如REST、DUBBO、SOAP等,缺乏统一的标准。
- API设计不一致:各个服务的API设计往往不一致,导致服务之间的兼容性问题和集成难度增加。
- 组件技术不同:各个服务使用的组件技术不同,如数据库、消息队列、缓存等,缺乏统一的标准。
- 部署架构不同:各个服务的部署架构不同,如部署方式、环境依赖等,导致部署和维护的复杂度增加。
- 监控和诊断不一致:各个服务的监控和诊断方式不一致,导致对服务性能和可用性的监控和调优变得困难。
- 缺乏轻量级框架
- 运行时环境:需要引入庞大的运行时环境,导致部署和运维成本高昂。
- 配置编排:需要使用复杂的配置和编排方式,导致开发和维护难度较大。
- 通信协议:需要使用重量级的通信协议和序列化方式,导致通信效率较低。
- 服务发现:需要使用复杂的服务发现和负载均衡机制,导致运维和调试难度较大。
- 基础组件:需要使用大量的第三方组件和库,导致应用程序的复杂度增加。
- 缺乏云原生能力
- 弹性能力:缺乏弹性伸缩和自动化治理能力,无法适应云原生动态环境的需求。
- 容器支持:缺乏容器化支持和云原生编排能力,无法充分利用云平台的资源管理优势。
- 安全隔离:缺乏多租户和安全隔离能力,无法满足云原生应用程序的安全性和稳定性要求。
- 异步编程:缺乏事件驱动和异步编程模型的支持,无法适应云原生应用程序的高并发和低延迟需求。
- 持续交付:缺乏持续交付和微服务治理能力,无法满足快速迭代和敏捷开发的要求。
- 缺乏对微服务场景的适应性
- 多协议:缺乏对异构语言和异构协议的支持,无法适应多语言和多协议的微服务场景。
- 多样化:缺乏对低功耗设备和边缘计算场景的支持,无法适应分布式微服务的多样化需求。
- 机器学习:缺乏对实时流处理和机器学习场景的支持,无法满足高性能、低延迟和数据处理等要求。
- 大数据:缺乏对物联网和大规模分布式计算场景的支持,无法满足大规模数据采集和分析的需求。
变革
为了应带挑战,Java也在积极的变化,一些轻量级的云原生微服务框架应运而生(诸如,Quarkus、Open Liberty、Helidon)。其中,以2018年RedHat推出的专为云原生设计的Java开发框架(让Java开发者能为现在的云原生世代创建应用程序) - Quarkus最为出名( 详解见 - 云原生架构下的Java框架新势力-Quarkus)。设计之初便与Kubernetes紧密结合,以提高构建微服务、无服务以及基于云服务的应用程序的开发效率为目的。
实现
- Quarkus
由Red Hat开发的开源Java框架,旨在提供一个快速、轻量级的平台,支持构建云原生应用程序。
- 特点
- 快速启动和低内存占用:Quarkus使用GraalVM和SubstrateVM技术,可以将应用程序的启动时间缩短到几毫秒,并且内存占用率非常低。
- 优化的开发体验:Quarkus提供了一组优化的开发工具和API,可以帮助开发人员更加高效地开发和测试应用程序。
- 可扩展性:Quarkus支持在运行时动态添加和删除扩展,可以根据应用程序的需求进行自定义扩展。
- 云原生支持:Quarkus专注于云原生应用程序开发,提供了许多与云原生应用程序开发相关的API和规范,如MicroProfile和Kubernetes扩展。
- 高性能:Quarkus具有优异的性能表现,可以处理高并发、高吞吐量的请求。
- 开源:Quarkus是一个开源项目,由一个活跃的社区驱动,并且与其他Java技术和框架兼容。
- Open Liberty
由IBM开发的开源应用服务器。它是Java EE和Eclipse MicroProfile规范的实现,致力于提供一个灵活、可扩展的应用程序开发和运行环境。
- 特点
- 轻量级:Open Liberty采用了模块化架构,只加载应用程序所需的模块,从而减小了应用程序的体积和启动时间。
- 可扩展性:Open Liberty支持在运行时动态添加和删除功能模块,使应用程序可以根据需求进行自定义扩展。
- 开源:Open Liberty是一个开源项目,由IBM和其他贡献者共同开发和维护。
- 容器化支持:Open Liberty支持在容器化环境下部署和运行应用程序,如Docker和Kubernetes。
- 安全性:Open Liberty提供了一套完整的安全性功能,包括SSL/TLS、认证和授权、访问控制等,可以保护应用程序和数据的安全。
- 高可用性:Open Liberty支持集群模式和负载均衡,可以提高应用程序的可用性和性能。
- Helidon
轻量级的Java框架,用于构建响应式的微服务应用程序。它由Oracle开发并开源,提供两个版本:Helidon SE和Helidon MP。
- Helidon SE(简化版)是一个非常轻量级的框架,提供了构建响应式应用程序所需的基本功能,如Web服务器、响应式流、安全性和配置管理等。它适用于构建小型应用程序或需要自定义应用程序堆栈的特殊情况。
- Helidon MP(微配置版)是一个面向Java企业版(Java EE)的框架,提供了构建微服务应用程序所需的所有功能。它基于Java EE标准,支持微服务开发的核心技术,如JAX-RS、CDI和JSON-P/B等。
- 特点
- 响应式编程:使用响应式编程模型,可以利用多核处理器和异步I/O,提高应用程序的性能和可伸缩性。
- 云原生:支持容器化部署,并与Kubernetes等云原生平台进行集成。
- 易于使用:提供了简单易用的API和工具,使开发人员能够快速构建应用程序。
- 可扩展性:支持插件式开发,能够根据需要扩展应用程序功能。
- 开放源码:Helidon是开源软件,可以免费使用和修改。
总结
我们始终在追寻技术的脚步,勇往直前。但是,在历史的枷锁的面前,还是做出了“妥协”。或受制于技术、或受制于规范,又或满足于现状,我们不曾向它们发起挑战。随着云原生技术的发展,我们有了越来越多的技术选择,例如,以Micro Profile为代表的新兴势力,以其轻便、高效、云原生等诸多特性吸引了无数的粉丝。而这些新的技术也对我们带来了诸多的启发与变革。是时候拥抱新的变革了!