雲原生架構之SpringBoot+K8s service服務註冊發現方案(東西流量)

語言: CN / TW / HK

“我報名參加金石計劃1期挑戰——瓜分10萬獎池,這是我的第3篇文章,點選檢視活動詳情

一 方案概述

將spring cloud應用上K8s叢集,服務註冊直接使用K8s service,即為服務繫結service,服務發現使用K8s service(改方案負責均衡為服務端負載均衡)。

二 SpringBoot + K8s service服務註冊發現方案

2.1 方案簡介

使用K8s 原生service/endpoints/coredns/etcd組建實現服務註冊發現過程,服務註冊使用和服務發現均使用service,在K8s環境下,藉助K8s service能力實現負載均衡,更高階流量、安全等功能需要藉助服務治理框架實現。

2.2 服務註冊發現實現

2.2.1 服務註冊過程:

spring cloud 服務配置有serivce的服務,啟動後k8s叢集針對呼叫該service,後端會返回具體的pod列表。

2.2.2 服務發現過程:

  • 在同一名稱空間,直接使用service進行呼叫;
  • 跨名稱空間使用resttemplate進行呼叫service;

2.3 方案特點

  • 優點:
  • 負載均衡演算法在服務端實現(service 的原生負載均衡演算法),後期可使用服務治理框架例如istio/linkerd進行服務治理。
  • 不足:
  • 服務直接通過k8s服務發現,經過service一層,在書主機請求通過iptables/lvs是轉發一層,效能稍弱。

三 實戰

3.1 服務提供者

3.1服務提供者 專案位置:https://github.com/redhatxl/cloudnative-java

3.2 服務消費端

3.2.1 消費者邏輯

服務註冊,僅需為服務編寫 service yaml 資源清單即可。 springboot-clientservice 直接使用service 發起呼叫,服務發現通過service後端關聯的endpoints,轉發至對應endpoints上。

3.2.2 服務發現

引入 spring-cloud-starter-openfeign 進行客戶端http請求發起; 引入 spring-cloud-starter-loadbalancer 進行負載均衡(實際針對service發起呼叫不用負載均衡);

```yaml org.springframework.cloud spring-cloud-starter-openfeign 3.1.3

org.springframework.cloud spring-cloud-starter-loadbalancer 3.1.3 ```

3.2.3 專案目錄結構

shell . ├── Dockerfile ├── HELP.md ├── README.md ├── deploy │ ├── deploy.yaml ├── mvnw ├── mvnw.cmd ├── pom.xml ├── springboot-clientservice.iml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── xuel │ │ │ ├── controller │ │ │ │ └── SpringBootClientServiceController.java │ │ │ ├── feign │ │ │ │ └── FeignService.java │ │ │ ├── service │ │ │ │ ├── SpringBootClientService.java │ │ │ │ └── impl │ │ │ │ └── SpringBootClientServiceImpl.java │ │ │ └── springbootclientservice │ │ │ └── SpringbootClientserviceApplication.java │ │ └── resources │ │ ├── application.properties │ │ ├── static │ │ └── templates

3.2.4 K8s部署檔案

  • deploy.yml

yaml apiVersion: apps/v1 kind: Deployment metadata: namespace: spring name: springboot-clientservice labels: app: springboot-clientservice spec: replicas: 1 selector: matchLabels: app: springboot-clientservice template: metadata: labels: app: springboot-clientservice spec: containers: - name: springboot-clientservice image: ccr.ccs.tencentyun.com/xxxxxxx-dev/springbootclientservice:img_v7 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 protocol: TCP livenessProbe: httpGet: port: 8080 path: /actuator/health periodSeconds: 10 initialDelaySeconds: 3 terminationGracePeriodSeconds: 10 failureThreshold: 5 timeoutSeconds: 10 readinessProbe: httpGet: port: 8080 path: /actuator/health initialDelaySeconds: 5 periodSeconds: 10 failureThreshold: 5 timeoutSeconds: 10

  • service.yaml

yaml apiVersion: v1 kind: Service metadata: name: springbootclientservice namespace: spring labels: app: springboot-clientservice spec: ports: - port: 8080 protocol: TCP targetPort: 8080 type: ClusterIP selector: app: springboot-clientservice

3.2.5 專案原始碼

專案位置:https://github.com/redhatxl/cloudnative-java

四 測試

4.1 訪問服務提供者

由於本地mac 使用kind部署,通過port-forward進行對映到宿主機。

shell k port-forward -n spring --address 0.0.0.0 svc/springbootinit 9999:8080

/services: 獲取到對的service 列表,當前的時間,相應的 Pod 主機名稱。

4.2 訪問服務消費者

shell k port-forward -n spring --address 0.0.0.0 svc/springbootclientservice 8888:8080

/getsvc : 獲取 K8s 內部列表,即請求到的 POD hostname。

在此負載均衡使用的為service的,測試訪問很多次才進行輪換。

4.3 檢視資源

五 其他

總結下來,服務註冊通過給服務新增service,服務發現通過直接呼叫service發起請求。