您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何使用Java中的Serverless”,在日常操作中,相信很多人在如何使用Java中的Serverless問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何使用Java中的Serverless”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
2019 年,O'Reilly 對 1500 名 IT 專業人員的調查中,有 40% 的受訪者在采用 Serverless 架構的組織中工作。2020 年 DataDog 調查顯示,現在有超過 50% 的 AWS 用戶正在使用 Serverless 架構的 AWS Lambda。
Serverless 正在成為主流,于是就誕生了下面這幅圖,從單體應用的管理到微服務應用的管理再到函數的管理。
Serverless 到目前為止還沒有一個精準定義。Martin Fowler 在個人博客上有一篇《Serverless Architectures》文章,其對 Serverless 的的定義分成了 BaaS 或 FaaS。
Baas 是全稱是 Backend-as-a-Service,后端即服務,FaaS 的全稱是 Function-as-a-Service,函數即服務。
今天我們來聊聊 FaaS。這是維基百科對 FaaS 的定義:
函數即服務(FaaS)是一類云計算服務,它提供了一個平臺,使客戶可以開發,運行和管理應用程序功能,而無需構建和維護通常與開發和啟動應用程序相關的基礎架構。遵循此模型構建應用程序是實現 Serverless 架構的一種方法,通常在構建微服務應用程序時使用。
對于 Python、JavaScript 這種天生支持 Lambda 的開發語言,和 FaaS 簡直是完美結合。Serverless Framework 的調研報告也很好地說明了這一點。NodeJS、Python 是 FaaS 使用率前二的語言。
我們知道,因為 JVM 占用的內存比較大,所以 Java 應用的啟動會有點慢,不太適合 FaaS 這個場景,這也是 Java 在使用率上偏低的原因。
另外,對 Java 開發者來說 Spring Boot/Cloud 已經成為了事實標準,依賴注入是 Spring Framework 的核心,Spring Boot/Cloud 這個事實標準應對 FaaS 這個場景,會碰撞出怎么樣的火花呢?這就是今天我們要聊的 Spring Cloud Function。
在對 Spring Cloud Function 介紹之前,我們先來看 Java 里的核心函數定義。
JDK 1.8 推出了新特性 Lambda 表達式,java.util.function 包下面提供了很多的函數。這 3 個函數尤為重要:
@FunctionalInterface public interface Function<T, R> { R apply(T t); }
比如通過 Stream API 里的 map 方法可以通過 Function 把字符串從小寫變成大寫:
Stream.of("a", "b", "c").map(String::toUpperCase);
這里的 map 方法需要一個 Function 參數:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
@FunctionalInterface public interface Consumer<T> { void accept(T t); }
比如通過 Stream API 里的 forEach 方法遍歷每個元素,做對應的業務邏輯處理:
RestTemplate restTemplate = new RestTemplate(); Stream.of("200", "201", "202").forEach(code -> { ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://httpbin.org/status/" + code, String.class); System.out.println(responseEntity.getStatusCode()); });
@FunctionalInterface public interface Supplier<T> { T get(); }
比如自定義 Supplier 可以返回隨機數:
Random random = new Random(); Supplier supplier100 = () -> random.nextInt(100); Supplier supplier1000 = () -> random.nextInt(1000); System.out.println(supplier100.get()); System.out.println(supplier1000.get());
Java Function 的編程模型非常簡單,本質上就是這 3 個核心函數:
Supplier<O>
Function<I, O>
Consumer<I>
Spring Cloud Function 是 Spring 生態跟 Serverless(FaaS) 相關的一個項目。它出現的目的是增強 Java Function,主要體現在這幾點:
統一云廠商的 FaaS 編程模型: Spring Cloud Function 的口號是 "Write Once, Run Anywhere"。我們寫的 Spring Cloud Function 代碼可以運行在本地、各個云廠商(AWS Lambda, GCP Cloud Functions, Azure Functions)。
自動類型轉換: 理解過 Spring MVC 或者 Spring Cloud Stream 的同學肯定對 HttpMessageConverter 或者 MessageConverter 模型,這個轉換器的作用是將 HTTP BODY(或者 Message Payload)、HTTP Query Parameter、HTTP HEADER(或者 Message Header)自動轉換成對應的 POJO。有了這個特性后,我們就無需關注函數的入參和返回值,用 String 參數就可以獲取原始的入參信息,用 User 這個 POJO 參數就可以將原始的入參參數自動轉換成 User 對象。
函數組合: 可以讓多個函數之間進行組合操作。
函數管理: 新增 FunctionCatalog、FunctionRegistry 接口用于 Function 的管理。管理 ApplicationContext 內的 Function,動態注冊 Function 等操作。
Reactive 支持: Spring Cloud Function 新增比如 FluxFunction、FluxSupplier、FunctionConsumer 這種 Reactive 函數。
自動跟 Spring 生態內部原有的組件進行深度集成:
Spring Web/Spring WebFlux: 一次 HTTP 請求是一次函數調用。
Spring Cloud Task: 一次任務執行是一次函數調用。
Spring Cloud Stream: 一次消息消費/生產/轉換是一次函數調用。
這里再多介紹統一云廠商的 FaaS 編程模型,讓大家對 Spring Cloud Function 更有體感。
AWS Lambda 是第一個是提供 FaaS 服務的云廠商,RequestStreamHandler 是 AWS 提供的針對 Java 開發者的接口,需要實現這個接口:
public class HandlerStream implements RequestStreamHandler { @Override public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { ...
Azure Functions 針對 Java 開發者提供了 @HttpTrigger 注解:
public class Function { public String echo(@HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) String req, ExecutionContext context) { ... } }
從這兩段代碼可以看出,不同的云廠商要編寫不同的代碼。如果要變換云廠商,這個過程會很痛苦。
另外,無論是 AWS、Azure 或者 GCP 提供的接口或注解,他們沒有任何 Spring 上下文相關的初始化邏輯。如果我們是一個 Spring Boot/Cloud 應用遷移到 FaaS 平臺,需要添加 Spring 上下文初始化邏輯等改動量。
Spring Cloud Function 的出現就是為了解決這些問題。
Spring Cloud Function & Spring Web:
@SpringBootApplication public class SpringCloudFunctionWebApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudFunctionWebApplication.class, args); } @Bean public Function<String, String> upperCase() { return s -> s.toUpperCase(); } @Bean public Function<User, String> user() { return user -> user.toString(); } }
訪問對應的 Endpoint:
$ curl -XPOST -H "Content-Type: text/plain" localhost:8080/upperCase -d hello HELLO $ curl -XPOST -H "Content-Type: text/plain" localhost:8080/user -d '{"name":"hello SCF"}' User{name\u003d\u0027hello SCF\u0027}
Spring Cloud Function & Spring Cloud Stream:
@SpringBootApplication public class SpringCloudFunctionStreamApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudFunctionStreamApplication.class, args); } @Bean public Function<String, String> uppercase() { return x -> x.toUpperCase(); } @Bean public Function<String, String> prefix() { return x -> "prefix-" + x; } }
加上 function 相關的配置(針對 input-topic 上的每個消息,payload 轉換大寫后再加上 prefix- 前綴,再寫到 output-topic 上):
spring.cloud.stream.bindings.input.destination=input-topic spring.cloud.stream.bindings.input.group=scf-group spring.cloud.stream.bindings.output.destination=output-topic spring.cloud.stream.function.definition=uppercase|prefix
Spring Cloud Function & Spring Cloud Task:
@SpringBootApplication public class SpringCloudFunctionTaskApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudFunctionTaskApplication.class, args); } @Bean public Supplier<List<String>> supplier() { return () -> Arrays.asList("200", "201", "202"); } @Bean public Function<List<String>, List<String>> function() { return (list) -> list.stream().map( item -> "prefix-" + item).collect(Collectors.toList()); } @Bean public Consumer<List<String>> consumer() { return (list) -> { list.stream().forEach(System.out::println); }; } }
加上 function 相關的配置(Supplier 模擬任務的輸入源,Function 模擬對任務輸入源的處理,Consumer 模擬處理對 Function 處理輸入源后的數據):
spring.cloud.function.task.function=function spring.cloud.function.task.supplier=supplier spring.cloud.function.task.consumer=consumer
到此,關于“如何使用Java中的Serverless”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。