Netty Java快速指南
使用Okta的身份管理平臺輕松部署您的應用程序 使用Okta的API在幾分鐘之內即可對任何應用程序中的用戶進行身份驗證,管理和保護。 今天嘗試Okta。
Netty是一個無阻塞的輸入/輸出(NIO)框架,它使開發低級網絡服務器和客戶端變得相對簡單。 Netty為需要在套接字級別上工作的開發人員提供了令人難以置信的強大功能,例如,在開發客戶端和服務器之間的自定義通信協議時。 它支持SSL / TLS,具有阻塞和非阻塞統一API,以及靈活的線程模型。 它又快又高效。
Netty的異步,非阻塞I / O模型是為高度可擴展的體系結構設計的,與類似的阻塞模型相比,它可能允許更高的吞吐量。 基本上,非阻塞服務器在單個線程上異步運行所有請求(沒有函數應“阻塞”事件循環)。 這與阻塞服務器模型形成對比,后者通常在單獨的線程上運行每個請求。 通過不必在負載增加時切換線程或創建新線程,非阻塞模型可以減少開銷,并隨著流量增加而更快地進行擴展。
但是,所有這些功能都是以復雜性為代價的。 非阻塞代碼通常更難閱讀,測試和維護,盡管隨著異步范例的成熟,非阻塞代碼已大大改善。 由于Netty是在套接字級別工作的,因此還需要更深入地了解諸如線程循環,字節緩沖區和內存管理之類的細節。
Netty.io團隊做了出色的工作,使Netty的所有功能易于使用,但是它仍然比高級庫(例如Spring Boot WebFlux)更加復雜。 那么為什么要使用它呢?
Netty旨在使自定義網絡協議的實現相對容易。 HTTP很不錯,但是它是一種通用協議,基本上適合大多數情況。 但是,如果您始終在服務器和客戶端之間來回傳遞自定義的結構化數據(大型文件,流媒體,實時游戲數據等),則可以做得更好。 Netty允許您編寫適合自己特定需求的網絡協議,針對特定情況優化流量,而不會產生HTTP或FTP之類的不必要開銷。
但是,即使您不打算編寫自己的自定義TCP協議,也可以使用Netty的功能。 Spring WebFlux是Spring對非阻塞和反應式編程的解答。 它是傳統(阻塞)Spring MVC體系結構的替代方案。 默認情況下,Spring Boot WebFlux Starter在嵌入式Netty服務器上運行。 在這種配置中,您可以將WebFlux視為基于Netty的NIO套接字優勢構建的反應性,非阻塞HTTP應用程序層。
在本教程中,您將在Netty中創建一個基本的“ Hello world”應用程序。 接下來,您將在Spring Boot WebFlux中創建相同的“ Hello world”應用程序。 最后,您將使用Okta作為OAuth 2.0提供程序將OAuth 2.0登錄名添加到應用程序中。
安裝項目依賴項
在開始之前,該項目需要安裝一些必需的工具。
Java 11 :該項目使用Java11 。您可以按照OpenJDK網站上的說明或使用SDKMAN來安裝OpenJDK。
HTTPie :這是一個簡單的命令行實用程序,用于發出將用于測試REST應用程序的HTTP請求。 Okta開發人員也喜歡它。 按照其網站上的說明進行安裝 。
Okta開發人員帳戶 :您將Okta用作OAuth / OIDC提供程序,以向應用程序添加OAuth2登錄身份驗證。 如果尚未注冊免費的Okta開發者帳戶 ,請注冊。
您還應該繼續克隆該博客的GitHub存儲庫 。
<
git clone https://github.com/oktadeveloper/okta-netty-webflux-example.git該項目包含三個子目錄,分別對應于本教程的三個部分:
使用Netty構建HTTP服務器
HTTP服務器是HTTP協議(OSI第7層)的應用程序層實現,因此在Internet堆棧中相對較高。 如果您正在開發REST API, 那么您將在為您提供此實現的API的基礎上進行開發 。 相比之下,Netty并不一定要構建通信,提供會話管理甚至提供像TLS這樣的安全性。 如果您要構建超低級網絡應用程序,那就太好了; 但是,如果您正在構建REST服務,則可能不是最佳選擇。
幸運的是,Netty API還提供了一些幫助程序類和函數,這些類和函數使我們能夠輕松集成更高級別的協議(例如HTTP)。 在本部分的教程中,您將使用它們來構建一個簡單的HTTP服務器。
在您喜歡的IDE或文本編輯器中打開netty-hello-world項目。
首先,查看src/main/java/com/okta/netty/AppServer.java文件。 此類是應用程序的入口點,用于設置Netty服務器。
package com.okta.netty; ...public class AppServer { private static final int HTTP_PORT = 8080; public void run() throws Exception { // Create the multithreaded event loops for the serverEventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { // A helper class that simplifies server configuration ServerBootstrap httpBootstrap = new ServerBootstrap(); // Configure the serverhttpBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ServerInitializer()) // <-- Our handler created here .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // Bind and start to accept incoming connections. ChannelFuture httpChannel = httpBootstrap.bind(HTTP_PORT).sync(); // Wait until server socket is closedhttpChannel.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new AppServer().run(); } }最重要的一行是.childHandler(new ServerInitializer()) ,它創建ServerInitializer和ServerHandler并掛接到Netty服務器。
接下來查看src/main/java/com/okta/netty/ServerInitializer.java 。 此類配置Netty通道,該通道將處理我們的請求并將其連接到ServerHandler 。
package com.okta.netty; ...public class ServerInitializer extends ChannelInitializer<Channel> { @Override protected void initChannel(Channel ch) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(Integer.MAX_VALUE)); pipeline.addLast(new ServerHandler()); } }最后,有src/main/java/com/okta/netty/ServerHandler.java 。 這是映射實際請求并生成響應的地方。
package com.okta.netty; ...public class ServerHandler extends SimpleChannelInboundHandler{ @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) { ByteBuf content = Unpooled.copiedBuffer("Hello World!", CharsetUtil.UTF_8); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html"); response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); ctx.write(response); ctx.flush(); } }在此類中,請注意,您必須將響應字符串轉換為字節緩沖區。 實際上,您會生成一個HTTP響應并直接設置一些標頭。 這是Internet的應用層(OSI第7層)。 調用ctx.write(response) ,它將響應作為字節流通過TCP發送。 Netty團隊在保持低級傳輸協議的同時,為隱藏大量的復雜性做了出色的工作。
測試您的Netty應用
要測試此Netty應用程序,請從項目根目錄netty-hello-world運行:
./gradlew run一旦應用程序完成了加載,就從另一個外殼程序中,使用HTTPie執行GET請求:
$ http :8080HTTP/1.1 200 OK content-length: 12 content-type: text/htmlHello World!那是Netty內置的簡單HTTP服務器。 接下來,您將爬上梯級的抽象階梯,并使用Spring Boot和WebFlux簡化操作。
在Netty上向WebFlux打個招呼
如前所述,WebFlux是Spring MVC的無阻塞替代方案。 它通過事件驅動,異步和非阻塞方法來處理請求,從而支持反應式編程。 它還提供了許多功能性API。 Reactor是與Spring緊密合作開發的反應性服務器端Java庫,它提供了WebFlux的反應流方面。 但是,您也可以使用其他反應式流庫。
回想一下,默認情況下,Spring Boot WebFlux啟動程序在Netty服務器上運行。 在下一個示例中,您會注意到Spring Boot隱藏了多少復雜性。
Spring Boot WebFlux項目位于GitHub存儲庫的webflux-hello-world子目錄中。 非常簡單。
看一下ReactiveApplication類。 這是準系統的標準Spring Boot應用程序類。 它只是利用public static void main()方法和@SpringBootApplication來啟動整個Spring Boot應用程序框架。
src/main/java/com/okta/webflux/app/ReactiveApplication.java
package com.okta.webflux.app; ... @SpringBootApplication public class ReactiveApplication { public static void main(String[] args) { SpringApplication.run(ReactiveApplication.class, args); } }ReactiveRouter是一個簡單的路由器類,它將HTML端點與處理程序方法鏈接在一起。 您可以看到它使用依賴注入將ReactiveHandler傳遞給路由器bean,該bean為/路由定義了一個端點。
src/main/java/com/okta/webflux/app/ReactiveRouter.java
package com.okta.webflux.app; ...@Configuration public class ReactiveRouter { @Bean public RouterFunctionroute(ReactiveHandler handler) { return RouterFunctions .route(RequestPredicates .GET("/") .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::hello); } }ReactiveHandler同樣簡單。 它定義了一個返回純文本的處理函數。 Mono<ServerResponse>返回類型是一種特殊類型,用于返回一個元素的流。 查看有關了解反應類型的Spring文檔,以了解有關返回類型的更多信息。 如果您習慣使用Spring MVC,這可能是WebFlux較為陌生的方面之一。
package com.okta.webflux.app; ...@Component public class ReactiveHandler { public Mono<ServerResponse> hello() { return ServerResponse .ok() .contentType(MediaType.TEXT_PLAIN) .body(BodyInserters.fromObject("Hello world!")); } }打開一個外殼,然后導航到項目的webflux-hello-world子目錄。
使用以下項目運行項目: ./gradlew bootRun 。
打開另一個外殼以使用http :8080測試端點。
HTTP/1.1 200 OK Content-Length: 12 Content-Type: text/plainHello world!看到使用Spring Boot比Netty簡單多少?
創建一個OpenID Connect(OIDC)應用程序
接下來,您將使用OAuth 2.0登錄名來保護應用程序。 這聽起來可能很復雜,但是不用擔心。 Spring和Okta密謀使其變得非常簡單!
Okta是SaaS(軟件即服務)身份驗證和授權提供者。 我們為開發人員提供免費帳戶,因此您可以輕松開發OIDC應用程序。 前往developer.okta.com并注冊一個帳戶。
驗證電子郵件后,登錄并執行以下步驟(如果這是您第一次登錄,則可能需要單擊黃色的“ 管理”按鈕才能進入開發人員儀表板):
- 轉到應用程序 > 添加應用程序 。
- 選擇應用程序類型Web ,然后單擊下一步 。
- 為應用命名。 我將其命名為“ WebFlux OAuth”。
- 在登錄重定向URI下, 將值更改為http://localhost:8080/login/oauth2/code/okta 。 其余的默認值將起作用。
- 單擊完成 。
注意底部的客戶端ID和客戶端密鑰 。 稍后您將需要它們。
使用OAuth 2.0保護您的應用安全
在Okta上創建OIDC應用程序后,需要在項目中進行一些更新。 如果您想跳過本教程的完成項目,可以在webflux-oauth2login子目錄中找到,但是我將向您展示如何修改webflux-hello-world以添加login 。
首先,將Okta Spring Boot Starter添加到Gradle構建文件中。 我們一直在努力使這一過程盡可能容易,并且Okta Spring Boot Starter簡化了OAuth配置。 看看入門的GitHub項目,了解更多信息。
將以下依賴項添加到build.gradle文件的依賴項塊中:
dependencies { ...implementation 'com.okta.spring:okta-spring-boot-starter:1.3.0' }接下來,將以下屬性添加到src/main/resources/application.properties文件。 您需要用自己的Okta域和客戶端ID替換括號中的值。
您可以通過打開Okta開發人員儀表板并轉到API > 授權服務器,然后在默認服務器的表中查找來找到您的Issuer URI。 客戶端ID和機密來自您剛才創建的OIDC應用程序。
okta.oauth2.issuer={yourIssuerUri} okta.oauth2.client-id={yourClientId} okta.oauth2.client-secret={yourClientSecret}現在運行應用程序: ./gradlew bootRun 。
注銷您的Okta開發人員帳戶或使用隱身窗口并瀏覽至(在瀏覽器中): http:// localhost:8080 。
系統將指導您使用Okta帳戶登錄。
登錄后,您將被重定向回該應用程序。 是的-成功!
了解有關Netty,Spring Boot和OAuth 2.0的更多信息
在本教程中,您使用Netty創建了一個基本的“ Hello world”應用程序。 您已經看到Netty是如何用于創建TCP和UDP網絡協議的超強大框架。 您已經了解了它如何支持非阻塞IO,以及Spring WebFlux如何在Netty之上構建以提供反應性,非阻塞HTTP應用程序框架。 然后,您在WebFlux中構建了一個“ Hello world”應用程序,此后,您使用Okta作為OAuth 2.0 / OIDC提供程序來向該應用程序添加OAuth 2.0登錄名。
您可以在oktadeveloper / okta-netty-webflux-example上的GitHub上查看本教程的完整代碼。
除了WebFlux,在Netty之上還構建了一些強大的網絡框架。 Apple最近開放了ServiceTalk的源代碼, ServiceTalk是一個支持HTTP,HTTP / 2和gRPC的反應性微服務客戶端/服務器庫。 還有一個Armeria ,一個基于Java 8,Netty,Thrift和gRPC構建的開源異步HTTP / 2 RPC / REST客戶端/服務器庫。 其主要目標是幫助工程師構建高性能的異步微服務。
如果您想了解有關Spring Boot,Spring WebFlux和OAuth 2.0的更多信息,請查看以下有用的教程:
- Spring Boot,OAuth 2.0和Okta入門
- 使用Spring WebFlux構建反應性API
- OAuth到底是什么?
- Spring Security 5.0和OIDC入門
- 身份,聲明和令牌– OpenID Connect入門,第1部分,共3部分
- 使用Spring Boot和GraphQL構建安全的API
如果您對此帖子有任何疑問,請在下面添加評論。 有關更多精彩內容, 請在Twitter上關注@oktadev或訂閱我們的YouTube頻道 !
使用Okta的身份管理平臺輕松部署您的應用程序 使用Okta的API在幾分鐘之內即可對任何應用程序中的用戶進行身份驗證,管理和保護。 今天嘗試Okta。
翻譯自: https://www.javacodegeeks.com/2020/01/a-quick-guide-to-java-on-netty.html
總結
以上是生活随笔為你收集整理的Netty Java快速指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: input发送a.jax_JAX-RS
- 下一篇: (gd linux)