使用JHipster領域語言在30分鐘內建立完整的微服務棧

banq發表於2018-09-23
JHipster是Java Web應用程式和微服務開發的開發平臺。到目前為止我實現的最酷的功能肯定是使用JDL生成多個應用程式。

電子商務應用程式

那麼讓我們看看如何使用JHipster建立一個微服務堆疊。我們今天將建立一個電子商務商店。堆疊包括 -

1/ 使用JHipster Registry進行服務發現,這是一個包含Eureka伺服器和Spring雲配置伺服器的Spring啟動應用程式。

2. 使用Spring Boot,Netflix Zuul,ReactJS和Swagger的API管理和閘道器。

3. 使用Spring Boot的微服務。

4. 使用由彈性堆疊(ELK)和Zipkin組成的JHipster控制檯進行監控。

[img index=1]

閘道器將請求路由到兩個微服務,Invoice應用程式和Notification應用程式。

要求
為了學習本教程,您需要在計算機上安裝最新版本的Docker,Docker-compose,NodeJS和Java 8。以下是我安裝的版本。

$ docker -v                                                                                                                       
Docker version 18.06.1-ce, build e68fc7a

$ docker-compose -v                                
docker-compose version 1.20.1, build 5d8c71b

$ node -v                
v8.11.4

$ java -version          
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
<p class="indent">


首先,安裝最新版本的JHipster

$ npm install generator-jhipster -g

透過執行驗證您是否具有5.3.4或更高版本

$ jhipster --version

建立JDL

現在讓我們建立我們的JDL。轉到JDL Studio(暫時使用舊版本,因為JDL 3更新尚未針對新的JDL工作室釋出)或喜歡的IDE /編輯器(如果您願意,可以使用JHipster IDE外掛)。

首先,讓我們定義我們的應用程式。我們將從Gateway開始:

application {
  config {
    baseName store,
    applicationType gateway,
    packageName com.jhipster.demo.store,
    serviceDiscoveryType eureka,
    authenticationType jwt,
    prodDatabaseType mysql,
    cacheProvider hazelcast,
    buildTool gradle,
    clientFramework react,
    useSass true,
    testFrameworks [protractor]
  }
  entities *
}
<p class="indent">


大多數的選項是不言自明的,我們正在建立一個名為store型別應用,其閘道器帶有JWT認證,以eureka為基礎的服務發現。該應用程式使用MySQL資料庫和Hazelcast作為快取。它是使用Gradle構建的。對於客戶端,它使用React和Sass。它還有用於端到端測試的Protractor。

在定義的最後你可以看到entities *,我們稍後會討論。

現在讓我們定義我們的Invoice微服務:

application {
  config {
    baseName invoice,
    applicationType microservice,
    packageName com.jhipster.demo.invoice,
    serviceDiscoveryType eureka,
    authenticationType jwt,
    prodDatabaseType mysql,
    buildTool gradle,
    serverPort 8081,
    skipUserManagement true
  }
  entities Invoice, Shipment
}
<p class="indent">


它遵循類似的選項,如我們的閘道器,因為它是微服務,它沒有定義任何客戶端選項,也跳過使用者管理,因為它將由閘道器處理。此外,我們還提到了自定義埠8081,因為我們不希望此應用程式與閘道器使用的預設埠8080衝突。

現在讓我們定義第二個微服務,Notification應用程式:

application {
  config {
    baseName notification,
    applicationType microservice,
    packageName com.jhipster.demo.notification,
    serviceDiscoveryType eureka,
    authenticationType jwt,
    databaseType mongodb,
    prodDatabaseType mongodb,
    devDatabaseType mongodb,
    cacheProvider no,
    enableHibernateCache false,
    buildTool gradle,
    serverPort 8082,
    skipUserManagement true
  }
  entities Notification
}
<p class="indent">

此應用程式遵循許多類似於Gateway和Invoice應用程式的選項,但它不使用MySQL,而是使用MongoDB作為其資料庫並禁用快取。


現在我們的應用程式定義已經完成,我們將繼續定義我們的實體模型。

對於我們的閘道器商店應用程式,讓我們定義以下實體和列舉:

/** Product sold by the Online store */
entity Product {
    name String required
    description String
    price BigDecimal required min(0)
    size Size required
    image ImageBlob
}
enum Size {
    S, M, L, XL, XXL
}
entity ProductCategory {
    name String required
    description String
}
entity Customer {
    firstName String required
    lastName String required
    gender Gender required
    email String required pattern(/^[^@\s]+@[^@\s]+\.[^@\s]+$/)
    phone String required
    addressLine1 String required
    addressLine2 String
    city String required
    country String required
}
enum Gender {
    MALE, FEMALE, OTHER
}
entity ProductOrder {
    placedDate Instant required
    status OrderStatus required
    code String required
    invoiceId Long
}
enum OrderStatus {
    COMPLETED, PENDING, CANCELLED
}
entity OrderItem {
    quantity Integer required min(0)
    totalPrice BigDecimal required min(0)
    status OrderItemStatus required
}
enum OrderItemStatus {
    AVAILABLE, OUT_OF_STOCK, BACK_ORDER
}
relationship OneToOne {
    Customer{user(login) required} to User
}
relationship ManyToOne {
    OrderItem{product(name) required} to Product
}
relationship OneToMany {
    Customer{order} to ProductOrder{customer(email) required},
    ProductOrder{orderItem} to OrderItem{order(code) required} ,
    ProductCategory{product} to Product{productCategory(name)}
}
service Product, ProductCategory, Customer, ProductOrder, OrderItem with serviceClass
paginate Product, Customer, ProductOrder, OrderItem with pagination
<p class="indent">


JDL定義實體,列舉,實體和選項(如分頁和服務層)之間的關係。

實體欄位定義遵循語法:

entity <entity name> {
  <field name> <type> [<validation>*]
}
<p class="indent">

關係定義遵循語法:

relationship (OneToMany | ManyToOne | OneToOne | ManyToMany) {
    <from entity>[{<relationship name>[(<display field>)]}] 
    to 
    <to entity>[{<relationship name>[(<display field>)]}]
}
<p class="indent">


請參閱JDL文件以獲取完整的DSL參考。

Invoice微服務應用程式具有以下實體:

entity Invoice {
    code String required
    date Instant required
    details String
    status InvoiceStatus required
    paymentMethod PaymentMethod required
    paymentDate Instant required
    paymentAmount BigDecimal required
}
enum InvoiceStatus {
    PAID, ISSUED, CANCELLED
}
entity Shipment {
    trackingCode String
    date Instant required
    details String
}
enum PaymentMethod {
    CREDIT_CARD, CASH_ON_DELIVERY, PAYPAL
}
relationship OneToMany {
    Invoice{shipment} to Shipment{invoice(code) required}
}
service Invoice, Shipment with serviceClass
paginate Invoice, Shipment with pagination
microservice Invoice, Shipment with invoice
<p class="indent">


注意這裡宣告的最後一行microservice選項,它指定這些實體屬於名為invoice的微服務,以便我們的閘道器知道在哪裡為這些實體路由請求。

現在讓我們看一下Notification微服務應用程式的實體:

entity Notification {
    date Instant required
    details String
    sentDate Instant required
    format NotificationType required
    userId Long required
    productId Long required
}
enum NotificationType {
    EMAIL, SMS, PARCEL
}
microservice Notification with notification
<p class="indent">


現在讓我們在看看定義中使用的實體:

application {
  config {
    ...
  }
  entities *
}
application {
  config {
    ...
  }
  entities Invoice, Shipment
}
application {
  config {
    ...
  }
  entities Notification
}
/* Entities for Store Gateway */
entity Product {
    ...
}
entity ProductCategory {
    ...
}
entity Customer {
    ...
}
entity ProductOrder {
    ...
}
entity OrderItem {
    ...
}
microservice Invoice, Shipment with invoice
/* Entities for Invoice microservice */
entity Invoice {
    ...
}
entity Shipment {
    ...
}
/* Entities for notification microservice */
entity Notification {
    ...
}
microservice Notification with notification
<p class="indent">

在這裡,我們指示商店閘道器應用程式它應該包含JDL中定義的所有實體,並且閘道器將知道跳過屬於被呼叫微服務的實體程式碼,因此只會為這些實體生成呼叫者客戶端程式碼,這裡是 Invoice, Shipment, 和 Notification。

我們還指示Invoice應用程式和Notification應用程式包含其實體。

生成應用程式

建立一個我們想要建立微服務堆疊的資料夾:

$ mkdir ecommerce && cd ecommerce

現在,讓我們將所有內容放在一起成為JDL檔案。讓我們呼叫它app.jdl並將其儲存到此資料夾中。

application {
  config {
    baseName store,
    applicationType gateway,
    packageName com.jhipster.demo.store,
    serviceDiscoveryType eureka,
    authenticationType jwt,
    prodDatabaseType mysql,
    cacheProvider hazelcast,
    buildTool gradle,
    clientFramework react,
    useSass true,
    testFrameworks [protractor]
  }
  entities *
}
application {
  config {
    baseName invoice,
    applicationType microservice,
    packageName com.jhipster.demo.invoice,
    serviceDiscoveryType eureka,
    authenticationType jwt,
    prodDatabaseType mysql,
    buildTool gradle,
    serverPort 8081,
    skipUserManagement true
  }
  entities Invoice, Shipment
}
application {
  config {
    baseName notification,
    applicationType microservice,
    packageName com.jhipster.demo.notification,
    serviceDiscoveryType eureka,
    authenticationType jwt,
    databaseType mongodb,
    prodDatabaseType mongodb,
    devDatabaseType mongodb,
    cacheProvider no,
    enableHibernateCache false,
    buildTool gradle,
    serverPort 8082,
    skipUserManagement true
  }
  entities Notification
}
/* Entities for Store Gateway */
/** Product sold by the Online store */
entity Product {
    name String required
    description String
    price BigDecimal required min(0)
    size Size required
    image ImageBlob
}
enum Size {
    S, M, L, XL, XXL
}
entity ProductCategory {
    name String required
    description String
}
entity Customer {
    firstName String required
    lastName String required
    gender Gender required
    email String required pattern(/^[^@\s]+@[^@\s]+\.[^@\s]+$/)
    phone String required
    addressLine1 String required
    addressLine2 String
    city String required
    country String required
}
enum Gender {
    MALE, FEMALE, OTHER
}
entity ProductOrder {
    placedDate Instant required
    status OrderStatus required
    code String required
    invoiceId Long
}
enum OrderStatus {
    COMPLETED, PENDING, CANCELLED
}
entity OrderItem {
    quantity Integer required min(0)
    totalPrice BigDecimal required min(0)
    status OrderItemStatus required
}
enum OrderItemStatus {
    AVAILABLE, OUT_OF_STOCK, BACK_ORDER
}
relationship OneToOne {
    Customer{user(login) required} to User
}
relationship ManyToOne {
 OrderItem{product(name) required} to Product
}
relationship OneToMany {
   Customer{order} to ProductOrder{customer(email) required},
   ProductOrder{orderItem} to OrderItem{order(code) required} ,
   ProductCategory{product} to Product{productCategory(name)}
}
service Product, ProductCategory, Customer, ProductOrder, OrderItem with serviceClass
paginate Product, Customer, ProductOrder, OrderItem with pagination
/* Entities for Invoice microservice */
entity Invoice {
    code String required
    date Instant required
    details String
    status InvoiceStatus required
    paymentMethod PaymentMethod required
    paymentDate Instant required
    paymentAmount BigDecimal required
}
enum InvoiceStatus {
    PAID, ISSUED, CANCELLED
}
entity Shipment {
    trackingCode String
    date Instant required
    details String
}
enum PaymentMethod {
    CREDIT_CARD, CASH_ON_DELIVERY, PAYPAL
}
relationship OneToMany {
    Invoice{shipment} to Shipment{invoice(code) required}
}
service Invoice, Shipment with serviceClass
paginate Invoice, Shipment with pagination
microservice Invoice, Shipment with invoice
/* Entities for notification microservice */
entity Notification {
    date Instant required
    details String
    sentDate Instant required
    format NotificationType required
    userId Long required
    productId Long required
}
enum NotificationType {
    EMAIL, SMS, PARCEL
}
microservice Notification with notification
<p class="indent">


現在讓我們呼叫JHipster CLI來匯入這個檔案:

$ jhipster import-jdl app.jdl

這將建立商店,發票和通知資料夾,並在每個資料夾中執行以下操作

生成適當的應用程式和實體配置。
根據配置生成應用程式和實體原始碼。
為應用程式安裝NPM依賴項。
完成該過程後,您應該在控制檯上看到以下內容:

Entity Product generated successfully.
Entity ProductCategory generated successfully.
Entity Customer generated successfully.
Entity ProductOrder generated successfully.
Entity OrderItem generated successfully.
Entity Invoice generated successfully.
Entity Shipment generated successfully.
Entity Notification generated successfully.
Congratulations, JHipster execution is complete!
<p class="indent">


使用Docker執行應用程式
首先讓我們使用JHipster生成一些docker compose配置。
在ecommerce資料夾中建立一個新資料夾,然後執行JHipster docker-compose命令

$ mkdir 
docker -compose && cd docker -compose $ jhipster docker-compose
<p class="indent">[/code

它會提示您幾個問題,選擇下面突出顯示的答案:

<p class="indent">[code]
Files will be generated in folder: /home/deepu/workspace/temp/ecommerce/docker-compose
✔ Docker is installed

? Which *type* of application would you like to deploy? Microservice application

? Which *type* of gateway would you like to use? JHipster gateway based on Netflix Zuul

? Enter the root directory where your gateway(s) and microservices are located ../

3 applications found at /home/deepu/workspace/temp/ecommerce/
? Which applications do you want to include in your configuration? invoice, notification, store

? Which applications do you want to use with clustered databases (only available with MongoDB and Couchbase)? 

? Do you want to setup monitoring for your applications ? Yes, for logs and metrics with the JHipster Console (based on ELK and Zipkin)

? You have selected the JHipster Console which is based on the ELK stack and additional technologies, which one do you want to use ? Zipkin, for distributed tracing (only compatible with
 JHipster >= v4.2.0)

JHipster registry detected as the service discovery and configuration provider used by your apps
? Enter the admin password used to secure the JHipster Registry
 admin
<p class="indent">


這將為堆疊生成所有必需的docker-compose配置,並且還將列印出構建docker映象的更多指令。

Docker Compose configuration generated with missing images!
To generate the missing Docker image(s), please run:
  ./gradlew -Pprod bootWar buildDocker in /home/deepu/workspace/temp/ecommerce/invoice
  ./gradlew -Pprod bootWar buildDocker in /home/deepu/workspace/temp/ecommerce/notification
  ./gradlew -Pprod bootWar buildDocker in /home/deepu/workspace/temp/ecommerce/store
<p class="indent">


按照說明構建docker映象。構建完所有3個後,從docker-compose資料夾中執行以下命令以啟動所有內容。

$ docker-compose up -d

容器啟動後,可以使用以下命令流式傳輸日誌

docker-compose logs -f

瀏覽 http://localhost:8080/ 看到你的電子商務網站上線了。

Create full Microservice stack using JHipster Doma

相關文章