新聞中心
審校 | 孫淑娟

目前成都創(chuàng)新互聯(lián)已為成百上千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、綿陽(yáng)服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、大方網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
當(dāng)我們談?wù)搫?chuàng)建可擴(kuò)展的應(yīng)用程序時(shí),微服務(wù)已經(jīng)成為一個(gè)流行語(yǔ)。但這還不足夠,與任何軟件架構(gòu)決策一樣,它有一個(gè)權(quán)衡和幾個(gè)挑戰(zhàn)。幸運(yùn)的是,對(duì)于我們Java開發(fā)人員來說,有兩種工具的組合使我們的生活更輕松:Microstream和MicroProfile。本文將介紹如何將Microstream和 Open Liberty 結(jié)合起來,以創(chuàng)建一個(gè)輕松穩(wěn)定且超快速的微服務(wù)應(yīng)用程序。
具有Open Liberty的微服務(wù)
微服務(wù)給我們軟件工程師帶來了一些挑戰(zhàn),特別是作為面對(duì)分布式系統(tǒng)的第一步。但這并不意味著我們是孤獨(dú)的。事實(shí)上,有幾種工具可以讓我們?cè)贘ava世界中的生活更輕松,尤其是MicroProfile。
MicroProfile的目標(biāo)是針對(duì)微服務(wù)架構(gòu)優(yōu)化企業(yè)版 Java 。它基于Java EE / Jakarta EE標(biāo)準(zhǔn)以及專門用于微服務(wù)的API,如Rest Client,Configuration,Open API等。
Open Liberty就是這些實(shí)現(xiàn)之一,它以IBM為主要貢獻(xiàn)者。Open Liberty 是一個(gè)輕量級(jí)的開放式框架,用于構(gòu)建快速高效的云原生 Java 微服務(wù)。它為運(yùn)行云原生應(yīng)用和微服務(wù)提供了足夠的運(yùn)行時(shí)。
Microstream的數(shù)據(jù)持久性非???/h4>
一旦我們談?wù)撐⒎?wù),我們就會(huì)談?wù)摲植际较到y(tǒng)及其挑戰(zhàn),這種談?wù)撛诔志眯詫又袑⑹窍嗤摹?/p>
當(dāng)你有更多關(guān)于業(yè)務(wù)的不確定信息時(shí),我們應(yīng)該有一個(gè)模型,甚至是無模式數(shù)據(jù)庫(kù)。盡管如此,持久性層仍然存在很多問題,主要是因?yàn)樗茈y改變。
制作可擴(kuò)展應(yīng)用程序的秘訣之一是確保它是無狀態(tài)的,但我們?cè)诔志眯詫又胸?fù)擔(dān)不起它。首先,數(shù)據(jù)庫(kù)旨在保留信息及其狀態(tài)。
使數(shù)據(jù)持久化層更自然的解決方案之一是直接與 Java 實(shí)體作為圖形集成。這就是Microstream所做的。
Microstream通過純Java實(shí)現(xiàn)超快的在內(nèi)存中處理數(shù)據(jù)。它提供微秒級(jí)查詢時(shí)間、低延遲數(shù)據(jù)訪問、巨大的數(shù)據(jù)吞吐量和工作負(fù)載。因此,它節(jié)省了數(shù)據(jù)中心的大量CPU功耗,二氧化碳排放和成本。
顯示代碼
讓我們將兩者結(jié)合起來,打造一個(gè)超快的微服務(wù)。一旦主要目標(biāo)是展示兩者如何結(jié)合,我們將選擇一個(gè)流暢的演示。在此示例中,我們將創(chuàng)建一個(gè)簡(jiǎn)單的 CRUD,其中包含產(chǎn)品、名稱和評(píng)級(jí),并將其導(dǎo)出為 Rest API。
第一步是創(chuàng)建MicroProfile骨架:它毫不費(fèi)力且流暢,主要是因?yàn)槲覀兛梢允褂肕icroProfile啟動(dòng)器進(jìn)行可視化配置。配置文件版本 4.1 、 Java 11 和 Open Liberty ,如下圖所示
現(xiàn)在有了應(yīng)用程序的骨架。下一步就是添加Microstream并使兩者協(xié)同工作。幸運(yùn)的是,有一個(gè)庫(kù)可以通過CDI擴(kuò)展集成兩者。因此,任何具有CDI和MicroProfile Config的應(yīng)用程序都可以借助此API工作。
請(qǐng)查看最新版本并將其添加到您的應(yīng)用程序中。
1.
2.one.microstream
3.microstream-integrations-cdi
4.LAST_VERSION_HERE
5.
骨架已設(shè)置,因此讓我們從代碼開始。模型是中心部分。一旦它是一個(gè)平滑的示例,我們將創(chuàng)建一個(gè)包含幾個(gè)字段的產(chǎn)品實(shí)體。使用Microstream的主要建議是使用不可變實(shí)體。因此,我們將創(chuàng)建一個(gè)產(chǎn)品作為不可變的實(shí)體。
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 如何將實(shí)體序列化為 JSON。
下一步是定義產(chǎn)品集合,我們稱之為“庫(kù)存”。庫(kù)存類是一組具有多種操作方法的產(chǎn)品。
此類是實(shí)體與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 Setproducts = 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 SetgetProducts() {
21. return Collections.unmodifiableSet(this.products);
22. }
23.
24. public OptionalfindById(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 PredicateisIdEquals(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. }
}
集合準(zhǔn)備就緒后,讓我們創(chuàng)建存儲(chǔ)庫(kù)。要使用我們的類,我們可以使用 CDI 中的注釋。我們需要將此操作提交到將要更改此集合的每個(gè)操作中。對(duì)于任何更改庫(kù)存的方法,都有一個(gè)InventoryInjectStore注釋為我們自動(dòng)處理它。
1.public interface ProductRepository
2.{
3. CollectiongetAll();
4.
5. Product save(Product item);
6.
7. OptionalfindById(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 CollectiongetAll() {
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 OptionalfindById(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. }
}
最后一步是將此產(chǎn)品公開為 Rest API。然后,我們將使用Jakarta EE API返回MicroProfile:JAX-RS。接下來,我們將使用 MicroProfile 創(chuàng)建 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 CollectiongetAll()
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.
}
就是這樣,我們可以測(cè)試正在運(yùn)行的應(yīng)用程序并檢查結(jié)果。
1.mvn clean package
2.java -jar target/openliberty-example.jar
3.
4.curl --location --request POST 'http://localhost:8080/products/' \
5.--header 'Content-Type: application/json' \
6.--data-raw '{"id": 1, "name": "banana", "description": "a fruit", "rating": 5}'
7.
8.curl --location --request POST 'http://localhost:8080/products/' \
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 'http://localhost:8080/products/'
13.
curl --location --request GET 'http://localhost:8080/products/1'
我們終于在Open Liberty和Microstream之間實(shí)現(xiàn)了集成。本教程展示了兩者如何協(xié)同工作,并為您提供了一個(gè)面對(duì)持久性問題的新工具:Microstream。事實(shí)上,當(dāng)你想要?jiǎng)?chuàng)建微服務(wù)來超快速運(yùn)行它時(shí),Microstream和Open Liberty就是偉大的盟友。
譯者介紹
朱鋼,社區(qū)編輯,2021年IT影響力專家博主,阿里云專家博主,2019年CSDN博客之星20強(qiáng),2020年騰訊云+社區(qū)優(yōu)秀作者,11年一線開發(fā)經(jīng)驗(yàn),曾參與獵頭服務(wù)網(wǎng)站架構(gòu)設(shè)計(jì),企業(yè)智能客服以及大型電子政務(wù)系統(tǒng)開發(fā),主導(dǎo)某大型央企內(nèi)部防泄密和電子文檔安全監(jiān)控系統(tǒng)的建設(shè),目前在北京圖伽健康從事醫(yī)療軟件研發(fā)工作。
原文標(biāo)題:??Ultra-Fast Microservices in Java: When Microstream Meets Open Liberty??,作者:Otavio Santana
網(wǎng)站名稱:Java中的超快微服務(wù):當(dāng)Microstream遇上OpenLiberty
文章位置:http://fisionsoft.com.cn/article/dhsspjd.html


咨詢
建站咨詢
