您好,登錄后才能下訂單哦!
本篇內容主要講解“如何使用Quarkus/GraalVM將JGroups編譯成可執行文件”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何使用Quarkus/GraalVM將JGroups編譯成可執行文件”吧!
Quarkus 是一個將 Java 代碼編譯為本機代碼(使用GraalVM)并刪除運行時不需要的代碼的框架。
Quarkus 在構建階段分析代碼,并刪除在運行時未使用的代碼,以便擁有一個可以快速啟動的小型可執行文件。不過這意味著無法在運行時使用反射,因為在構建時刪除了所有未使用的類。 但是,可以在構建時使用反射。
影響 JGroups 的其他限制是線程和套接字的創建。 兩者都無法在構建時完成,但必須在運行時完成。
那么為Quarkus提供JGroups擴展的重點是什么呢?
雖然JGroups應用程序可以直接編譯為本機代碼(使用GraalVM的本機映像),但它很麻煩,并且必須重新構建應用程序以適應本機編譯的限制。
相反,JGroups 擴展提供了一個可以注入應用程序的JChannel。 已根據配置文件創建通道,并通過擴展連接(=加入群集)。 擴展負責在正確的時間(構建或運行時)執行反射,套接字創建和線程啟動,用戶無需擔心這一點。
接下來讓我們看一個具體的例子。
POM 引入擴展 groupId=org.jgroups.quarkus.extension 和 artifactId=quarkus-jgroups. 這樣就可以提供一個可注入的 JChannel。
主類是 ChatResource,代碼如下:
@ApplicationScoped @Path("/chat") public class ChatResource extends ReceiverAdapter implements Publisher<String> { protected final Set<Subscriber<? super String>> subscribers=new HashSet<>(); @Inject JChannel channel; protected void init(@Observes StartupEvent evt) throws Exception { channel.setReceiver(this); System.out.printf("-- view: %s\n", channel.getView()); } protected void destroy(@Observes ShutdownEvent evt) { Util.close(channel); subscribers.forEach(Subscriber::onComplete); subscribers.clear(); } @GET @Produces(MediaType.TEXT_PLAIN) @Path("/send/{msg}") public String sendMessage(@PathParam("msg") String msg) throws Exception { channel.send(null, Objects.requireNonNull(msg).getBytes()); return String.format("message \"%s\" was sent on channel \n", msg); } @GET @Produces(MediaType.SERVER_SENT_EVENTS) @Path("/subscribe") public Publisher<String> greeting() { return this; } public void receive(Message msg) { onNext(msg); } public void receive(MessageBatch batch) { for(Message msg: batch) onNext(msg); } public void viewAccepted(View view) { System.out.printf("-- new view: %s\n", view); } public void subscribe(Subscriber<? super String> s) { if(s != null) subscribers.add(s); } protected void onNext(Message msg) { String s=new String(msg.getRawBuffer(), msg.getOffset(), msg.getLength()); System.out.printf("-- from %s: %s\n", msg.src(), s); subscribers.forEach(sub -> sub.onNext(s)); } }
它有一個由Arc注入的JChannel通道(Quarkus中使用的依賴機制)。 該通道在注入時已經完全創建并連接。
receive(Message) 和 receive(MessageBatch) 方法接收由其自身或集群中的其他成員發送的消息。 它反過來通過Publisher接口發布它們。 因此,所有訂戶都將收到群集中發送的所有消息。
當收到格式為http://localhost:8080/chat/send/mymessage 的 URL 時,將調用 sendMessage() 方法。 它接受字符串參數(“mymessage”)并使用注入的通道將其發送給集群的所有成員。
URL http://localhost:8080/chat/subscribe (或者在瀏覽器中的 http://localhost:8080/streaming.html) 可用來訂閱消息。
接下來我們運行兩個實例的集群,打開兩個命令行窗口,并輸入如下的命令:
Shell1: [belasmac] /Users/bela/quarkus-jgroups-chat$ mvn compile quarkus:dev ... [INFO] --- quarkus-maven-plugin:0.18.0:dev (default-cli) @ quarkus-jgroups-chat --- 2019-07-03 14:12:05,025 DEBUG [org.jgr.qua.ext.JChannelTemplate] (main) creating channel based on config config=chat-tcp.xml, bind_addr=, initial_hosts=, cluster=quarkus-jgroups-chat ------------------------------------------------------------------- GMS: address=belasmac-19612, cluster=quarkus-jgroups-chat, physical address=127.0.0.1:7800 ------------------------------------------------------------------- -- view: [belasmac-19612|0] (1) [belasmac-19612] Shell2: [belasmac] /Users/bela/quarkus-jgroups-chat$ mvn compile quarkus:dev -Dquarkus.http.port=8081 ... [INFO] --- quarkus-maven-plugin:0.18.0:dev (default-cli) @ quarkus-jgroups-chat --- 2019-07-03 14:15:02,463 DEBUG [org.jgr.qua.ext.JChannelTemplate] (main) creating channel based on config config=chat-tcp.xml, bind_addr=, initial_hosts=, cluster=quarkus-jgroups-chat ------------------------------------------------------------------- GMS: address=belasmac-25898, cluster=quarkus-jgroups-chat, physical address=127.0.0.1:7801 ------------------------------------------------------------------- -- view: [belasmac-19612|1] (2) [belasmac-19612, belasmac-25898]
這里我們需要一個系統屬性設置 quarkus.http.port=8081 ,否則會產生端口沖突,因為默認的 8080 端口已經被第一個應用占用。
輸出信息顯示集群共有兩個成員。
我們可以通過調用 curl http://localhost:8080/chat/send/hello%20world 和 curl http://localhost:8081/chat/send/message2 來發送消息。
兩個命令行窗口都顯示接收到同樣的消息:
-- view: [belasmac-19612|1] (2) [belasmac-19612, belasmac-25898] -- from belasmac-19612: hello world -- from belasmac-25898: message2
當然我們也可以使用瀏覽器來發送 HTTP GET 請求。
當在瀏覽器中訂閱消息時 (http://localhost:8081/streaming.html),會有如下效果:
注意這些頻道都是綁定到本機 loopback (127.0.0.1) 地址上。可以通過 application.properties 配置中的 bind_addr 和 initial_hosts 來進行修改。
quarkus.channel.config=chat-tcp.xml quarkus.channel.cluster=quarkus-jgroups-chat # quarkus.channel.bind_addr=192.168.1.105 # quarkus.channel.initial_hosts=192.168.1.105[7800]
另外我們也可以通過系統屬性來進行設置,例如:
[belasmac] /Users/bela/quarkus-jgroups-chat$ mvn compile quarkus:dev -Dbind_addr=192.168.1.105 -Dinitial_hosts=192.168.1.105[7800],192.168.1.105[7801] ... [INFO] --- quarkus-maven-plugin:0.18.0:dev (default-cli) @ quarkus-jgroups-chat --- 2019-07-03 14:38:28,258 DEBUG [org.jgr.qua.ext.JChannelTemplate] (main) creating channel based on config config=chat-tcp.xml, bind_addr=, initial_hosts=, cluster=quarkus-jgroups-chat ------------------------------------------------------------------- GMS: address=belasmac-10738, cluster=quarkus-jgroups-chat, physical address=192.168.1.105:7800 ------------------------------------------------------------------- -- view: [belasmac-10738|0] (1) [belasmac-10738]
要將應用編譯成可執行程序,可以使用 mvn package -Pnative 命令:
[belasmac] /Users/bela/quarkus-jgroups-chat$ mvn package -Pnative [INFO] Building jar: /Users/bela/quarkus-jgroups-chat/target/quarkus-jgroups-chat-1.0.0-SNAPSHOT.jar [INFO] [INFO] --- quarkus-maven-plugin:0.18.0:build (default) @ quarkus-jgroups-chat --- [INFO] [io.quarkus.deployment.QuarkusAugmentor] Beginning quarkus augmentation [INFO] [org.jboss.threads] JBoss Threads version 3.0.0.Beta4 [INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 1343ms [INFO] [io.quarkus.creator.phase.runnerjar.RunnerJarPhase] Building jar: /Users/bela/quarkus-jgroups-chat/target/quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner.jar [INFO] [INFO] --- quarkus-maven-plugin:0.18.0:native-image (default) @ quarkus-jgroups-chat --- [INFO] [io.quarkus.creator.phase.nativeimage.NativeImagePhase] Running Quarkus native-image plugin on OpenJDK 64-Bit Server VM [INFO] [io.quarkus.creator.phase.nativeimage.NativeImagePhase] /Users/bela/graalvm/Contents/Home/bin/native-image -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager --initialize-at-build-time= -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime -jar quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner.jar -J-Djava.util.concurrent.ForkJoinPool.common.parallelism=1 -H:FallbackThreshold=0 -H:+ReportUnsupportedElementsAtRuntime -H:+ReportExceptionStackTraces -H:+PrintAnalysisCallTree -H:-AddAllCharsets -H:EnableURLProtocols=http -H:-SpawnIsolates -H:+JNI --no-server -H:-UseServiceLoaderFeature -H:+StackTrace [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] classlist: 6,857.25 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] (cap): 4,290.72 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] setup: 6,430.30 ms 14:43:05,540 INFO [org.jbo.threads] JBoss Threads version 3.0.0.Beta4 14:43:06,468 INFO [org.xnio] XNIO version 3.7.2.Final 14:43:06,528 INFO [org.xni.nio] XNIO NIO Implementation Version 3.7.2.Final [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] (typeflow): 17,331.26 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] (objects): 24,511.12 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] (features): 1,194.16 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] analysis: 44,204.65 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] (clinit): 579.00 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] universe: 1,715.40 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] (parse): 3,315.80 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] (inline): 4,563.11 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] (compile): 24,906.58 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] compile: 34,907.28 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] image: 4,557.78 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] write: 2,531.16 ms [quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner:93574] [total]: 109,858.54 ms [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 01:58 min [INFO] Finished at: 2019-07-03T14:44:40+02:00
這使用的是 GraalVM 的本地應用映像來生成一個本地可執行程序。生成完成后將在 ./target 目錄產生一個可執行文件:
其大小約為 27MB ,在 MacOS 的可執行程序如下:
[belasmac] /Users/bela/quarkus-jgroups-chat/target$ ls -lh quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner -rwxr-xr-x 1 bela staff 27M Jul 3 14:44 quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner [belasmac] /Users/bela/quarkus-jgroups-chat/target$ file quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner: Mach-O 64-bit executable x86_64
接下來可以運行這個程序:
[belasmac] /Users/bela/quarkus-jgroups-chat/target$ ./quarkus-jgroups-chat-1.0.0-SNAPSHOT-runner ------------------------------------------------------------------- GMS: address=belasmac-55106, cluster=quarkus-jgroups-chat, physical address=127.0.0.1:7800 ------------------------------------------------------------------- -- view: [belasmac-55106|0] (1) [belasmac-55106]
當您自己運行時,您會注意到第二個及后續成員的快速啟動時間。 為什么不是第一個成員? 第一個成員必須等待GMS.join_timeout millis(在chat-tcp.xml中定義)以查看它是否發現任何其他成員,因此它總是會遇到此超時。
要改動 bind_addr 和 initial_hosts 的話,application.properties 必須在編譯成本機代碼之前進行修改。
quarkus-jgroups擴展依賴于JGroups-4.1.2-SNAPSHOT,除非已將快照存儲庫添加到POM(或settings.xml),否則它可能無法找到。 或者通過如下命令在您的本地maven倉庫中生成并安裝此工件:
git clone https://github.com/belaban/JGroups.git; cd JGroups; mvn install
當前的版本只支持 TCP 通訊,UDP 需要在 GraalVM 支持 MulticastSockets 后才可以使用。
出于某些不明原因,必須在 POM 中啟用 enableJni ,否則編譯成本機代碼時會失敗。
<enableJni>true</enableJni>
希望我能快速理解這個原因并解決問題。
這是快速將 JGroups 移植到本機代碼的方法。 有關反饋和問題,請使用JGroups郵件列表。
接下來的計劃:
通過擴展提供更多 JGroups 類的支持,例如 RpcDispatcher (用以執行遠程方法調用)
提供本地可執行程序的 Docker 映像
支持 UDP
降低可執行文件的體積
到此,相信大家對“如何使用Quarkus/GraalVM將JGroups編譯成可執行文件”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。