当前位置: 首页 > 科技观察

Java中的超快微服务:当Microstream遇到OpenLiberty

时间:2023-03-17 01:44:19 科技观察

译者|朱钢评论|SunShujuan当我们谈论创建可扩展的应用程序时,微服务已经成为一个流行语。但这还不够,与任何软件架构决策一样,它需要权衡和一些挑战。对我们Java开发人员来说幸运的是,有两种工具的组合可以让我们的生活更轻松:Microstream和MicroProfile。本文将向您展示如何结合Microstream和OpenLiberty来创建一个简单稳定且超快的微服务应用程序。带有OpenLiberty微服务的微服务给我们软件工程师带来了一些挑战,尤其是作为面对分布式系统的第一步。但这并不意味着我们是孤独的。事实上,有几种工具可以让我们在Java世界中的生活更轻松,尤其是MicroProfile。MicroProfile的目标是针对微服务架构优化企业Java。它基于JavaEE/JakartaEE标准和专用于微服务的API,例如RestClient、Configuration、OpenAPI等。其中一个实现是OpenLiberty,它的主要贡献者是IBM。OpenLiberty是一个轻量级的开放式框架,用于构建快速高效的云原生Java微服务。它为运行云原生应用程序和微服务提供了足够的运行时间。Microstream的数据持久化非常快一说到微服务,就说到分布式系统及其挑战,这个讲到持久层也是一样的。当你对业务有更多的不确定信息时,我们应该有一个模型,甚至是一个无模式的数据库。尽管如此,持久层还是有很多问题,主要是因为它很难改变。制作可伸缩应用程序的秘诀之一是确保它是无状态的,但我们不能在持久层中承受这一点。首先,数据库旨在保存信息及其状态。使数据持久层更自然的解决方案之一是直接与Java实体集成为图形。这就是Microstream所做的。Microstream通过纯Java实现超快的内存中数据处理。它提供微秒级查询时间、低延迟数据访问、巨大的数据吞吐量和工作负载。因此,它节省了大量数据中心的CPU功耗、CO2排放和成本。显示代码让我们将两者结合起来制作一个超快速的微服务。一旦主要目标是展示两者如何结合在一起,我们将选择一个流畅的演示。在此示例中,我们将创建一个包含产品、名称和评级的简单CRUD,并将其导出为RestAPI。第一步是创建MicroProfile骨架:它毫不费力且流畅,主要是因为我们可以使用MicroProfile启动器进行可视化配置。配置文件版本4.1、Java11和OpenLiberty,如下所示,现在具有应用程序的框架。下一步是添加Microstream并使两者协同工作。幸运的是,有一个库通过CDI扩展将两者集成在一起。因此,任何具有CDI和MicroProfileConfig的应用程序都可以在此API的帮助下工作。请检查最新版本并将其添加到您的应用程序中。1.<依赖>2.one.microstream3.microstream-integrations-cdi4.LAST_VERSION_HERE5.skeleton已经设置好,让我们从代码开始吧。模型是核心部分。一旦它成为一个流畅的示例,我们将创建一个包含几个字段的产品实体。使用Microstream的主要建议是使用不可变实体。因此,我们将创建一个产品作为一个不可变的实体。1.publicclassProduct{2.privatefinallongid;3.私有最终字符串名称;4.privatefinal字符串描述;5.私人最终内部评级;6.7.@JsonbCreator8.publicProduct(9.@JsonbProperty("id")finallongid,10.@JsonbProperty("name")finalStringname,11.@JsonbProperty("description")finalStringdescription,12.@JsonbProperty("rating")finalintrating13.){14.this.id=id;15.this.name=名字;16.this.description=描述;17.this.rating=评分;18.}JSON注释只是告诉MicroProfile如何将实体序列化为JSON。下一步是定义产品集合,我们称之为“库存”。库存类是一组具有多种操作方法的产品。这个类是实体和Microstream引擎之间的链接。与Microstream的连接正在使用注释存储。1.导入java.util.Collections;2.导入java.util.HashSet;3.导入java.util.Objects;4.导入java.util.Optional;5.导入java.util.Set;6.导入java.util.function.Predicate;7.8.importone.microstream.integrations.cdi.types.Storage;9.10.11.@Storage12.publicclassInventory{13.privatefinalSetproducts=newHashSet<>();14.15.publicvoidadd(finalProductproduct){16.Objects.requireNonNull(product,"productisrequired");17.this.products.add(产品);18.}19.20.publicSetgetProducts(){21.returnCollections.unmodifiableSet(this.products);22.}23.24.publicOptionalfindById(finallongid){25.returnthis.products.stream().filter(this.isIdEquals(id)).limit(1).findFirst();26.}27.28.publicvoiddeleteById(finallongid){29.this.products.removeIf(this.isIdEquals(id));30.31.}32.33.privatePredicateisIdEquals(finallongid){34.returnp->p.getId()==id;35.}36.37.@Override38.publicbooleanequals(Objecto){39.if(this==o)returntrue;40.if(o==null||getClass()!=o.getClass())返回false;41.库存inventory=(Inventory)o;42.返回对象。等于(产品,库存。产品);43.}44.45.@Override46.publicinthashCode(){47.返回对象。哈希(产品);48.}49.50.@Override51.publicStringtoString(){52.return"Inventory{"+53."products="+products+54.'}';55.}}现在集合准备好了,让我们创建存储库来使用我们的类,我们可以在CDI中使用注释。我们需要将此操作提交给将更改此集合的每个操作。对于任何更改库存的方法,都有一个InventoryInjectStore注释会自动为我们处理它。1.publicinterfaceProductRepository2.{3.CollectiongetAll();4.5.产品保存(Productitem);6.7.可选findById(longid);8.9.voiddeleteById(longid);10.}11.12.13.@ApplicationScoped14.publicclassProductRepositoryStorageimplementsProductRepository{15.privatestaticfinalLoggerLOGGER=Logger.getLogger(ProductRepositoryStorage.class.getName());16.17.@Inject18.privateInventory库存;19.20.@Override21.publicCollectiongetAll(){22.returnthis.inventory.getProducts();23.}24.25.@Override26.@Store27.publicProductsave(finalProductitem){28.this.inventory.add(item);29.退货;30.}31.32.@Override33.publicOptionalfindById(finallongid){34.LOGGER.info("通过id查找项目:"+id);35.r返回this.inventory.findById(id);36.}37.38.@Override39.@Store40.publicvoiddeleteById(finallongid){41.this.inventory.deleteById(id);42.}}final第一步是将此产品公开为RestAPI然后,我们将使用JakartaEEAPI返回MicroProfile:JAX-RS。接下来,我们将使用MicroProfile创建OpenAPI文档。1.@RequestScoped2.@Path("products")3.@Consumes(MediaType.APPLICATION_JSON)4.@Produces(MediaType.APPLICATION_JSON)5.publicclassProductController6.{7.@Inject8.privateProductRepository存储库;9.10.//TODO不要担心分页11.@GET12.@Operation(summary="Getallproducts",description="Returnsallavailableitemsattherestaurant")13.@APIResponse(responseCode="500",description="服务器不可用")14.@APIResponse(responseCode="200",description="产品")15.@Tag(name="BETA",description="此API目前处于测试状态")16.@APIResponse(description="产品",responseCode="200",content=@Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=Collection.class,readOnly=true,description="产品",required=true,name="products")))17.publicCollectiongetAll()18.{19.返回this.repository.getAll();20.}21.22.@GET23.@Path("{id}")24.@Operation(summary="通过id查找产品",description="通过id查找产品")25.@APIResponse(responseCode="200",description="产品")26.@APIResponse(responseCode="404",description="id不存在时")27.@APIResponse(responseCode="500",description="Serverunavailable")28.@Tag(name="BETA",description="ThisAPIcurrentlyinbetastate")29.@APIResponse(description="Theproduct",content=@Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=Product.class)))30.publicProductfindById(31.@Parameter(description="TheitemID",required=true,example="1",schema=@Schema(type=SchemaType.INTEGER))@PathParam("id")finallongid)32.{33.returnthis.repository.findById(id).orElseThrow(34.()->newWebApplicationException("没有id为"+id,Response.Status.NOT_FOUND)的产品);35.}36.37.@POST38.@Operation(summary="Insertaproduct",description="Insertaproduct")39.@APIResponse(responseCode="201",description="Whencreatesanproduct")40.@APIResponse(responseCode="500",description="服务器不可用")41.@Tag(name="BETA",description="此API目前处于测试状态")42.publicResponseinsert(43.@RequestBody(description="Createanewproduct.",content=@Content(mediaType="application/json",schema=@Schema(implementation=Product.class)))finalProductproduct)44.{45.returnResponse.状态(Response.Status.CREATED).entity(this.repository.save(产品)).build();46.}47.48.@DELETE49.@Path("{id}")50.@Operation(summary="通过ID删除产品",description="通过ID删除产品")51.@APIResponse(responseCode="200",description="删除商品时")52.@APIResponse(responseCode="500",description="服务器不可用")53.@Tag(name="BETA",description="ThisAPI目前处于测试状态")54.publicResponsedelete(55.@Parameter(description="TheitemID",required=true,example="1",schema=@Schema(type=SchemaType.INTEGER))@PathParam("id")finallongid)56.{57.this.repository.deleteById(id);58.returnResponse.status(Response.Status.NO_CONTENT).build();59.}60.}就是这样,我们可以测试正在运行的应用程序并检查结果1.mvncleanpackage2.java-jartarget/openliberty-example.jar3.4.curl--location--requestPOST'http://localhost:8080/products/'\5.--header'Content-类型:application/json'\6.--data-raw'{"id":1,"name":"banana","description":"afruit","rating":5}'7.8.curl--location--requestPOST'http://localhost:8080/products/'\9.--header'Content-Type:application/json'\10.--data-raw'{"id":2,"name":"watermelon","description":"西瓜糖啊","rating":4}'11.12.curl--location--requestGET'http://localhost:8080/products/'13.curl--location--requestGET'http://localhost:8080/products/1'我们终于集成了OpenLiberty和Microstream。本教程展示了两者如何协同工作,并为您提供了一个解决持久性问题的新工具:Microstream。事实上,当您想要创建微服务以超快运行时,Microstream和OpenLiberty是很好的盟友。译者介绍朱刚,社区编辑,2021IT影响力专家博主,阿里云专家博主,2019CSDN博客之星Top20,2020腾讯云+社区优秀作者,11年一线开发经验,曾参与猎头服务网站架构设计、企业智能客服及大型电子政务系统开发,主导某大型央企内部防泄密及电子文档安全监控系统建设,目前在北京途家健康从事医疗软件研发。原标题:Ultra-FastMicroservicesinJava:WhenMicrostreamMeetsOpenLiberty,作者:OtavioSantana