Dapr在Java中的服务调用实战过程详解
服务调用
通过服务调用(Service-to-service Invocation),服务可以使用 gRPC 或 HTTP 这样的标准协议来发现并可靠地与其他服务通信。
Dapr采用边车(Sidecar)、去中心化的架构。 要使用Dapr来调用服务,可以在任意Dapr实例上使用invoke这个API。 边车编程模型鼓励每个服务与自己的Dapr实例对话。 Dapr实例会相互发现并进行通信。
创建项目
创建两个SpringBoot项目,分别命名为:invoke-server
和invoke-client
。invoke-server
作为下游服务,被invoke-client
调用,具体调用过程如下图:
调用过程包括:
invoke-client
服务对invoke-server
服务发起HTTP或gRPC调用的时候,访问invoke-client
服务的Dapr实例。invoke-client
服务的Dapr实例通过运行在给定托管平台上服务名解析组件(Name Resolution Component)发现了运行在此Dapr环境中的invoke-server
服务。invoke-client
服务的Dapr实例将消息转发到服务invoke-server
服务的Dapr实例。Dapr实例之间的所有调用考虑到性能都优先使用gRPC。 仅服务与Dapr实例之间的调用可以是HTTP或gRPC。invoke-server
服务的Dapr实例将请求转发至invoke-server
服务上的特定端点或方法,随后运行其业务逻辑代码。invoke-server
服务返回响应信息给invoke-client
服务时,响应信息给将转至invoke-server
服务的Dapr实例。invoke-server
服务的Dapr实例消息转发至invoke-client
服务的Dapr实例。invoke-client
服务接收到其Dapr实例的响应信息。
编写invoke-server的代码
调用/send
接口时,返回对应信息,主要代码如下:
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(); } }
调用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
启动服务
在启动之前先用mvn
命令打包:
mvn clean package
在invoke-server
项目的目录中执行以下命令,启动invoke-server
服务:
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
项目的目录中执行以下命令,启动invoke-client
服务:
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中看到:
两个服务都已经启动成功。
访问http://localhost:30002/say?message=OneMoreSociety验证整个调用流程:
可以看到服务之间的调用没有问题,并返回了预想的结果。
名称解析组件
为了启用服务发现和服务调用,Dapr使用可插拔的名称解析组件。 Kubernetes名称解析组件使用Kubernetes DNS服务来解析集群中运行的其他服务的位置;自托管机器可以使用mDNS名称解析组件。
Consul名称解析组件可以在任何托管环境中使用,包括Kubernetes或自托管环境。下面让我们来尝试一下,使用Consul作为名称解析组件。
在用户目录下的.dapr
文件夹中,找到config.yaml
文件。在该文件中,添加一个nameResolution
的spec
,并将component
字段设置为consul
,比如:
apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: daprConfig spec: nameResolution: component: "consul" configuration: client: address: "127.0.0.1:8500" selfRegister: true
重新启动服务,可以在日志中看到注册到了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中也可以看到两个服务都已经注册上去了,如下图:
值得注意的是:Consul名称解析组件目前还处于Alpha状态,最好不要在生产环境使用。
更详细的配置说明见下表:
配置项 | 是否必填 | 数据类型 | 说明 | 示例 |
---|---|---|---|---|
client | N | Config | 配置客户端与 Consul 代理的连接。 如果留空,将使用默认值,即127.0.0.1:8500 | 192.168.0.111:8500 |
queryOptions | N | QueryOptions | 配置用于解决健康服务的查询,默认为UseCache:true | UseCache: false, Datacenter: "myDC" |
checks | N | AgentServiceCheck数组 | 当进行注册服务时,配置健康检查。默认到Dapr实例检测健康端点。 | |
tags | N | string数组 | 在注册服务服务时包含的额外标签 | - "dapr" |
meta | N | string字典 | 在注册服务服务时包含的额外的元数据 | DAPR_METRICS_PORT: "${DAPR_METRICS_PORT}" |
daprPortMetaKey | N | string | 用于在服务解析过程中从Consul服务元数据中获取Dapr实例端口的 key,它也将用于在注册时在元数据中设置Dapr实例端口。 默认为 DAPR_PORT | "DAPR_TO_DAPR_PORT" |
selfRegister | N | boolean | 控制Dapr实例是否会向Consul注册服务,默认为 false | true |
advancedRegistration | N | AgentServiceRegistration | 通过配置完全控制服务注册结果。 如果配置此项,Checks、 Tags、 Meta 和 SelfRegister的任何配置将被忽略。 |
配置示例:
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中的服务调用实战过程详解的详细内容,更多关于Dapr Java服务调用的资料请关注脚本之家其它相关文章!
相关文章
谈谈Java中对象,类和this,super,static关键字的使用
对象:对象是类的一个实例,有状态和行为。类:类是一个模板,它描述一类对象的行为和状态。本文就来和大家聊聊Java中对象,类和关键字的使用,需要的可以参考一下2022-08-08javaweb 国际化:DateFormat,NumberFormat,MessageFormat,ResourceBu
本文主要介绍javaWEB国际化的知识,这里整理了详细的资料及实现代码,有兴趣的小伙伴可以参考下2016-09-09PowerJob的IdGenerateService工作流程源码解读
这篇文章主要为大家介绍了PowerJob的IdGenerateService工作流程源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2024-01-01SpringBoot集成Nacos实现注册中心与配置中心流程详解
这篇文章主要介绍了SpringBoot集成Nacos实现注册中心与配置中心流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧2023-02-02
最新评论