在前面的講解中,我們已經提及了微服務的一些弊端,並介紹了Istio這樣的解決方案。那麼,對於我們開發人員來說,Istio究竟會帶來哪些變革呢?今天我們就來簡要探討一下!
Kubernetes,俗稱K8s,僅僅是因為L與s之間有8個字母所以叫的K8s,是一種用於管理和編排Docker叢集的工具。它被廣泛使用且備受推崇,因此在講解Istio技術時,我們選擇與Kubernetes進行整合開發。接下來,我們將重點關注如何在整合了Istio的專案中進行程式碼編寫和重構。儘管Kubernetes技術對於開發者來說關係不是特別密切,但我們會在以後的時間裡專門設立一個Kubernetes系列專欄,來詳細介紹該技術。
bookinfo是Istio提供的學習樣例,通過使用bookinfo,您可以更深入地理解Istio提供的路由、遙測等功能。下圖展示了bookinfo在未整合Istio之前的物理架構:
bookinfo是一個線上書店應用,由四個微服務組成,分別是Product page、Reviews、Details和Ratings。為了展示Istio的無侵入性,這四個微服務分別使用Python、Java、Ruby和Node進行開發。下面對每個服務進行詳細說明:
Product page:這是一個聚合服務,它通過聚合Reviews和Details的內容來展示產品頁面。
Details:這是圖書詳情服務,提供了書籍的詳細資訊。
Reviews:這是圖書評價服務,它有多個版本供選擇。Reviews還是一個聚合服務,它將Ratings的評分資訊與評價內容進行聚合。
Ratings:這是圖書預訂排名服務,提供了圖書的評分資訊。
下圖展示了bookinfo在嵌入了Istio後的物理架構:
為了簡化bookinfo應用的部署過程,可以使用批註入的方式來自動注入sidecar。這樣可以避免每次手動注入sidecar的繁瑣步驟。
批註入是一種將sidecar自動注入到Kubernetes部署中的方法。通過批註入,可以在應用部署的同時自動新增sidecar容器,而無需手動進行注入操作。
在部署bookinfo應用之前,需要確保已經安裝和設定了Istio。然後,可以按照以下步驟進行批註入部署bookinfo應用:
kubectl create ns test
kubectl label ns test istio-injection=enabled
kubectl get ns test --show-labels
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n test
這裡就不再贅述了,你可以在官方網站上詳細瞭解:https://istio.io/latest/zh/docs/examples/bookinfo/
當你部署完bookinfo 之後,開啟瀏覽器並存取網址,多次重新整理頁面,你會發現 bookinfo 應用使用了多個不同版本的 reviews,如下所示:
這裡我們將不再設定關於Istio的虛擬服務和路由規則。這些都可以通過編寫一個YAML格式的檔案,並在Kubernetes中執行一條命令來完成。你可以參考官方提供的範例來進行設定。設定完成後,Istio將能夠捕獲所有當前服務傳送的請求,並進行解析路由,從而實現灰度釋出、A/B測試、故障注入等邏輯。但是這不是我們文章的重點,我們只需要關注程式碼的編寫即可。剩下的運維工作將由相關人員負責
在開發之前,讓我們先來看一下官方GitHub上的bookinfo專案是如何進行呼叫的。官方倉庫的地址是:https://github.com/istio/istio/blob/master/samples/bookinfo/src/reviews/reviews-application/src/main/java/application/rest/LibertyRestEndpoint.java
我已經將地址定位到了我們關注的Java檔案。如果你是Python開發或者使用Node.js,你可以自行切換到相應的目錄。無論使用哪種語言,基本的邏輯都是相同的。
private final static Boolean ratings_enabled = Boolean.valueOf(System.getenv("ENABLE_RATINGS"));
private final static String star_color = System.getenv("STAR_COLOR") == null ? "black" : System.getenv("STAR_COLOR");
private final static String services_domain = System.getenv("SERVICES_DOMAIN") == null ? "" : ("." + System.getenv("SERVICES_DOMAIN"));
private final static String ratings_hostname = System.getenv("RATINGS_HOSTNAME") == null ? "ratings" : System.getenv("RATINGS_HOSTNAME");
private final static String ratings_port = System.getenv("RATINGS_SERVICE_PORT") == null ? "9080" : System.getenv("RATINGS_SERVICE_PORT");
private final static String ratings_service = String.format("http://%s%s:%s/ratings", ratings_hostname, services_domain, ratings_port);
private final static String pod_hostname = System.getenv("HOSTNAME");
private final static String clustername = System.getenv("CLUSTER_NAME");
//·······此處省略沒必要的程式碼
//呼叫邏輯
private JsonObject getRatings(String productId, HttpHeaders requestHeaders) {
ClientBuilder cb = ClientBuilder.newBuilder();
Integer timeout = star_color.equals("black") ? 10000 : 2500;
cb.property("com.ibm.ws.jaxrs.client.connection.timeout", timeout);
cb.property("com.ibm.ws.jaxrs.client.receive.timeout", timeout);
Client client = cb.build();
WebTarget ratingsTarget = client.target(ratings_service + "/" + productId);
Invocation.Builder builder = ratingsTarget.request(MediaType.APPLICATION_JSON);
//·······此處省略沒必要的程式碼
通過以上的程式碼,我們可以發現,使用Istio可以大大簡化微服務架構中的程式碼邏輯。通過使用服務名進行HTTP呼叫,Istio會自動處理請求的路由、負載均衡和流量控制等功能,從而減少了對其他元件的依賴,使程式碼更加清爽。在實際開發中,可以選擇使用OpenFeign或gRPC等技術來實現微服務之間的通訊。
OpenFeign是一個基於註解的宣告式Web Service使用者端,它可以簡化HTTP請求的編寫和呼叫。使用OpenFeign,你可以定義一個介面,並使用註解來描述介面的請求路徑、請求方法和引數等資訊。OpenFeign會根據這些註解自動生成HTTP請求的程式碼,使開發者可以更加方便地呼叫其他微服務。
gRPC是一個高效能、開源的遠端過程呼叫(RPC)框架,它使用Protocol Buffers作為介面定義語言(IDL)來定義服務介面和訊息格式。通過gRPC,你可以定義一個介面,並使用Protocol Buffers來描述介面的請求和響應訊息。gRPC會自動生成使用者端和伺服器端的程式碼,使開發者可以直接呼叫遠端服務而無需關心底層的網路通訊細節。
無論是選擇OpenFeign還是gRPC,都可以根據具體的需求和技術棧來決定。它們都提供了方便的工具和框架來簡化微服務之間的通訊,使開發者可以更加專注於業務邏輯的實現。
總的來說,Istio為開發人員帶來了許多變革。首先,它提供了批註入的方式來自動注入sidecar,簡化了應用部署的過程。其次,通過Istio,開發人員可以輕鬆地進行灰度釋出、A/B測試和故障注入等操作,而無需手動設定路由規則。此外,Istio還提供了服務發現、負載均衡和流量控制等功能,減少了對其他元件的依賴,使程式碼更加清爽。在程式碼開發方面,可以選擇使用OpenFeign或gRPC等技術來簡化微服務之間的通訊。總之,Istio的引入為微服務架構的開發人員提供了更便捷和高效的開發方式。