歡迎訪問我的GitHub

https://github.com/zq2599/blog_demos

內容:所有原創文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;

《java版gRPC實戰》全系列鏈接

  1. 用proto生成代碼
  2. 服務發布和調用
  3. 服務端流
  4. 客戶端流
  5. 雙向流
  6. 客戶端動態獲取服務端地址
  7. 基於eureka的注册發現

關於eureka

前面咱們在開發客戶端應用時,所需的服務端地址都是按如下步驟設置的:

  • 在application.yml中配置,如下圖:

  • 在用到gRPC的bean中,使用注解GrpcClient即可將Stub類注入到成員變量中:

  • 上述操作方式的優點是簡單易用好配置,缺點也很明顯:服務端的IP地址或者端口一旦有變化,就必須修改application.yml並重啟客戶端應用;
  • 聰明的您一定想到了應對之道:注册中心!沒錯,有了注册中心,咱們的客戶端只要能從注册中心取得最新的服務端地址,就不再需要手動配置了,以下是常規的eureka作用說明:

本篇概覽

  • 如果您有Spring Cloud的開發經驗,對resttemplate和feign等應該很熟悉,但是Spring Cloud環境下的gRPC調用卻沒有那麼常用,本篇的目標是通過實戰與大家一起掌握Spring Cloud環境下的gRPC調用,分為以下章節:
  1. eureka應用開發
  2. gRPC服務端開發
  3. gRPC客戶端開發
  4. 驗證
  5. 一點疑惑

源碼下載

名稱 鏈接 備注
項目主頁 https://github.com/zq2599/blog_demos 該項目在GitHub上的主頁
git倉庫地址(https) https://github.com/zq2599/blog_demos.git 該項目源碼的倉庫地址,https協議
git倉庫地址(ssh) [email protected]:zq2599/blog_demos.git 該項目源碼的倉庫地址,ssh協議
  • 這個git項目中有多個文件夾,《java版gRPC實戰》系列的源碼在grpc-tutorials文件夾下,如下圖紅框所示:

  • grpc-tutorials文件夾下有多個目錄,本篇文章對應的eureka代碼在cloud-eureka目錄,服務端代碼在cloud-server-side目錄,客戶端代碼在cloud-client-side目錄,如下圖:

eureka應用開發

  • 在父工程grpc-turtorials下面新建名為cloud-eureka的模塊,其build.gradle內容如下:
// 使用springboot插件
plugins {
id 'org.springframework.boot'
} dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
// 依賴eureka
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
// 狀態暴露需要的依賴
implementation 'org.springframework.boot:spring-boot-starter-actuator'
// 依賴自動生成源碼的工程
implementation project(':grpc-lib')
}
  • 配置文件bootstrap.yml,設置自己的web端口號和應用名,另外eureka.client.serviceUrl.defaultZone的配置請改成自己的IP:
server:
port: 8085 spring:
application:
name: cloud-eureka eureka:
instance:
hostname: localhost
prefer-ip-address: true
status-page-url-path: /actuator/info
health-check-url-path: /actuator/health
lease-expiration-duration-in-seconds: 30
lease-renewal-interval-in-seconds: 30
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://192.168.50.5:8085/eureka/
server:
enable-self-preservation: false endpoints:
shutdown:
enabled: true
  • 這個模塊只有一個類CloudEurekaApplication.java:
package com.bolingcavalry.grpctutorials;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer
@SpringBootApplication
public class CloudEurekaApplication { public static void main(String[] args) {
SpringApplication.run(CloudEurekaApplication.class, args);
}
}
  • 以上就是一個簡單通用的eureka服務了;

gRPC服務端開發

  • 依賴eureka的gRPC服務端,其重點在於:第一,配置使用eureka,第二,不要指定端口;

  • 在父工程grpc-turtorials下面新建名為cloud-server-side的模塊,其build.gradle內容如下,注意要引入gRPC服務端相關的starter:

// 使用springboot插件
plugins {
id 'org.springframework.boot'
} dependencies {
implementation 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter'
// 作為gRPC服務提供方,需要用到此庫
implementation 'net.devh:grpc-server-spring-boot-starter'
// 作為eureka的client
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
// 狀態暴露需要的依賴
implementation 'org.springframework.boot:spring-boot-starter-actuator'
// 依賴自動生成源碼的工程
implementation project(':grpc-lib')
// annotationProcessor不會傳遞,使用了lombok生成代碼的模塊,需要自己聲明annotationProcessor
annotationProcessor 'org.projectlombok:lombok'
}
  • 配置文件application.yml,設置自己的應用名,另外值得注意的是server.port和grpc.server.port這兩個配置的值都是0,這樣兩個端口就會被自動分配未被占用的值:
spring:
application:
name: cloud-server-side server:
port: 0
grpc:
server:
port: 0
eureka:
instance:
prefer-ip-address: true
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://192.168.50.5:8085/eureka/
  • 啟動類CloudServerSideApplication.java:
package com.bolingcavalry.grpctutorials;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class CloudServerSideApplication { public static void main(String[] args) {
SpringApplication.run(CloudServerSideApplication.class, args);
}
}
  • 提供gRPC服務的類GrpcServerService,和local-server模塊中的一樣:
package com.bolingcavalry.grpctutorials;
import com.bolingcavalry.grpctutorials.lib.HelloReply;
import com.bolingcavalry.grpctutorials.lib.SimpleGrpc;
import net.devh.boot.grpc.server.service.GrpcService;
import java.util.Date; @GrpcService
public class GrpcServerService extends SimpleGrpc.SimpleImplBase { @Override
public void sayHello(com.bolingcavalry.grpctutorials.lib.HelloRequest request,
io.grpc.stub.StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("1. Hello " + request.getName() + ", " + new Date()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
  • 以上就是服務端代碼了,可見除了將gRPC端口設置為0,以及常規使用eureka的配置,其他部分和local-server模塊是一樣的;

gRPC客戶端開發

  • 依賴eureka的gRPC客戶端,其重點在於:第一,配置使用eureka,第二,配置中的gRPC配置項的名字要等於gRPC服務端在eureka注册的名字,如下圖紅框所示:

  • 在父工程grpc-turtorials下面新建名為cloud-client-side的模塊,其build.gradle內容如下,注意要引入gRPC客戶端相關的starter:
// 使用springboot插件
plugins {
id 'org.springframework.boot'
} dependencies {
implementation 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter'
// 作為gRPC服務使用方,需要用到此庫
implementation 'net.devh:grpc-client-spring-boot-starter'
// 作為eureka的client
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
// 狀態暴露需要的依賴
implementation 'org.springframework.boot:spring-boot-starter-actuator'
// 依賴自動生成源碼的工程
implementation project(':grpc-lib')
// annotationProcessor不會傳遞,使用了lombok生成代碼的模塊,需要自己聲明annotationProcessor
annotationProcessor 'org.projectlombok:lombok'
}
  • 配置文件application.yml,設置自己的web端口號,另外值得注意的是gRPC配置項cloud-server-side的名字要等於gRPC服務端在eureka注册的名字,並且不需要address配置項:
server:
port: 8086
spring:
application:
name: cloud-client-side
eureka:
instance:
prefer-ip-address: true
status-page-url-path: /actuator/info
health-check-url-path: /actuator/health
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://192.168.50.5:8085/eureka/
grpc:
client:
# gRPC配置的名字,GrpcClient注解會用到
cloud-server-side:
enableKeepAlive: true
keepAliveWithoutCalls: true
negotiationType: plaintext
  • 啟動類CloudClientSideApplication.java,使用了eureka相關的注解:
package com.bolingcavalry.grpctutorials;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class CloudClientSideApplication { public static void main(String[] args) {
SpringApplication.run(CloudClientSideApplication.class, args);
}
}
  • 封裝gRPC調用的服務類GrpcServerService,和local-server模塊中的一樣,GrpcClient注解對應配置中的gRPC配置項:
package com.bolingcavalry.grpctutorials;
import com.bolingcavalry.grpctutorials.lib.HelloReply;
import com.bolingcavalry.grpctutorials.lib.HelloRequest;
import com.bolingcavalry.grpctutorials.lib.SimpleGrpc;
import io.grpc.StatusRuntimeException;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service; @Service
public class GrpcClientService { @GrpcClient("cloud-server-side")
private SimpleGrpc.SimpleBlockingStub simpleStub; public String sendMessage(final String name) {
try {
final HelloReply response = this.simpleStub.sayHello(HelloRequest.newBuilder().setName(name).build());
return response.getMessage();
} catch (final StatusRuntimeException e) {
return "FAILED with " + e.getStatus().getCode().name();
}
}
}
  • 再做一個web接口類,這樣我們就能通過web調用驗證gRPC服務了:
package com.bolingcavalry.grpctutorials;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; @RestController
public class GrpcClientController { @Autowired
private GrpcClientService grpcClientService; @RequestMapping("/")
public String printMessage(@RequestParam(defaultValue = "will") String name) {
return grpcClientService.sendMessage(name);
}
}
  • 客戶端開發完畢,接下來可以驗證了;

驗證

  • 啟動cloud-eureka:

  • 啟動cloud-server-side,可見gRPC服務端口自動分配了65141,不過我們無需關心這個值,因為客戶端可以從eureka獲取到:

  • 接下來啟動cloud-client-side,啟動成功後eureka上可見兩個服務的注册信息:

  • 瀏覽器訪問cloud-client-side提供的web接口,響應如下,可見cloud-client-side成功調用了cloud-server-side的gRPC服務:

一點疑惑

  • 如果您對eureka有所了解,可能會產生一點疑惑:cloud-client-side從eureka取得的cloud-server-side信息,應該是http服務的地址和端口,不應該有gRPC的端口號,因為eureka的注册發現服務並不包含gRPC有關的!

  • 篇幅所限,這裏不適合將上述問題展開分析,咱們來關注最核心的地方,相信聰明的您看上一眼就會豁然開朗;

  • DiscoveryClientNameResolver來自grpc-client-spring-boot-autoconfigure.jar,用來保存從eureka取得的服務端信息,該類的注釋已經說得很清楚了,從metadata的gRPC.port配置項中取得gRPC端口號:

  • 在DiscoveryClientNameResolver的代碼中打上斷點,查看成員變量instanceList,可見metadata中確實有gRPC端口的信息:

  • 至於cloud-server-side如何將端口號提交到eureka,以及cloud-client-side為何會使用DiscoveryClientNameResolver來處理eureka的服務列錶信息,就不在本文中討論了,您要是有興趣深入研究eureka,可以參考《程序員欣宸文章匯總(Spring篇)》中的Eureka源碼分析專題,如下圖:

  • 至此,基於eureka的gRPC服務注册發現的開發和驗證就完成了,希望本文可以給您帶來一些參考,讓您的服務在注册中心的加持下更加靈活和可靠;

你不孤單,欣宸原創一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 數據庫+中間件系列
  6. DevOps系列

歡迎關注公眾號:程序員欣宸

微信搜索「程序員欣宸」,我是欣宸,期待與您一同暢遊Java世界...

https://github.com/zq2599/blog_demos

java版gRPC實戰之七:基於eureka的注册發現的更多相關文章

  1. Spring-cloud &amp; Netflix 源碼解析:Eureka 服務注册發現接口 ****

    http://www.idouba.net/spring-cloud-source-eureka-client-api/?utm_source=tuicool&utm_medium=refer ...

  2. 微服務學習筆記二:Eureka服務注册發現

    Eureka服務注册發現 服務發現:雲端負載均衡,一個基於 REST 的服務,用於定比特服務,以實現雲端的負載均衡和中間層服務器的故障轉移. 1. Service Discovery: Eureka S ...

  3. spring cloud Eureka 服務注册發現與調用

    記錄一下用spring cloud Eureka搭建服務注册與發現框架的過程. 為了創建spring項目方便,使用了STS. 一.Eureka注册中心 1.新建項目-Spring Starter Pr ...

  4. eureka服務注册發現流程和核心參數

    參數1:eureka.instance.lease-renewal-interval-in-seconds 參數2:eureka.instance.lease-expiration-duration- ...

  5. 微信公眾平臺Java版極速SDK

    JEEWX-API 是第一個微信公眾平臺Java版極速SDK,基於 jeewx-api 開發可以立即擁有簡單易用的API,讓開發更加輕松自如,節省更多時間 http://www.jeewx.com/

  6. 第九篇 :微信公眾平臺開發實戰Java版之如何實現自定義分享內容

    第一部分:微信JS-SDK介紹 微信JS-SDK是微信公眾平臺面向網頁開發者提供的基於微信內的網頁開發工具包. 通過使用微信JS-SDK,網頁開發者可借助微信高效地使用拍照.選圖.語音.比特置等手機系統 ...

  7. Java工程師 基礎+實戰 完整路線圖(詳解版)

    Java工程師 基礎+實戰 完整路線圖(詳解版)   Java 基礎 Java 是一門純粹的面向對象的編程語言,所以除了基礎語法之外,必須得弄懂它的 oop 特性:封裝.繼承.多態.此外還有泛型.反射 ...

  8. 第八篇 :微信公眾平臺開發實戰Java版之如何網頁授權獲取用戶基本信息

    第一部分:微信授權獲取基本信息的介紹 我們首先來看看官方的文檔怎麼說: 如果用戶在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取用戶基本信息,進而實現業務邏輯. 關於網頁授權回調域 ...

  9. 第七篇 :微信公眾平臺開發實戰Java版之如何獲取微信用戶基本信息

    在關注者與公眾號產生消息交互後,公眾號可獲得關注者的OpenID(加密後的微信號,每個用戶對每個公眾號的OpenID是唯一的.對於不同公眾號,同一用戶的openid不同). 公眾號可通過本接口來根據O ...

  10. 第六篇 :微信公眾平臺開發實戰Java版之如何自定義微信公眾號菜單

    我們來了解一下 自定義菜單創建接口: http請求方式:POST(請使用https協議) https://api.weixin.qq.com/cgi-bin/menu/create?access_to ...

隨機推薦

  1. [saiku] 配置saiku實時展現查詢數據

    緣起: 在默認的情况下,saiku是不能對數據進行實時展現的,只能通過刷新按鈕或者重啟服務器來刷新數據 這樣以來會有很多的麻煩,每天得手動去刷新,這個操作只有管理員可以操作,在刷新以前客戶看到的都是緩 ...

  2. 怎樣向IT行業的朋友說明《聖經》的重要性

    “世界的官方文檔”——怎麼樣?

  3. bzoj1402:[HAOI2008]硬幣購物

    思路:完全背包加容斥原理 首先不考慮限制,那麼很容易可以預處理出f[i](f[i]+=f[i-c[i]],1<=i<=4,i-c[i]>=0). 然後考慮如何求出限制後的答案. 首先 ...

  4. npm install fetchmatedata慢的解决辦法

    最近在開發webpack工程時,第一步npm install這裏超級慢,一直停著,顯示:"fetchMetadata: sill mapToRegistry uri https://regi ...

  5. CentOS7 PHP+Redis實現Session共享

    先yum簡單的安裝redis wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/epel-7.repo ...

  6. github 操作

    https://www.cnblogs.com/cxk1995/p/5800196.html 1在已有的GitHub賬號下創建項目. 2將GitHub項目克隆到本地.  git clone https ...

  7. Gluon Datasets and DataLoader

    mxnet.recordio MXRecordIO Reads/writes RecordIO data format, supporting sequential read and write. r ...

  8. 圖像數據增强 (Data Augmentation in Computer Vision)

    1.1 簡介 深層神經網絡一般都需要大量的訓練數據才能獲得比較理想的結果.在數據量有限的情况下,可以通過數據增强(Data Augmentation)來增加訓練樣本的多樣性, 提高模型魯棒性,避免過擬 ...

  9. jQuery $(&#39;div&gt;ul&#39;) $(&#39;div ul&#39;

    $('div>ul')是<div>的直接後代裏找<ul>: 而$('div ul')是在<div>的所有後代裏找<ul>.

  10. wamp昇級php5.3.10到php5.6.13版本

    1.  停止WAMP服務器. 2.  去網站windows.php.net 下載php-5.6.13-nts-Win32-VC9-x86.zip. 不要下載THE INSTALLER. 3.  在wa ...