前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Dapr在Java中的实践 之 服务调用

Dapr在Java中的实践 之 服务调用

作者头像
万猫学社
发布2022-12-01 16:03:37
6670
发布2022-12-01 16:03:37
举报
文章被收录于专栏:技术专家成长之路

服务调用

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

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

创建项目

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

service-invocation-overview

调用过程包括:

  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实例的响应信息。

编写invoke-server的代码

调用/send接口时,返回对应信息,主要代码如下:

代码语言:javascript
复制
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();
        response.setStatus("ok");
        response.setMsgId(System.nanoTime());
        response.setMsgContent("I konw you said: " + request.getMsgContent());

        return response;
    }
}

其中,InvokeRequestInvokeResponse的源码如下:

代码语言:javascript
复制
package one.more.society.invoke.server;

import lombok.Data;

@Data
public class InvokeRequest {

    private Long msgId;
    private String msgContent;
}
代码语言:javascript
复制
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中配置:

代码语言:javascript
复制
server.port=30001

编写invoke-client

invoke-client项目的pom.xml文件中添加如下依赖:

代码语言:javascript
复制
<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:

代码语言:javascript
复制
@Configuration
public class DaprConfig {

    private static final DaprClientBuilder BUILDER = new DaprClientBuilder();

    @Bean
    public DaprClient buildDaprClient() {
        return BUILDER.build();
    }
}

调用invoke-server/send接口,主要代码如下:

代码语言:javascript
复制
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中配置:

代码语言:javascript
复制
server.port=30002

启动服务

在启动之前先用mvn命令打包:

代码语言:javascript
复制
mvn clean package

invoke-server项目的目录中执行以下命令,启动invoke-server服务:

代码语言:javascript
复制
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服务:

代码语言:javascript
复制
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中看到:

Dapr Dashboard

两个服务都已经启动成功。

访问http://localhost:30002/say?message=OneMoreSociety验证整个调用流程:

http://localhost:30002/say?message=OneMoreSociety

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

名称解析组件

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

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

在用户目录下的.dapr文件夹中,找到config.yaml文件。在该文件中,添加一个nameResolutionspec ,并将component字段设置为consul,比如:

代码语言:javascript
复制
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprConfig
spec:
  nameResolution:
    component: "consul"
    configuration:
      client:
        address: "127.0.0.1:8500"
      selfRegister: true

重新启动服务,可以在日志中看到注册到了Consul上:

代码语言:javascript
复制
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

值得注意的是: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的任何配置将被忽略。

配置示例:

代码语言:javascript
复制
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"
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 万猫学社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 服务调用
  • 创建项目
  • 编写invoke-server的代码
  • 编写invoke-client
  • 启动服务
  • 名称解析组件
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档