Dapr在Java中的服務(wù)調(diào)用實戰(zhàn)過程詳解
服務(wù)調(diào)用
通過服務(wù)調(diào)用(Service-to-service Invocation),服務(wù)可以使用 gRPC 或 HTTP 這樣的標(biāo)準(zhǔn)協(xié)議來發(fā)現(xiàn)并可靠地與其他服務(wù)通信。
Dapr采用邊車(Sidecar)、去中心化的架構(gòu)。 要使用Dapr來調(diào)用服務(wù),可以在任意Dapr實例上使用invoke這個API。 邊車編程模型鼓勵每個服務(wù)與自己的Dapr實例對話。 Dapr實例會相互發(fā)現(xiàn)并進行通信。
創(chuàng)建項目
創(chuàng)建兩個SpringBoot項目,分別命名為:invoke-server和invoke-client。invoke-server作為下游服務(wù),被invoke-client調(diào)用,具體調(diào)用過程如下圖:

調(diào)用過程包括:
invoke-client服務(wù)對invoke-server服務(wù)發(fā)起HTTP或gRPC調(diào)用的時候,訪問invoke-client服務(wù)的Dapr實例。invoke-client服務(wù)的Dapr實例通過運行在給定托管平臺上服務(wù)名解析組件(Name Resolution Component)發(fā)現(xiàn)了運行在此Dapr環(huán)境中的invoke-server服務(wù)。invoke-client服務(wù)的Dapr實例將消息轉(zhuǎn)發(fā)到服務(wù)invoke-server服務(wù)的Dapr實例。Dapr實例之間的所有調(diào)用考慮到性能都優(yōu)先使用gRPC。 僅服務(wù)與Dapr實例之間的調(diào)用可以是HTTP或gRPC。invoke-server服務(wù)的Dapr實例將請求轉(zhuǎn)發(fā)至invoke-server服務(wù)上的特定端點或方法,隨后運行其業(yè)務(wù)邏輯代碼。invoke-server服務(wù)返回響應(yīng)信息給invoke-client服務(wù)時,響應(yīng)信息給將轉(zhuǎn)至invoke-server服務(wù)的Dapr實例。invoke-server服務(wù)的Dapr實例消息轉(zhuǎn)發(fā)至invoke-client服務(wù)的Dapr實例。invoke-client服務(wù)接收到其Dapr實例的響應(yīng)信息。
編寫invoke-server的代碼
調(diào)用/send接口時,返回對應(yīng)信息,主要代碼如下:
package one.more.society.invoke.server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class InvokeServerController {
@RequestMapping(value = "/send", method = RequestMethod.POST)
public InvokeResponse send(@RequestBody InvokeRequest request) {
log.info("send - request:{}", request);
InvokeResponse response = new InvokeResponse();
response.setCode(1);
response.setStatus("ok");
response.setMsgId(System.nanoTime());
response.setMsgContent("I konw you said: " + request.getMsgContent());
return response;
}
}其中,InvokeRequest和InvokeResponse的源碼如下:
package one.more.society.invoke.server;
import lombok.Data;
@Data
public class InvokeRequest {
private Long msgId;
private String msgContent;
}package one.more.society.invoke.server;
import lombok.Data;
@Data
public class InvokeResponse {
private int code;
private String status;
private Long msgId;
private String msgContent;
}在application.properties中配置:
server.port=30001
編寫invoke-client
在invoke-client項目的pom.xml文件中添加如下依賴:
<dependency>
<groupId>io.dapr</groupId>
<artifactId>dapr-sdk-springboot</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>注入一個DaprClient的bean:
@Configuration
public class DaprConfig {
private static final DaprClientBuilder BUILDER = new DaprClientBuilder();
@Bean
public DaprClient buildDaprClient() {
return BUILDER.build();
}
}調(diào)用invoke-server的/send接口,主要代碼如下:
package one.more.society.invoke.client;
import io.dapr.client.DaprClient;
import io.dapr.client.domain.HttpExtension;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class InvokeClientController {
@Autowired
private DaprClient client;
private static final String SERVICE_APP_ID = "invoke-server";
private static final String METHOD_NAME = "send";
@RequestMapping(value = "/say", method = RequestMethod.GET)
public InvokeResponse say(String message) {
log.info("send - message:{}", message);
InvokeRequest request = new InvokeRequest();
request.setMsgId(System.nanoTime());
request.setMsgContent(message);
InvokeResponse response = client.invokeMethod(
SERVICE_APP_ID,
METHOD_NAME,
request,
HttpExtension.POST,
InvokeResponse.class).block();
return response;
}
}其中,InvokeRequest、InvokeResponse的源碼與invoke-server中是一樣的。
在application.properties中配置:
server.port=30002
啟動服務(wù)
在啟動之前先用mvn命令打包:
mvn clean package
在invoke-server項目的目錄中執(zhí)行以下命令,啟動invoke-server服務(wù):
dapr run --app-id invoke-server --app-port 30001 --dapr-http-port 31001 -- java -jar target/invoke-server-0.0.1-SNAPSHOT.jar
在invoke-client項目的目錄中執(zhí)行以下命令,啟動invoke-client服務(wù):
dapr run --app-id invoke-client --app-port 30002 --dapr-http-port 31002 -- java -jar target/invoke-client-0.0.1-SNAPSHOT.jar
在Dapr Dashboard中看到:

兩個服務(wù)都已經(jīng)啟動成功。
訪問http://localhost:30002/say?message=OneMoreSociety驗證整個調(diào)用流程:

可以看到服務(wù)之間的調(diào)用沒有問題,并返回了預(yù)想的結(jié)果。
名稱解析組件
為了啟用服務(wù)發(fā)現(xiàn)和服務(wù)調(diào)用,Dapr使用可插拔的名稱解析組件。 Kubernetes名稱解析組件使用Kubernetes DNS服務(wù)來解析集群中運行的其他服務(wù)的位置;自托管機器可以使用mDNS名稱解析組件。
Consul名稱解析組件可以在任何托管環(huán)境中使用,包括Kubernetes或自托管環(huán)境。下面讓我們來嘗試一下,使用Consul作為名稱解析組件。
在用戶目錄下的.dapr文件夾中,找到config.yaml文件。在該文件中,添加一個nameResolution的spec ,并將component字段設(shè)置為consul,比如:
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: daprConfig
spec:
nameResolution:
component: "consul"
configuration:
client:
address: "127.0.0.1:8500"
selfRegister: true重新啟動服務(wù),可以在日志中看到注冊到了Consul上:
time="14:28:54.4540593+08:00" level=info msg="service:invoke-client registered on consul agent" app_id=invoke-client instance=OneMoreSociety scope=dapr.contrib type=log ver=1.7.3
time="14:28:54.4550937+08:00" level=info msg="Initialized name resolution to consul" app_id=invoke-client instance=OneMoreSociety scope=dapr.runtime type=log ver=1.7.3
在Consul中也可以看到兩個服務(wù)都已經(jīng)注冊上去了,如下圖:

值得注意的是:Consul名稱解析組件目前還處于Alpha狀態(tài),最好不要在生產(chǎn)環(huán)境使用。
更詳細的配置說明見下表:
| 配置項 | 是否必填 | 數(shù)據(jù)類型 | 說明 | 示例 |
|---|---|---|---|---|
| client | N | Config | 配置客戶端與 Consul 代理的連接。 如果留空,將使用默認值,即127.0.0.1:8500 | 192.168.0.111:8500 |
| queryOptions | N | QueryOptions | 配置用于解決健康服務(wù)的查詢,默認為UseCache:true | UseCache: false, Datacenter: "myDC" |
| checks | N | AgentServiceCheck數(shù)組 | 當(dāng)進行注冊服務(wù)時,配置健康檢查。默認到Dapr實例檢測健康端點。 | |
| tags | N | string數(shù)組 | 在注冊服務(wù)服務(wù)時包含的額外標(biāo)簽 | - "dapr" |
| meta | N | string字典 | 在注冊服務(wù)服務(wù)時包含的額外的元數(shù)據(jù) | DAPR_METRICS_PORT: "${DAPR_METRICS_PORT}" |
| daprPortMetaKey | N | string | 用于在服務(wù)解析過程中從Consul服務(wù)元數(shù)據(jù)中獲取Dapr實例端口的 key,它也將用于在注冊時在元數(shù)據(jù)中設(shè)置Dapr實例端口。 默認為 DAPR_PORT | "DAPR_TO_DAPR_PORT" |
| selfRegister | N | boolean | 控制Dapr實例是否會向Consul注冊服務(wù),默認為 false | true |
| advancedRegistration | N | AgentServiceRegistration | 通過配置完全控制服務(wù)注冊結(jié)果。 如果配置此項,Checks、 Tags、 Meta 和 SelfRegister的任何配置將被忽略。 |
AgentServiceCheck數(shù)組
配置示例:
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: appconfig
spec:
nameResolution:
component: "consul"
configuration:
client:
address: "127.0.0.1:8500"
selfRegister: true
checks:
- name: "Dapr Health Status"
checkID: "daprHealth:${APP_ID}"
interval: "15s",
http: "http://${HOST_ADDRESS}:${DAPR_HTTP_PORT}/v1.0/healthz"
- name: "Service Health Status"
checkID: "serviceHealth:${APP_ID}"
interval: "15s",
http: "http://${HOST_ADDRESS}:${APP_PORT}/health"
tags:
- "dapr"
- "v1"
- "${OTHER_ENV_VARIABLE}"
meta:
DAPR_METRICS_PORT: "${DAPR_METRICS_PORT}"
DAPR_PROFILE_PORT: "${DAPR_PROFILE_PORT}"
daprPortMetaKey: "DAPR_PORT"
queryOptions:
useCache: true
filter: "Checks.ServiceTags contains dapr"以上就是Dapr在Java中的服務(wù)調(diào)用實戰(zhàn)過程詳解的詳細內(nèi)容,更多關(guān)于Dapr Java服務(wù)調(diào)用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用java代碼實現(xiàn)保留小數(shù)點的位數(shù)
因為個人應(yīng)用的需要,所以就寫個簡單點的了。希望大家都給給建議,共同學(xué)習(xí)。需要的朋友也可以參考下2013-07-07
Java連接合并2個數(shù)組(Array)的5種方法例子
最近在寫代碼時遇到了需要合并兩個數(shù)組的需求,突然發(fā)現(xiàn)以前沒用過,于是研究了一下合并數(shù)組的方式,這篇文章主要給大家介紹了關(guān)于Java連接合并2個數(shù)組(Array)的5種方法,需要的朋友可以參考下2023-12-12
java基礎(chǔ)篇之Date類型最常用的時間計算(相當(dāng)全面)
這篇文章主要給大家介紹了關(guān)于java基礎(chǔ)篇之Date類型最常用的時間計算的相關(guān)資料,Java中的Date類是用來表示日期和時間的類,它提供了一些常用的方法來處理日期和時間的操作,需要的朋友可以參考下2023-12-12

