龙空技术网

Java 中的超快微服务:当Microstream遇上Open Liberty

卑微打工人998 874

前言:

现在大家对“javaopen”大概比较珍视,小伙伴们都需要了解一些“javaopen”的相关资讯。那么小编同时在网络上搜集了一些对于“javaopen””的相关知识,希望我们能喜欢,大家一起来学习一下吧!

当我们谈论创建可扩展的应用程序时,微服务已经成为一个流行语。但这还不足够,与任何软件架构决策一样,它有一个权衡和几个挑战。幸运的是,对于我们Java开发人员来说,有两种工具的组合使我们的生活更轻松:Microstream和MicroProfile。本文将介绍如何将Microstream和 Open Liberty 结合起来,以创建一个轻松稳定且超快速的微服务应用程序。

具有Open Liberty的微服务

微服务给我们软件工程师带来了一些挑战,特别是作为面对分布式系统的第一步。但这并不意味着我们是孤独的。事实上,有几种工具可以让我们在Java世界中的生活更轻松,尤其是MicroProfile。

MicroProfile的目标是针对微服务架构优化企业版 Java 。它基于Java EE / Jakarta EE标准以及专门用于微服务的API,如Rest Client,Configuration,Open API等。

Open Liberty就是这些实现之一,它以IBM为主要贡献者。Open Liberty 是一个轻量级的开放式框架,用于构建快速高效的云原生 Java 微服务。它为运行云原生应用和微服务提供了足够的运行时间。

Microstream的数据持久性非常快

一旦我们谈论微服务,我们就会谈论分布式系统及其挑战,这种谈论在持久性层中将是相同的。

当你有更多关于业务的不确定信息时,我们应该有一个模型,甚至是无模式数据库。尽管如此,持久性层面仍然存在很多问题,主要是因为它很难改变。

制作可扩展应用程序的秘诀之一是确保它是无状态的,但我们在持久性层中负担不起它。首先,数据库旨在保留信息及其状态。

使数据持久化层更自然的解决方案之一是直接与 Java 实体作为图形集成。这就是Microstream所做的。

Microstream通过纯Java实现超快的在内存中处理数据。它提供微秒级查询时间、低延迟数据访问、巨大的数据吞吐量和工作负载。因此,它节省了数据中心的大量CPU功耗,二氧化碳排放和成本。

显示代码

让我们将两者结合起来,打造一个超快的微服务。一旦主要目标是展示两者如何结合,我们将选择一个流畅的演示。在此示例中,我们将创建一个简单的 CRUD,其中包含产品、名称和评级,并将其导出为 Rest API。

第一步是创建MicroProfile骨架:它毫不费力且流畅,主要是因为我们可以使用MicroProfile启动器进行可视化配置。配置文件版本 4.1 、 Java 11 和 Open Liberty ,如下图所示

现在有了应用程序的骨架。下一步就是添加Microstream并使两者协同工作。幸运的是,有一个库可以通过CDI扩展集成两者。因此,任何具有CDI和MicroProfile Config的应用程序都可以借助此API工作。

请查看最新版本并将其添加到您的应用程序中。

1. <dependency>2. <groupId>one.microstream</groupId>3. <artifactId>microstream-integrations-cdi</artifactId>4. <version>LAST_VERSION_HERE</version>5. </dependency>

骨架已设置好,因此让我们从代码开始。模型是中心部分。一旦它是一个平滑的示例,我们将创建一个包含几个字段的产品实体。使用Microstream的主要建议是使用不可变实体。因此,我们将创建一个产品作为不可或缺的实体。

1.public class Product {  2.    private final long id;  3.    private final String name;  4.    private final String description;  5.    private final int rating;  6.  7.    @JsonbCreator  8.    public Product(  9.            @JsonbProperty("id") final long id,  10.            @JsonbProperty("name") final String name,  11.            @JsonbProperty("description") final String description,  12.            @JsonbProperty("rating") final int rating  13.    ) {  14.        this.id = id;  15.        this.name = name;  16.        this.description = description;  17.        this.rating = rating;  18.    }

JSON 注释仅告知 MicroProfile 如何将实体序列化为 JSON。

下一步是定义产品集合,我们称之为“库存”。库存类是一组具有多种操作方法的产品。

此类是实体与Microstream引擎之间的链接。与Microstream的连接是使用注释Storage 。

1.import java.util.Collections;  2.import java.util.HashSet;  3.import java.util.Objects;  4.import java.util.Optional;  5.import java.util.Set;  6.import java.util.function.Predicate;  7.  8.import one.microstream.integrations.cdi.types.Storage;  9.  10.  11.@Storage  12.public class Inventory {  13.    private final Set<Product> products = new HashSet<>();  14.  15.    public void add(final Product product) {  16.        Objects.requireNonNull(product, "product is required");  17.        this.products.add(product);  18.    }  19.  20.    public Set<Product> getProducts() {  21.        return Collections.unmodifiableSet(this.products);  22.    }  23.  24.    public Optional<Product> findById(final long id) {  25.        return this.products.stream().filter(this.isIdEquals(id)).limit(1).findFirst();  26.    }  27.  28.    public void deleteById(final long id) {  29.        this.products.removeIf(this.isIdEquals(id));  30.  31.    }  32.  33.    private Predicate<Product> isIdEquals(final long id) {  34.        return p -> p.getId() == id;  35.    }  36.  37.    @Override  38.    public boolean equals(Object o) {  39.        if (this == o) return true;  40.        if (o == null || getClass() != o.getClass()) return false;  41.        Inventory inventory = (Inventory) o;  42.        return Objects.equals(products, inventory.products);  43.    }  44.  45.    @Override  46.    public int hashCode() {  47.        return Objects.hash(products);  48.    }  49.  50.    @Override  51.    public String toString() {  52.        return "Inventory{" +  53.                "products=" + products +  54.                '}';  55.    }  }

集合准备就绪后,让我们创建存储库。要使用我们的类型,我们可以使用 CDI 中的注释。我们需要将此操作提交到将要更改此集合的每个操作中。对于任何更改库存的方法,都有一个InventoryInjectStore注释为我们自动处理它。

1.public interface ProductRepository  2.{  3.    Collection<Product> getAll();  4.      5.    Product save(Product item);  6.      7.    Optional<Product> findById(long id);  8.      9.    void deleteById(long id);  10.}  11.  12.  13.@ApplicationScoped  14.public class ProductRepositoryStorage implements ProductRepository {  15.    private static final Logger LOGGER = Logger.getLogger(ProductRepositoryStorage.class.getName());  16.  17.    @Inject  18.    private Inventory inventory;  19.      20.    @Override  21.    public Collection<Product> getAll() {  22.        return this.inventory.getProducts();  23.    }  24.  25.    @Override  26.    @Store  27.    public Product save(final Product item) {  28.        this.inventory.add(item);  29.        return item;  30.    }  31.  32.    @Override  33.    public Optional<Product> findById(final long id) {  34.        LOGGER.info("Finding the item by id: " + id);  35.        return this.inventory.findById(id);  36.    }  37.  38.    @Override  39.    @Store  40.    public void deleteById(final long id) {  41.        this.inventory.deleteById(id);  42.    }  }

最后一步是将此产品公开为 Rest API。然后,我们将使用Jakarta EE API返回MicroProfile:JAX-RS。接下来,我们将使用 MicroProfile 创建 Open API 文档。

1.@RequestScoped  2.@Path("products")  3.@Consumes(MediaType.APPLICATION_JSON)  4.@Produces(MediaType.APPLICATION_JSON)  5.public class ProductController  6.{  7.    @Inject  8.    private ProductRepository repository;  9.      10.    // TODO don't worried about pagination  11.    @GET  12.    @Operation(summary = "Get all products", description = "Returns all available items at the restaurant")  13.    @APIResponse(responseCode = "500", description = "Server unavailable")  14.    @APIResponse(responseCode = "200", description = "The products")  15.    @Tag(name = "BETA", description = "This API is currently in beta state")  16.    @APIResponse(description = "The products", responseCode = "200", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = Collection.class, readOnly = true, description = "the products", required = true, name = "products")))  17.    public Collection<Product> getAll()  18.    {  19.        return this.repository.getAll();  20.    }  21.      22.    @GET  23.    @Path("{id}")  24.    @Operation(summary = "Find a product by id", description = "Find a product by id")  25.    @APIResponse(responseCode = "200", description = "The product")  26.    @APIResponse(responseCode = "404", description = "When the id does not exist")  27.    @APIResponse(responseCode = "500", description = "Server unavailable")  28.    @Tag(name = "BETA", description = "This API is currently in beta state")  29.    @APIResponse(description = "The product", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = Product.class)))  30.    public Product findById(  31.        @Parameter(description = "The item ID", required = true, example = "1", schema = @Schema(type = SchemaType.INTEGER)) @PathParam("id") final long id)  32.    {  33.        return this.repository.findById(id).orElseThrow(  34.            () -> new WebApplicationException("There is no product with the id " + id, Response.Status.NOT_FOUND));  35.    }  36.      37.    @POST  38.    @Operation(summary = "Insert a product", description = "Insert a product")  39.    @APIResponse(responseCode = "201", description = "When creates an product")  40.    @APIResponse(responseCode = "500", description = "Server unavailable")  41.    @Tag(name = "BETA", description = "This API is currently in beta state")  42.    public Response insert(  43.        @RequestBody(description = "Create a new product.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Product.class))) final Product product)  44.    {  45.        return Response.status(Response.Status.CREATED).entity(this.repository.save(product)).build();  46.    }  47.      48.    @DELETE  49.    @Path("{id}")  50.    @Operation(summary = "Delete a product by ID", description = "Delete a product by ID")  51.    @APIResponse(responseCode = "200", description = "When deletes the product")  52.    @APIResponse(responseCode = "500", description = "Server unavailable")  53.    @Tag(name = "BETA", description = "This API is currently in beta state")  54.    public Response delete(  55.        @Parameter(description = "The item ID", required = true, example = "1", schema = @Schema(type = SchemaType.INTEGER)) @PathParam("id") final long id)  56.    {  57.        this.repository.deleteById(id);  58.        return Response.status(Response.Status.NO_CONTENT).build();  59.    }  60.      }

就是这样,我们可以测试正在运行的应用程序并检查结果。

1.mvn clean package  2.java -jar target/openliberty-example.jar  3.  4.curl --location --request POST '; \  5.--header 'Content-Type: application/json' \  6.--data-raw '{"id": 1, "name": "banana", "description": "a fruit", "rating": 5}'  7.  8.curl --location --request POST '; \  9.--header 'Content-Type: application/json' \  10.--data-raw '{"id": 2, "name": "watermelon", "description": "watermelon sugar ahh", "rating": 4}'  11.  12.curl --location --request GET ';  13.  curl --location --request GET ';

我们终于在Open Liberty和Microstream之间实现了集成。本教程展示了两者如何协同工作,并为您提供了一个面对持久性问题的新工具:Microstream。事实上,当你想要创建微服务来超快速运行它时,Microstream和Open Liberty就是伟大的盟友。

标签: #javaopen