服务调用

通过服务调用(Service-to-service Invocation),服务可以使用 gRPC 或 HTTP 这样的标准协议来发现并可靠地与其他服务通信。

Dapr采用边车(Sidecar)、去中心化的架构。 要使用Dapr来调用服务,可以在任意Dapr实例上使用invoke这个API。 边车编程模型鼓励每个服务与自己的Dapr实例对话。 Dapr实例会相互发现并进行通信。

文章持续更新,微信搜索「万猫学社」第一时间阅读,关注后回复「电子书」,免费获取12本Java必读技术书籍。

创建项目

创建两个SpringBoot项目,分别命名为:invoke-serverinvoke-clientinvoke-server作为下游服务,被invoke-client调用,具体调用过程如下图:

调用过程包括:

  1. invoke-client服务对invoke-server服务发起HTTP或gRPC调用的时候,访问invoke-client服务的Dapr实例。
  2. invoke-client服务的Dapr实例通过运行在给定托管平台上服务名解析组件(Name Resolution Component)发现了运行在此Dapr环境中的invoke-server服务。
  3. invoke-client服务的Dapr实例将消息转发到服务invoke-server服务的Dapr实例。Dapr实例之间的所有调用考虑到性能都优先使用gRPC。 仅服务与Dapr实例之间的调用可以是HTTP或gRPC。
  4. invoke-server服务的Dapr实例将请求转发至invoke-server服务上的特定端点或方法,随后运行其业务逻辑代码。
  5. invoke-server服务返回响应信息给invoke-client服务时,响应信息给将转至invoke-server服务的Dapr实例。
  6. invoke-server服务的Dapr实例消息转发至invoke-client服务的Dapr实例。
  7. invoke-client服务接收到其Dapr实例的响应信息。

文章持续更新,微信搜索「万猫学社」第一时间阅读,关注后回复「电子书」,免费获取12本Java必读技术书籍。

编写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;
}
}

其中,InvokeRequestInvokeResponse的源码如下:

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

文章持续更新,微信搜索「万猫学社」第一时间阅读,关注后回复「电子书」,免费获取12本Java必读技术书籍。

编写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;
}
}

其中,InvokeRequestInvokeResponse的源码与invoke-server中是一样的。

application.properties中配置:

server.port=30002

文章持续更新,微信搜索「万猫学社」第一时间阅读,关注后回复「电子书」,免费获取12本Java必读技术书籍。

启动服务

在启动之前先用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验证整个调用流程:

可以看到服务之间的调用没有问题,并返回了预想的结果。

文章持续更新,微信搜索「万猫学社」第一时间阅读,关注后回复「电子书」,免费获取12本Java必读技术书籍。

名称解析组件

为了启用服务发现和服务调用,Dapr使用可插拔的名称解析组件。 Kubernetes名称解析组件使用Kubernetes DNS服务来解析集群中运行的其他服务的位置;自托管机器可以使用mDNS名称解析组件。

Consul名称解析组件可以在任何托管环境中使用,包括Kubernetes或自托管环境。下面让我们来尝试一下,使用Consul作为名称解析组件。

在用户目录下的.dapr文件夹中,找到config.yaml文件。在该文件中,添加一个nameResolutionspec ,并将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"

最后,感谢你这么帅,还给我点赞

微信公众号:万猫学社

微信扫描二维码

关注后回复「电子书」

获取12本Java必读技术书籍

Dapr在Java中的实践 之 服务调用的更多相关文章

  1. Java进阶(三十一) Web服务调用

    Java进阶(三十一) Web服务调用 前言 有朋友问了一个问题:如何调用已知的音乐服务接口,服务文档如下: https://www.evernote.com/shard/s744/sh/c37cd5 ...

  2. 中文乱码在java中URLEncoder.encode方法要调用两次解决

    中文乱码在java中URLEncoder.encode方法要调用两次解决 一.场景: 1.我在客户端要通过get方式调用服务器端的url,将中文参数做utf-8编码,需要在js中两次的进行编码,服务器 ...

  3. java中使用axis发布和调用webService及dom4j解析xml字符串

    工作中需要调用webService服务,这里记录一下如何在java中发布和调用webService. 需要的jar包: webService服务端: import javax.jws.WebMetho ...

  4. 关于Java中基类构造器的调用问题

    在<Java编程思想>第7章复用类中有这样一段话,值得深思.当子类继承了父类时,就涉及到了基类和导出类(子类)这两个类.从外部来看,导出类就像是一个与基类具有相同接口的新类,或许还会有一些 ...

  5. C++/Java中继承关系引发的调用关系详解

    C++: 这里引用到了 http://blog.csdn.net/haoel/article/details/1948051/ 中的内容,还请提前阅读陈大神的这篇博客后在阅读本篇. 覆盖,实现多态的基 ...

  6. java中静态方法和非静态方法调用的一点小困扰,已解决。

    public static void main(String[] args) { // TODO Auto-generated method stub SimpleGui1B gui=new Simp ...

  7. Java中多线程启动,为什么调用的是start方法,而不是run方法?

    前言 大年初二,大家新年快乐,我又开始码字了.写这篇文章,源于在家和基友交流的时候,基友问到了,我猛然发现还真是这么回事,多线程启动调用的都是start,那么为什么没人掉用run呢?于是打开我的ide ...

  8. 实例详解Java中如何对方法进行调用

    原文源自http://www.jb51.net/article/73827.htm 方法调用Java支持两种调用方法的方式,根据方法是否返回值来选择. 当程序调用一个方法时,程序的控制权交给了被调用的 ...

  9. java中避免集合死链调用

    目录 1. 前言 2. 场景 3. 环境 3.1 开发环境准备 3.2 数据准备 3.2.1 Mysql数据库表及数据 3.2.2 redis库数据 4. 解决方式 5.完整代码 5.1Model 5 ...

  10. Java中的一个类怎么调用另一个类中的方法

    如果另一个类中的那个方法是私有的话,就不能直接调用到,如果是其他类型的话看情况,如果是静态的(static)话,直接用类名可以调用到,如果是非静态的,就需要利用另一个类的实例(也就是用那个类生成的对象 ...

随机推荐

  1. QGIS 导入文本数据(WKT)

    在做GIS数据处理的时候,经常会遇到原始数据是 text.csv.Excel 等格式的数据.要使用数据前提是要先转换数据. 这里是介绍用 QGIS 导入数据.打开导入方式如下(根据自己的文本类型选择不 ...

  2. Rancher 系列文章-K3s Traefik MiddleWare 报错-Failed to create middleware keys

    概述 书接上回:<Rancher 系列文章-K3S 集群升级>, 我们提到:通过一键脚本升级 K3S 集群有报错. 接下来开始进行 Traefik 报错的分析和修复, 问题是: 所有 Tr ...

  3. Json和对象之间的转换

    JSON是一种字符: json转对象: var str = '{"name":"admin","age":16,"sex" ...

  4. 云上大数据存储:探究 JuiceFS 与 HDFS 的异同

    HDFS 作为 Hadoop 提供存储组件,已经成为大数据生态里面数据存储最常用的选择,通常在机房环境部署. JuiceFS 是一个基于对象存储的分布式文件系统,用户可以在云上快速地搭建按需扩容的弹性 ...

  5. What's the best way to read and understand someone else's code?

    Find one thing you know the code does, and trace those actions backward, starting at the end Say, fo ...

  6. Spring中Bean的实例化详细流程

    还是举个例子,我有一个朋友小汪他远赴南方某城市打工.然后安定下来后他的朋友很想来家里玩,但是呢我这个朋友家里搞的很乱,所以他不好意思请朋友来家里玩.这时我的另一个朋友说那请一个保姆把家里好好整理一下就 ...

  7. c/c++快乐算法第三天

    c/c++感受算法快乐(3) 开始时间2023-04-16 22:21:10 结束时间2023-04-17 00:09:34 前言:很好,这周就要结束了,大家都回学校了么,嘻嘻.回顾一下昨天的算法题, ...

  8. JavaFx 实现水平滚动文本(跑马灯效果)

    原文地址: JavaFx 实现水平滚动文本(跑马灯效果) - Stars-One的杂货小窝 本文是以TornadoFx框架进行编写,各位使用JavaFx可以参考 代码已经封装在common-contr ...

  9. YOLO2论文中文版

    文章目录 YOLO9000中文版 摘要 1. 引言 2. 更好 3. 更快 4. 更强 5. 结论 参考文献 YOLO9000中文版 摘要 我们引入了一个先进的实时目标检测系统YOLO9000,可以检 ...

  10. windows11 下使用 阿里云 modelscope docker 环境 运行参考

    昨天看视频 我们做了个能对话的AI派蒙,免费给大家玩! 发现阿里有一个语音转文字的模型(paraformer),之前处理这种需求一直都是直接调用服务商提交好的API接口 突然想尝试一下本地搭建,虽然和 ...