Micronaut:面向未來的微服務和雲原生應用框架
白小白 :
這是一篇花費小白較長時間的譯文,主要在於如何以零Java基礎的視角來理解和表達文中的諸多概念以及保證後續示例應用的部分可以正常執行。
依賴注入、控制反轉和麵向切面程式設計,是Micronaut有別於Spring Boot這類傳統框架的核心部分。關於這幾個概念,我推薦不瞭解的同學瀏覽下面的文章,輕鬆易懂。
輕鬆理解AOP(面向切面程式設計)
https://blog.csdn.net/yanquan345/article/details/19760027
依賴注入的簡單理解
https://www.cnblogs.com/alltime/p/6729295.html
友情提示,請注意文中小白的提示,有些段落如果沒有按照教程,是可能導致嘗試失敗的,切記。
經測試可以成功執行示例程式碼的環境如下 :
SDKMAN 5.7.2+323
java version "1.8.0_181"
Using micronaut version 1.0.0.M4
祝大家玩的愉快。
一、導言
今年5月,OCI的一個開發團隊釋出了新的開源框架Micronaut的第一個里程碑版本。
Micronaut是JVM的應用程式框架,主要用以建立 微服務 和 雲原生應用程式 。
可以理解,在一個似乎充斥著框架選項的行業中,開發者通常想要預先了解一個新框架帶來了什麼以及它提供了哪些獨特的特性或功能。
本文的目的是:
● 介紹microronaut背後的一些基本原理。
● 強調使用框架的一些關鍵優勢。
● 介紹一個簡單的應用程式,以全面瞭解框架的構造和程式設計風格。
二、內容精要
Micronaut是一個JVM框架,用於使用 Java、Groovy或Kotlin來建立可伸縮的高效能應用。
它提供了包括但不限於以下的所有特性:
● 提供高效率的 編譯時依賴注入(Dependency Injection,後文簡稱DI)容器
● 提供一套 雲原生 特性 用以在構建微服務系統時提高開發人員的生產力
該框架從Spring和Grails獲得靈感,提供了熟悉的開發流程,但是 最小化了啟動時間和記憶體使用 。因此,Micronaut可以用於一系列傳統MVC(Model/View/Controller)框架無能為力的場景:包括Android應用程式、無伺服器函式、IOT部署和CLI應用程式等。
三、單體式應用的崛起
目前正在開發的大多數JVM Web應用程式都基於倡導MVC模式的框架,並提供依賴注入、面向切面程式設計(AOP)支援和易於配置等特性。
Spring Boot和Grails等框架依賴Spring IoC(反轉控制)容器,使用反射機制在執行時分析應用程式類,然後將它們連線在一起來構建應用的依賴關係圖。反射元資料還用於為事務管理等功能生成代理。
這些框架給開發人員帶來了許多好處,包括提高生產力、減少冗餘程式碼和建立更具表現力的應用程式程式碼。
許多此類框架是圍繞單體應用設計的。單體應用是一個獨立的程式,管理從底層資料庫到前端UI的整個應用程式的堆疊,然後將應用程式打包為servlet容器等二進位制檔案,並部署到Tomcat、Glassfish等伺服器上。在一個更完整的工作流程中,框架就可以引入這些嵌入式容器,從而使應用程式更具可移植性。
四、雲化的微服務
今天,這些傳統的應用程式架構正在被新的模式和技術所取代。
許多組織正在將所謂的單體應用程式分解為更小的、面向服務的應用程式,這些應用程式在分散式系統中協同工作。
新的體系結構模式要求通過多個功能受限、相互獨立的微服務應用程式的互動來滿足業務需求:.
跨服務邊界的通訊是微服務設計的關鍵,通常採用RESTful HTTP呼叫來完成。

然而,現代框架不僅需要簡化開發,還需要簡化運維。
現代應用程式比以往任何時候都更加依賴於雲端計算技術。
相較於自建伺服器和資料中心並費心管理其健康狀況,越來越多的組織將其應用程式部署到雲端平臺之上,使用者不需要了解伺服器的細節,就可以使用功能完備的工具和自動化手段對服務進行伸縮、重新部署和監控。
五、反射機制的問題
誠然,傳統框架在很大程度上一直在緊跟行業的步伐,許多開發人員已經成功地使用這些構架構建了微服務並將其部署到雲端。
然而,在此過程中,新架構和雲環境的需求都暴露了一些潛在的痛點。對 執行時反射 (依賴注入和代理生成)機制的依賴帶來了一些效能問題,包括啟動、分析和連線應用程式所需的時間需求,以及載入和快取這些元資料所需的記憶體需求。
更不幸的是,在給定的應用程式中,對這些問題的考量需要隨著codebase的大小和資源需求的增加動態變化。
時間和記憶體都是在使用雲平臺過程中需要花費真金白銀的資源。服務需要被回收,並以最小的延遲重新上線。而且服務的數量也在增加(在大規模系統上可能會增加到數百個)。很明顯,對於每個服務的多個例項,在享用傳統框架所帶來的便利性的同時,需要支付相應的現實成本。
此外,許多雲提供商正在提供 無伺服器 平臺,如AWS Lambda,其中應用程式簡化為單一用途函式,用以組合和編排以執行復雜業務邏輯。
無伺服器計算的輕量級、響應性和最小化的記憶體消耗的優勢,讓傳統的、基於反射的框架的問題體現的更為突出。
六、更好的方法
Micronaut為微服務和雲端應用設計,保留了MVC程式設計模型和傳統框架的其他特性。這主要是得益於一個全新的DI/AOP容器,該容器在 編譯時 而不是執行時提供依賴注入機制。
通過在程式碼中註釋類和類成員,您可以使用與Spring非常相似的約定來表示應用程式的依賴關係和AOP行為;然而,在編譯應用程式時就會完成對元資料的分析。此時,Micronaut將在原始程式碼之外生成額外的類,建立bean定義、攔截器和其他工件,以便在應用程式執行時啟用DI/AOP行為。
提示:從技術上講,這種編譯時處理是通過使用Java 註釋處理器 實現的,Micronaut用這些處理器來分析類以及建立相關的bean定義類。對於支援Groovy的框架來說,相關處理是使用 AST變換 進行的。
Micronaut實現了JSR 330 Java依賴項注入規範,在javax.inject包(如@Inject和@Singleton)之下,提供了語義註解,來表示DI容器中的類與類關係。
下面的清單顯示了Micronaut DI的一個簡單示例。
import javax.inject.*;
interface Engine {
int getCylinders();
String start();
}
@Singleton
public class V8Engine implements Engine {
int cylinders = 8;
String start() {
return "Starting V8";
}
}
@Singleton
public class Vehicle {
final Engine engine
public Vehicle(Engine engine) {
this.engine = engine;
}
String public start() {
return engine.start();
}
}
當應用程式執行時,將生成一個新的Vehicle例項和Engine介面,在本例中是V8Engine。
import io.micronaut.context.*;
Vehicle vehicle = BeanContext.run().getBean(Vehicle);
System.out.println( vehicle.start() );
通過將DI容器的工作移到編譯階段,codebase的大小與啟動應用程式所需的時間之間或者儲存反射元資料所需的記憶體之間,不再有關聯關係。
因此,用Java編寫的Micronaut應用程式通常可以秒啟。
白小白:
呃,經小白的實際測試,即使是一個Hello World,在Gradle環境下也需要6秒左右的時間,這還是第二次執行的情況,首次執行需要28秒左右。秒起多少有點誇張。當然也可能因為是在Laptop而非伺服器端環境。
Gradle
> ./gradlew run
Task :run
16:21:32.511 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 842ms. Server Running: http://localhost:8080
Maven
> ./mvnw compile exec:exec
[INFO] Scanning for projects...
[INFO] --- exec-maven-plugin:1.6.0:exec (default-cli) @ my-java-app ---
16:22:49.833 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 796ms. Server Running: http://localhost:8080
用Groovy和Kotlin編寫的應用程式可能需要超過1秒的時間,原因在於語言方面的開銷,以及使用第三方類庫(如Hibernate)增加了啟動和記憶體需求。好在,無論是在啟動時間還是記憶體需求方面,codebase的大小都不再是一個重要因素;編譯後的位元組碼已經包含了執行和管理DI類所需的一切資源。
七、HTTP層
Micronaut的DI核心是微服務框架的一個重要部分,通過HTTP暴露服務和呼叫其他服務是微服務體系結構的另一個重要組成部分。
Micronaut的HTTP層,基於Netty建立,Netty提供了高效能的非同步網路框架, 反應事件驅動程式設計模型 ,以及對建立 伺服器-客戶端 應用的支援。
在微服務系統中,許多應用程式將同時扮演這兩種角色:通過網路暴露資料的服務端和針對系統中其他服務提出請求的客戶端。
與傳統框架一樣,Micronaut也包含了 Controller 為請求服務。下面是一個簡單的Micronaut controller。
HelloController.java
import io.micronaut.http.annotation.*;
@Controller("/hello")
public class HelloController {
@Get("/{name}")
public String hello(String name) {
return "Hello, " + name;
}
}
這個簡單的例子演示了許多Java MVC框架使用的熟悉的程式設計模型。Controller只是帶有方法的類,每個類都帶有具備含義的註釋,Micronaut使用這些註釋在編譯時建立必要的HTTP處理程式碼。
在微服務環境中,同樣重要的是作為客戶端與其他服務互動。
Micronaut提供了額外的屬性,以使其HTTP客戶端功能與伺服器的功能相當,呼叫服務的程式碼與建立服務的程式碼看起來非常相似。
下面是一個簡單的Micronaut客戶端程式碼,它將呼叫上面提供的控制器端點。
HelloClient.java
import io.micronaut.http.client.Client;
import io.micronaut.http.annotation.*;
@Client("/hello")
public interface HelloClient {
@Get("/{name}")
public String hello(String name);
}
HelloClient現在可以和執行在/hello URI的服務進行互動,在DI容器中建立客戶端bean所需的所有程式碼,包括執行HTTP請求、繫結引數,甚至解析響應,都是在編譯時生成的。
此客戶端可以在示例應用程式中使用,這是一個單獨的服務(假設URL設定正確或啟用了 服務發現 ),或者在如下所示測試類中使用。
HelloClientSpec.groovy
import io.micronaut.runtime.server.EmbeddedServer
import spock.lang.*
class HelloClientSpec extends Specification {
//start the application
@Shared
@AutoCleanup
EmbeddedServer embeddedServer =
ApplicationContext.run(EmbeddedServer)
//get a reference to HelloClient from the DI container
@Shared
HelloClient client =
embeddedServer.applicationContext.getBean(HelloClient)
void "test hello response"() {
expect:
client.hello("Bob") == "Hello, Bob"
}
}
由於客戶端方法和伺服器方法共享相同的簽名,因此通過實現共享介面,可以輕鬆地在請求兩端之間強制執行協議,該介面可以儲存在跨微服務系統使用的共享庫中。
在我們的例子中,HelloController和HelloClient都可從共享介面HelloOperations實現/擴充套件而來。
HelloOperations.java
import io.micronaut.http.annotation.*;
public interface HelloOperations {
@Get("/{name}")
public String hello(String name);
}
HelloClient.java
@Client("/hello")
public interface HelloClient extends HelloOperations {/*..*/ }
HelloController.java
@Controller("/hello")
public class HelloController extends HelloOperations {/*..*/ }
八、天生的反應性
反應式程式設計是Netty和Micronaut的核心概念。
上面的controller和client可以很容易的基於任何Reactive Streams實現來進行編寫,例如RxJava 2.0。這允許您以完全非阻塞的方式(諸如Observable, Subscriber,和Single結構)來編寫所有HTTP邏輯。
RxHelloController.java
import io.reactivex.*;
@Controller("/hello")
public class RxHelloController {
@Get("/{name}")
public Single<String> hello(String name) {
return Single.just("Hello, " + name);
}
}
RxHelloClient.java
import io.reactivex.*;
@Client("/hello")
public interface RxHelloClient {
@Get("/{name}")
public Single<String> hello(String name);
}
九、天然的雲原生
雲原生應用程式被專門設計為在雲端計算環境中操作,與系統中的其他服務互動,並在其他服務變得不可用或沒有響應時優雅地實現降級。
Micronaut提供了一整套的屬性來使得構建雲原生應用程式的過程非常愉快。
Micronaut為許多最常見的需求提供原生解決方案,而不是依賴第三方工具或服務。
讓我們來看看其中的幾個需求。
1、服務發現
服務發現意味著應用程式能夠在集中的註冊中心找到彼此,而無需在配置中查詢URL或硬編碼的伺服器地址。
Micronaut將服務發現支援直接構建於@Client註釋中,從而執行服務發現非常簡單,只需提供正確的配置,然後使用“服務ID”來發現所需服務。
例如,下面的配置將Micronaut應用程式註冊為Consul(一個分散式的服務發現和配置管理工具)例項,使用的服務ID為hello-world.
src/main/resources/application.yml
micronaut:
application:
name: hello-world
consul:
client:
registration:
enabled: true
defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}"
應用程式啟動並向Consul註冊後,客戶端可以通過簡單地在@Client註釋中指定服務ID來查詢服務。
@Client(id = "hello-world")
public interface HelloClient{
//...
}
Micronaut目前支援Consul和Kubernetes,並計劃支援更多的服務發現框架。
2、負載均衡
當註冊同一服務的多個例項時,Micronaut提供一種“輪詢排程”機制的負載平衡,通過對可用例項發出輪詢請求,以確保沒有例項被壓垮或浪費。
這是一種 客戶端負載平衡 機制,每個例項要麼接受當前請求,要麼將請求傳遞給服務的下一個例項,從而自動將負載分散到可用的例項中。
這種負載均衡方案是Micronaut內建的,免費提供給使用者。但是,Micronaut也支援替代實現,如,安裝和配置Netflix Ribbon庫來作為負載平衡策略。
src/main/resources/application.yml
ribbon:
VipAddress: test
ServerListRefreshInterval: 2000
3、重試和斷路器
當與分散式系統中的其他服務互動時,不可避免的是,在某些時候,事情不會按計劃進行;也許某個服務會暫時停止,或者只是簡單地放棄了一個請求。
Micronaut提供了許多工具來優雅地處理這些災難性場景。
例如,Micronaut中的任何方法都可以用@Retryable註釋來應用自定義的重試策略。當註釋應用於@Client介面時,重試策略將應用於客戶端中的每個請求方法。
@Retryable
@Client("/hello")
public interface HelloClient { /*...*/ }
預設情況下,@Retryable將嘗試呼叫該方法三次,每次嘗試之間有一秒的延遲。
當然,可以重寫這些值,例如:
@Retryable( attempts = "5", delay = "2s" )
@Client("/hello")
public interface HelloClient { /*...*/ }
當然,如果對硬編碼的方式不感冒,也可以配置中注入相關數值,如果沒有提供配置,將使用預設值。
@Retryable( attempts = "${book.retry.attempts:3}",
delay = "${book.retry.delay:1s}" )
@Client("/hello")
public interface HelloClient { /*...*/ }
@Retryable的一種更復雜的形式是@CircuitBreaker註釋。和上面的行為模式略有不同,@CircuitBreaker將允許設定一個reset期間(預設情況下為30秒),在此時間視窗內,一定數量的請求在可能的死迴圈開始之前就會失敗,被呼叫方法會立即失敗,其內部的程式碼也不會執行。
這可以幫助防止陷入困境的服務或其他下游資源被請求淹沒,給它們一個恢復的機會。
@CircuitBreaker( attempts = "3", reset = "20s")
@Client("/hello")
public interface HelloClient { /*...*/ }
十、構建Micronaut應用程式
真正瞭解一個框架的最好方法是上手實踐,所以我們將用一個漸進的指南來結束對Micronaut的介紹,通過這個指南,你將構建你的第一個Micronaut應用程式。
作為附加題,我們還將更進一步將我們的“微服務”作為容器部署到雲端,在本例中是Google計算引擎.
步驟1:安裝Micronaut
Microronaut可以從GitHub程式碼安裝,或者下載二進位制檔案本地安裝。我們建議使用sdkman來進行安裝。
如果還沒有安裝sdkman,則可以在任何基於Unix的shell中使用以下命令安裝sdkman:
> curl -s "https://get.sdkman.io" | bash
> source "$HOME/.sdkman/bin/sdkman-init.sh"
> sdk version
SDKMAN 5.6.4+305
白小白 :
安裝過程需要使用zip和unzip,因此這兩個應用需要預先安裝,對於我本機的ubuntu 16.04,安裝方式是 sudo apt-get install zip unzip。此外,sdk version可能會遇到臨時的網路問題而提示失敗,重試一下就好。
現在可以使用以下sdkman命令安裝Micronaut。
(使用sdk list micronaut檢視可用版本,請執行以下操作。目前最新的是1.0.0.M2.)
> sdk install micronaut 1.0.0.M2
白小白 :
成文時,最新版本已經更新為1.0.0.RC1,本文嘗試了M2和M4兩個版本,並且指定版本號的部分並非必須,即預設安裝最新版本。建議仍舊指定M2版本以順利完成教程,因本文的示例是基於M2版本的,M4版本和M2版本使用上有一定差異,會導致示例程式碼的執行失敗,後續會介紹。當然,可以通過指定版本號的方式,兩個版本都安裝,然後使用sdk default micronaut 版本號來切換當前版本。
通過執行mn -v。
mn -v
| Micronaut Version: 1.0.0.M2
| JVM Version: 1.8.0_171
白小白 :
當然,既然是基於JVM的框架,在安裝Micronaut前你本機先要安裝JDK。另外,mn -v在M4版本下不會顯示版本號,而是進入mn的互動式模式。M4顯示版本號應該執行mn –version。
步驟2:建立專案
mn命令是Micronaut的CLI。您可以使用此命令建立新的Micronaut專案。
在本練習中,我們將建立一個現成的Java應用程式,但也可以通過新增-lang 標誌來使用其他你喜歡的語言,如Groovy 或者 Kotlin (-lang groovy或-lang kotlin).
mn命令接受features標誌,可以新增對專案中各種類庫和配置的支援。可以通過執行mn profile-info services來檢視所有可用的features。
我們要用spock標誌在專案中新增對Spock測試框架的支援。執行以下命令:
mn create-app example.greetings -features spock
| Application created at /Users/dev/greetings
白小白 :
在M4版本中,添加了-features spock的情況下會導致執行失敗。因為在M4版本中,-features的正確寫法是--features或者-f,其他諸如前文的-lang和後文的-build與此規則類似。
注意,我們可以為專案名稱(greetings)提供一個預設的包字首(example)。否則,專案名稱將被用作預設包,此包將包含Application類和使用CLI命令生成的任何類,稍後我們會做介紹。
預設情況下,create-app命令將生成一個Gradle構建。如果您希望使用Maven作為構建工具,則可以使用-build標誌。
此時,您可以使用Gradle的run命令執行應用程式。
./gradlew run
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :run
03:00:04.807 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 1109ms. Server Running: http://localhost:37619
注意,每次執行應用程式時都會隨機選擇伺服器埠。當使用服務發現解決方案來定位例項時,這是有意義的,但是對於我們的練習來說,將埠號設定為一個已知的值(比如8080)更方便些。我們將在下面的步驟中這樣做。
提示:如果希望使用IDE執行Micronaut專案,請確保IDE支援Java註釋處理器,併為專案啟用了這種支援。在IntelliJ IDEA中,相關設定在Preferences → Build, Execution, Deployment → Compiler → Annotation Processors → Enabled。
步驟3:配置
Micronaut中的預設配置格式是YAML,但也支援其他格式,包括Java屬性檔案、Groovy配置和JSON。
預設配置檔案位於src/main/resources/application.yml。讓我們編輯這個檔案來設定我們的伺服器埠號。
src/main/resources/application.yml
micronaut:
application:
name: greetings
server:
port: 8080
如果重新啟動應用程式,您將看到它繼續執行http://localhost:8080.
步驟4:編寫程式碼
在專案目錄中,執行mn命令以互動模式啟動Micronaut CLI。
> mn
| Starting interactive mode...
| Enter a command name to run. Use TAB for completion:
mn>
執行以下兩個命令來生成控制器、客戶端和服務bean。
白小白 :
此處顯然是筆誤,實際上是3條命令。
mn> create-controller GreetingController
| Rendered template Controller.java to destination src/main/java/greetings/GreetingController.java
| Rendered template ControllerSpec.groovy to destination src/test/groovy/greetings/GreetingControllerSpec.groovy
mn> create-client GreetingClient
| Rendered template Client.java to destination src/main/java/greetings/GreetingClient.java
mn> create-bean GreetingService
| Rendered template Bean.java to destination src/main/java/demo/GreetingService.java
編輯生成的檔案,如下面三個清單所示
src/main/java/example/GreetingController.java
package example;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.reactivex.Single;
import javax.inject.Inject;
@Controller("/greeting")
public class GreetingController {
@Inject
GreetingService greetingService;
@Get("/{name}")
public Single<String> greeting(String name) {
return greetingService.message(name);
}
}
.src/main/java/example/GreetingClient.java
package example;
import io.micronaut.http.client.Client;
import io.micronaut.http.annotation.Get;
import io.reactivex.Single;
@Client("greeting")
public interface GreetingClient {
@Get("/{name}")
Single<String> greeting(String name);
}
.src/main/java/example/GreetingService.java
package example;
import io.reactivex.Single;
import javax.inject.Singleton;
@Singleton
public class GreetingService {
public Single<String> message(String name) {
return Single.just("Hello, " + name);
}
}
在編寫了控制器、客戶端和服務類之後,如果我們再次執行應用程式,我們應該能夠發出請求,如下面所示的curl命令。
> curl http://localhost:8080/greeting/Beth
Hello, Beth
讓我們編輯生成的GreetingControllerSpec利用我們的客戶端介面。
.src/test/groovy/example/GreetingControllerSpec.groovy
package example
import io.micronaut.context.ApplicationContext
import io.micronaut.runtime.server.EmbeddedServer
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification
class GreetingControllerSpec extends Specification {
@Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer)
void "test greeting"() {
given:
GreetingClient client = embeddedServer.applicationContext.getBean(GreetingClient)
expect:
client.greeting("Beth").blockingGet() == "Hello, Beth"
}
}
執行./gradlew test執行測試(如果啟用了註釋處理,也可以在IDE中執行測試)。
白小白 :
此處,直接執行是會報錯的,找不到greeting這個service,需要註釋掉given:和expect:這兩行,此外,在我的版本,成功測試後會有一個關於Gradle的Wanning,不影響後續嘗試,可以忽略
./gradlew test
BUILD SUCCESSFUL in 6s
步驟5:部署到雲端
為了部署我們的應用程式,我們需要生成一個可執行的構建工件。執行Gradle任務shadowJar建立一個可執行的“fat”JAR檔案。
> ./gradlew shadowJar
BUILD SUCCESSFUL in 6s
3 actionable tasks: 3 executed
使用java -jar命令來測試Jar檔案是否正常執行。
java -jar build/libs/greetings-0.1-all.jar
03:44:50.120 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 847ms. Server Running: http://localhost:8080
接下來的幾個步驟來自Google Cloud網站上的文件。進行如下操作前,你需要一個谷歌雲賬號並在設定中啟用billing enabled。
Google雲設定
1.在Google Cloud控制檯 建立一個專案。
2.確保在API類庫中啟用了Compute Engine和Cloud Storage API.
3.安裝Google Cloud SDK。執行gcloud init來初始化SDK並選擇在步驟1中建立的新專案。
上傳JAR包
1.建立一個新的Google儲存bucket來儲存JAR檔案。在本例中的bucket名稱是:greetings。
白小白 :
幾乎可以確定的是此處你一定會遇到“ServiceException: 409 Bucket greetings already exists.”的錯誤,因為geetings這個bucket名稱已經被使用了。你需要改成其他的不會重複的名字,比如greetings-micronaut-當前日期。
> gsutil mb gs://greetings
2.上傳greetings-all.jar歸檔到新的bucket。
gsutil cp build/libs/greetings-0.1-all.jar gs://greetings/greetings.jar
建立例項啟動指令碼
Google Compute允許使用Bash指令碼提供一個新例項。在專案目錄中建立一個名為instance-startup.sh。新增以下內容:
#!/bin/sh
# Set up instance metadata
PROJECTID=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google")
BUCKET=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/BUCKET" -H "Metadata-Flavor: Google")
echo "Project ID: ${PROJECTID} Bucket: ${BUCKET}"
# Copy the JAR file from the bucket
gsutil cp gs://${BUCKET}/greetings.jar .
# Update and install/configure dependencies
apt-get update
apt-get -y --force-yes install openjdk-8-jdk
update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
# Start the application
java -jar greetings.jar
白小白 :
注意,程式碼中一共有3處的${PROJECTID}和${BUCKET}變數要替換成實際的值,${PROJECTID}顯然在本例中就是greetings,${BUCKET}就是剛剛上傳的那個你設定的個性化的bucket名稱
配置計算引擎
1.執行以下命令來建立Compute例項,使用instance-startup.sh指令碼和在前面步驟中使用的bucket名。
gcloud compute instances create greetings-instance \
--image-family debian-9 --image-project debian-cloud \
--machine-type g1-small --scopes "userinfo-email,cloud-platform" \
--metadata-from-file startup-script=instance-startup.sh \
--metadata BUCKET=greetings --zone us-east1-b --tags http-server
2.例項將被初始化並立即啟動。這可能需要幾分鐘。
3.在啟動過程中隔一段時間執行以下命令以便檢視例項日誌。如果一切順利,一旦這個過程完成,您應該會看到一條“Finished running startup scripts”的訊息。
> gcloud compute instances get-serial-port-output greetings-instance --zone us-east1-b
白小白 :
其實,這並不是一個必要步驟,如果實際運行了上面這條命令,產生的日誌內容會佔據N屏Console,建議沒有任何問題的情況下,不要執行這條命令,此外,我在測試時並沒有Finished…這句提示,代之以Created [https://www.googleapis.co…這樣的提示,以及一個顯示例項基本資訊的列表,與第5步中用gcloud compute instances list得到的列表相同
4.執行以下命令在埠8080啟用HTTP流量。
gcloud compute firewall-rules create default-allow-http-8080 \
--allow tcp:8080 --source-ranges 0.0.0.0/0 \
--target-tags http-server --description "Allow port 8080 access to http-server"
5.使用以下命令獲取Compute例項的外部IP:
gcloud compute instances list
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
greetings-instance us-east1-b g1-small 10.142.0.3 35.231.160.118 RUNNING
現在應該能夠使用EXTERNAL_IP訪問應用.
> curl 35.231.160.118:8080/greeting/World
Hello, World
十一、優點和缺點
寫作本文時,Micronaut還處於開發的早期階段,還有許多工作要做。然而,在當前的里程碑版本中,已經有大量的功能可用。
除了本文討論的特性外,Micronaut還支援以下內容:
● 安全性(使用JWT、sessions或basic auth)
● 管理端點
● 使用Hibernate、JPA和GORM 自動配置資料訪問許可權
● 通過@Scheduled支援批處理作業。
● 配置共享
● 其他
使用Micronaut進行開發的權威參考是http://docs.micronaut.io.
數量不多但不斷增加的漸進教程可在http://guides.micronaut.io找到。此地址還包括Micronaut支援的所有三種語言的指南:Java、Groovy和Kotlin。
Gitter上的Micronaut社群頻道(https://gitter.im/micronautfw/)是個好地方,在這裡可以與已經在用框架構建應用程式的開發者交流心得,以及與Micronaut的核心開發團隊互動。
時間將證明Micronaut將對微服務開發和整個行業產生什麼影響,但似乎很明顯,該框架已經在未來如何構建應用程式方面做出了重大貢獻。
雲原生應用的開發已經被廣泛接受,Micronaut是基於這方面的考量而構建的全新工具。就像推動其建立的體系結構一樣,Micronaut的靈活性和模組化將允許開發人員建立甚至其設計者都無法預見的系統。
JVM上的開發前景是光明的,即使有少許暗淡,Micronaut也肯定會發揮重要作用。一個重要的時代即將來臨!
原文釋出時間為:2018-10-9
本文作者:Zachary Klein
本文來自雲棲社群合作伙伴“ ofollow,noindex">EAWorld ”,瞭解相關資訊可以關注“ EAWorld ”。