MicroProfile视角下的微服务建设

160 阅读15分钟

背景

在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为代表的新兴势力,以其轻便、高效、云原生等诸多特性吸引了无数的粉丝。而这些新的技术也对我们带来了诸多的启发与变革。是时候拥抱新的变革了!