写点什么

通过容器编排和服务网格来改进 Java 微服务的可测性

  • 2018-08-09
  • 本文字数:4774 字

    阅读完需:约 16 分钟

关键要点

  • 在企业测试中,测试软件的方式应该与软件在生产环境中运行的方式相同,以便确保软件能够按预期的方式运行。
  • 常见的挑战是微服务应用程序直接或间接依赖需要在测试场景中编排的其他服务。
  • 本文展示了容器编排如何在服务实例之上提供抽象,并使用模拟实例来替代真实实例。
  • 此外,服务网格让我们能够重新路由流量,并通过注入错误响应或延迟来验证服务的弹性。
  • 本文包含了一个示例代码,代码来自一个基于 Java 的咖啡店应用程序,该应用程序将被部署到 Kubernetes 和 Istio 上,并对其进行测试。

在企业测试中,测试软件的方式应该与软件在生产环境中运行的方式相同,以便确保软件能够按预期的方式运行。常见的挑战是微服务应用程序直接或间接依赖需要在测试场景中编排的其他服务。

本文展示了容器编排如何在服务实例之上提供抽象,并使用桩实例来替代真实实例。此外,服务网格让我们能够重新路由流量,并通过注入错误响应或延迟来验证服务的弹性。

我们将使用一个咖啡店示例应用程序,这个应用程序被部署在一个容器和服务网格集群中。我们选择Kubernetes 和Istio 作为实例运行环境。

测试场景

假设我们想要在不考虑其他外部服务的情况下测试应用程序的行为。应用程序的运行方式和配置方式应该与生产环境相同,以便确保以后它在生产环境中的行为是一致的。在测试中,我们将使用定义好的通信接口连接应用程序。

但是,外部服务不应成为测试场景的一部分。通常,在测试时我们应该关注被测试的对象,并忽略掉其他对象。因此,我们使用模拟服务器来替代外部服务。



容器编排

使用模拟服务器而不是真实实例与以与生产环境相同的方式运行微服务的想法相矛盾,因为到了生产环境配置会发生改变。但是,如果我们的应用程序部署到容器编排集群(例如 Kubernetes),就可以将抽象的服务名称用作配置,并让集群自己去解析后端服务实例。

以下示例是一个网关类,它是咖啡店应用程序的一部分,连接到端口 8080 上的 coffee-processor。

复制代码
public class OrderProcessor {
    // definitions omitted ...
    @PostConstruct
    private void initClient() {
        final Client client = ClientBuilder.newClient();
        target = client.target("http://coffee-processor:8080/processes");
    }
   @Transactional(Transactional.TxType.REQUIRES_NEW)
    public void processOrder(Order order) {
        OrderStatus status = retrieveOrderStatus(order);
        order.setStatus(status);
        entityManager.merge(order);
    }
    // ...
    private JsonObject sendRequest(final JsonObject requestBody) {
        Response response = target.request()
               .buildPost(Entity.json(requestBody))
                .invoke();
        // ...
        return response.readEntity(JsonObject.class);
    }
    // definitions omitted ...
}

主机名通过 Kubernetes 群集 DNS 解析,将流量引导到其中一个正在运行的处理器实例。然而,coffee-processor 的实例将成为一个模拟服务器,在我们的示例中使用了 WireMock 。这种替换对我们的应用来说是透明的。

在测试场景中,不仅会连接到应用程序来调用业务逻辑,还会与模拟服务器发生通信,在单独的管理界面上控制响应行为,并验证应用程序是否以正确的方式调用模拟服务器。这与类级别的单元测试类似,通常使用 JUnit 和 Mockito 实现。



外部服务

上述的设置可以让我们模拟和控制在容器编排集群内运行的服务。那么那些在集群之外的外部服务该怎么办呢?

通常,我们可以创建一个不带有选择器的Kubernetes 服务,让它指向一个外部IP,并重写我们的应用程序,让它始终使用由群集解析的服务名。这样一来,我们定义了一个单一的点,服务将被路由到这个点上。

以下的代码片段显示了一个外部 Kubernetes 服务和端点定义,它将 coffee-shop-db 路由到外部 IP 地址 1.2.3.4:

复制代码
kind: Service
apiVersion: v1
metadata:
  name: coffee-shop-db
spec:
  ports:
  - protocol: TCP
    port: 5432
---
kind: Endpoints
apiVersion: v1
metadata:
  name: coffee-shop-db
subsets:
  - addresses:
      - ip: 1.2.3.4
    ports:
      - port: 5432

在不同的环境中,服务可能会被路由到不同的数据库实例。

服务网格

服务网格能够帮助我们处理微服务间的通信问题。目前,Istio 是最常用的服务网格技术之一。它增加了与应用程序容器共存的边车代理容器,可以解决微服务间的通信问题,并且还可以用来操纵或减慢连接,以便进行弹性测试。

在端到端测试中,我们可以引入错误或缓慢的响应来验证应用程序是否能够正确处理这些问题场景。

以下的代码片段显示了一个 Istio 虚拟服务的定义,其中到 coffee-processor 的路由有 50% 的延迟为 3 秒,10%的响应是失败的。

复制代码
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: coffee-processor
spec:
  hosts:
  - coffee-processor
  http:
  - route:
    - destination:
        host: coffee-processor
        subset: v1
    fault:
      delay:
        fixedDelay: 3s
        percent: 50
      abort:
        httpStatus: 500
        percent: 10
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: coffee-processor
spec:
  host: coffee-processor
  subsets:
  - name: v1
    labels:
      version: v1

现在,我们可以运行其他测试,并验证应用程序将如何处理这些增加的响应时间和故障状况。

除了可以注入错误响应之外,服务网格技术还可以用来从环境中添加弹性。代理容器可以处理超时,实现断路器和隔板,而应用程序无需关心这些问题。

结论

容器编排和服务网格通过将应用程序的关注点转移到环境中来提高微服务应用程序的可测试性。有了服务抽象,我们就可以透明地替换服务或进行重新路由。服务网格不仅支持更复杂的路由,还允许我们注入故障或减慢响应,让应用程序处于压力之下,以此来验证其相应的行为。

更多资源

关于作者

 Sebastian Daschner 是一名自由 Java 顾问、作家和培训师,对编程和 Java 充满热情。他是“Architecting Modern Java EE Applications”一书的作者。Sebastian 正在参与 JCP,协助制定 Java EE 的未来标准,是 JAX-RS、JSON-P 和 Config 专家组的成员,并在各种开源项目上进行协作。由于在 Java 社区和生态系统中的贡献,他获得了 Java Champion、Oracle Developer Champion 和 2016 年 JavaOne Rockstar 的殊荣。除了 Java 之外,Sebastian 还是 Linux 和云原生技术的重要用户。他通过博客和Twitter(@DaschnerS)传播计算机科学实践。工作之余,他喜欢乘飞机或骑摩托车旅行。

查看英文原文 Improving Testability of Java Microservices with Container Orchestration and a Service Mesh

2018-08-09 18:272837
用户头像

发布了 731 篇内容, 共 479.3 次阅读, 收获喜欢 2008 次。

关注

评论

发布
暂无评论
发现更多内容

恒拓高科 × 华为共建鸿蒙生态:BeeWorks打造全免费的超级数字化协作平台

BeeWorks

在京东,向前一步的技术人

京东零售技术

Dify + OceanBase + MCP:三剑合璧,轻松构建 RAG 应用

Se7en

参赛报名|百万奖金+全球曝光:2025港科百创赛事正式启动!

声网

和鲸科技联合四川气象斩获 2025 爱分析·DeepSeek 最佳实践案例

ModelWhale

最佳案例 爱分析 DeepSeek 四川气象

信创 CDC 实战|国产数据库的数据高速通道:Dameng → Doris 实时入仓同步方案

tapdata

达梦数据同步 数据进doris 实时数据入仓 ogg国产替代 数据同步工具推荐

解码供应链数字化转型:低代码如何破解多环节协同的技术困局?

不在线第一只蜗牛

数字先锋 | 驱动“芯”发展,天翼云携手黑芝麻智能开启EDA上云之路!

天翼云开发者社区

云计算 超算

通过ETL从MySQL同步到GaussDB

谷云科技RestCloud

MySQL 数据库 ETL 数据集成工具 GaussDB 实时同步

【公开课】芯片ATE测试—93K机台与Smartest软件介绍

IC男奋斗史

芯片 半导体 测试工程师 芯片技术 芯片测试

封禁UDP端口提高防御能力分析

网络安全服务

CDN 服务器 udp DDoS 带宽

Golang基础笔记六之流程控制

Hunter熊

Go 流程控制 条件语句 循环语句 for循环

鸿蒙 SideBarContainer 开发攻略:侧边栏交互设计与多端适配

谢道韫

从0到100:房产中介小程序开发笔记(中)

CC同学

覆盖设计、开发、上线、运营全链路,腾讯游戏云发布小游戏全方位解决方案

极客天地

签约快讯|天润融通签约滴滴企业版

天润融通

腾讯云联合Gartner发布《Data+AI下一代数智平台建设指南》

极客天地

天润融通AI助手,8大AI功限时免费体验中!

天润融通

Nuclear - 基于流媒体的隐私优先音乐播放器

qife122

流媒体 音乐播放器

节省前端1000+pd人力成本!快手快聘「伏羲工作台」技术实践全解析

快手技术

前端 快手

基于华为开发者空间-Astro低代码平台,构建用户登录功能开发

华为云开发者联盟

低代码 华为云Astro 华为开发者空间

跨芯片 AI 算子库 FlagGems 正式加入PyTorch 基金会生态项目体系

智源研究院

大模型走向深度应用,CTO们的硬仗才刚刚开始

Alter

C# 中委托和事件的深度剖析与应用场景

量贩潮汐·WholesaleTide

Java C#

位置核验方案

天翼云开发者社区

位置核验

StarRocks 向量索引如何让大模型“记性更好”?

镜舟科技

分析型数据库 大模型 StarRocks 向量索引 RAG 框架

从0到1:文旅小程序开发笔记(上)

CC同学

大数据-24 Sqoop MySQL到Hive 与 Hive到MySQL JDBC ETL MapReduce

武子康

MySQL 大数据 hdfs sqoop ETL

代码界的“外卖加速包”:当程序员爱上拖拖拉拉

秃头小帅oi

互联网巨头争抢AI人才 京东以科技温度+产业厚度构筑人才热土

京东零售技术

阿里P8面试官给校招及社招程序员的建议(JAVA岗)!

程序员高级码农

java 程序员‘

通过容器编排和服务网格来改进Java微服务的可测性_Java_Sebastian Daschner_InfoQ精选文章