什么是发布-订阅

发布订阅是一种众所周知并被广泛使用的消息传送模式,常用在微服务架构的服务间通信,高并发削峰等情况。但是不同的消息中间件之间存在细微的差异,项目使用不同的产品需要实现不同的实现类,虽然是明智的决策,但必须编写和维护抽象及其基础实现。 此方法需要复杂、重复且容易出错的自定义代码。

Dapr为了解决这种问题,提供开箱即用的消息传送抽象和实现,封装在 Dapr 构建基块中。业务系统只需调用跟据Dapr的要求实现订阅发布即可。

工作原理

Dapr 发布&订阅构建基块提供了一个与平台无关的 API 框架来发送和接收消息。

服务将消息发布到指定主题, 业务服务订阅主题以使用消息。

服务在 Dapr sidecar 上调用 pub/sub API。 然后,sidecar 调用预定义 Dapr pub/sub 组件。

任何编程平台都可以使用 Dapr 本机 API 通过 HTTP 或 gRPC 调用构建基块。 若要发布消息,请进行以下 API 调用:

http://localhost:<dapr-port>/v1.0/publish/<pub-sub-name>/<topic>

上述调用中有几个特定于 Dapr 的 URL 段:

  • <dapr-port> 提供 Dapr sidecar 侦听的端口号。
  • <pub-sub-name> 提供所选 Dapr pub/sub 组件的名称。
  • <topic> 提供消息发布到的主题的名称。

设置发布订阅组件

Dapr 为 Pub/Sub 提供很多支持的组件,例如 Redis 和 Kafka 等。支持组件详见 链接

在win10上的自承载的Dapr中,默认在 %UserProfile%\.dapr\components\pubsub.yaml 中使用redis作为了pub/sub组件,dapr run一个app时,使用默认组件作为pub/sub组件

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""

订阅主题

Dapr 允许两种方法订阅主题:

  • 声明式,其中定义在外部文件中。
  • 编程方式,订阅在用户代码中定义

1.声明式订阅

在默认组件目录 %UserProfile%\.dapr\components\pubsub.yaml 中新建subscription.yaml文件,并写入以下内容

apiVersion: dapr.io/v1alpha1
kind: Subscription
metadata:
name: myevent-subscription
spec:
topic: test_topic
route: /TestPubSub
pubsubname: pubsub
scopes:
- frontend

上面的示例显示了 test_topic主题的事件订阅,使用组件 pubsub

  • route 告诉 Dapr 将所有主题消息发送到应用程序中的 /TestPubSub 端点。
  • scopes 为 FrontEnd启用订阅

现在需要在FrontEnd项目中定义接口TestSub,在FrontEnd中新建TestPubSubController

using Dapr.Client;

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using System.IO;
using System.Text;
using System.Threading.Tasks; namespace FrontEnd.Controllers
{
[Route("[controller]")]
[ApiController]
public class TestPubSubController : ControllerBase
{
private readonly ILogger<TestPubSubController> _logger;
private readonly DaprClient _daprClient;
public TestPubSubController(ILogger<TestPubSubController> logger, DaprClient daprClient)
{
_logger = logger;
_daprClient = daprClient;
} [HttpPost]
public ActionResult Post()
{
Stream stream = Request.Body;
byte[] buffer = new byte[Request.ContentLength.Value];
stream.Position = 0L;
stream.ReadAsync(buffer, 0, buffer.Length);
string content = Encoding.UTF8.GetString(buffer);
return Ok(content);
} [HttpGet("pub")]
public async Task<ActionResult> PubAsync()
{
var data = new WeatherForecast();
await _daprClient.PublishEventAsync<WeatherForecast>("pubsub", "test_topic", data);
return Ok();
}
}
}

需要在Startup的Configure中开启重复读取Body才能读取到数据

            app.Use((context, next) =>
{
context.Request.EnableBuffering();
return next();
});

启动FrontEnd

dapr run --dapr-http-port 3501 --app-port 5001  --app-id frontend dotnet  .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll

调用 pub API发布消息

查看订阅情况,订阅消息消费成功

2.编程式订阅

为了防止声明式订阅的影响,需要先把目录<%UserProfile%\.dapr\components\pubsub.yaml>中subscription.yaml文件删除

TestPubSubController新增Api Sub

        [Topic("pubsub", "test_topic")]
[HttpPost("sub")]
public async Task<ActionResult> Sub()
{
Stream stream = Request.Body;
byte[] buffer = new byte[Request.ContentLength.Value];
stream.Position = 0L;
stream.ReadAsync(buffer, 0, buffer.Length);
string content = Encoding.UTF8.GetString(buffer);
_logger.LogInformation("testsub" + content);
return Ok(content);
}

在Startup的Configure方法中新增中间件

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ...
app.UseCloudEvents(); app.UseEndpoints(endpoints =>
{
endpoints.MapSubscribeHandler();
// ...
});
}

启动FrontEnd

dapr run --dapr-http-port 3501 --app-port 5001  --app-id frontend dotnet  .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll

调用API发布消息

查看订阅情况,订阅消息消费成功

通过DapreCLI同样可以发布消息

dapr publish --publish-app-id frontend --pubsub pubsub --topic test_topic --data '{"date":"0001-01-01T00:00:00","temperatureC":0,"temperatureF":32,"summary":null}'

查看订阅情况,订阅消息消费成功

Dapr + .NET Core实战(四)发布和订阅的更多相关文章

  1. Dapr + .NET Core实战(十四)虚拟机集群部署 mDNS + Consul

    前面我们说了在单机模式下和K8S集群下的Dapr实战,这次我们来看看如何在不使用K8S的情况下,在一个传统的虚拟机集群里来部署Dapr. 1.环境准备 我们准备两台centos7虚拟机 Dapr1:1 ...

  2. Dapr + .NET Core实战(十-终篇)K8S运行Dapr

    工作原理 为了实现在k8s上安装Dapr,Dapr需要部署dapr-sidecar-injector.dapr-operator.dapr-placement和dapr-sentry服务. dapr- ...

  3. Dapr + .NET Core实战(六)绑定

    什么是绑定 处理外部事件或调用外部接口的功能就是绑定,绑定可以提供以下好处: 避免连接到消息系统 ( 如队列和消息总线 ) 并进行轮询的复杂性 聚焦于业务逻辑,而不是如何与系统交互 使代码不受 SDK ...

  4. Dapr + .NET Core实战(七)Secrets

    什么是Secrets 应用程序通常会通过使用专用的存储来存储敏感信息,如连接字符串.密钥等. 通常这需要建立一个密钥存储,如Azure Key Vault.Hashicorp等,并在那里存储应用程序级 ...

  5. Dapr + .NET Core实战(八)服务监测

    服务监测 分布式服务性能指标,链路追踪,运行状况,日志记录都很重要,我们日常开发中为了实现这些功能需要集成很多功能,替换监控组件时成本也很高. Dapr 可观测性模块将服务监测与应用程序分离.它自动捕 ...

  6. Dapr + .NET Core实战(九)本地调试

    前几节开发Dapr应用程序时,我们使用 dapr cli 来启动dapr服务,就像这样: dapr run --dapr-http-port 3501 --app-port 5001 --app-id ...

  7. Dapr + .NET Core实战(十一)单机Dapr集群

    如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...

  8. Dapr + .NET Core实战(十一)单机Dapr集群负载均衡

    如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...

  9. Dapr + .NET Core实战(十二)服务调用之GRPC

    什么是GRPC gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. gRPC 的主要优点是: 高性能轻量级 RPC 框架. 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的 ...

随机推荐

  1. Java中使用split方法根据英文问号?切割字符串时报错

    因为正则表达式的原因,我们无法在java中直接使用String.split("?"),需要先转义其正确写法为: public static void splitStr() { St ...

  2. SQL 练习10

    查询没有学全所有课程的同学的信息 分析 先查询出所有课程的数量 select count(cid) from course 再查询出成绩表中课程数量=总课数的人员 select sid from sc ...

  3. noip8

    T1 星际旅行 考试时觉得是道数学题,但没想到忘了欧拉路. 首先将每条边都拆成两条边,那么题目就变成了任意删掉两条边,使得新的图中存在欧拉路.设 \(sum\) 表示自环的数量, \(du_{i}\) ...

  4. 虚拟机下安装Centos设置静态ip,并通过桥接连接

    Centos7.6设置静态IP 1.CentOS7默认网卡设备文件存放于该目录下 /etc/sysconfig/network-scripts/ 网卡设备默认的名字为:ifcfg-ens33 查看网卡 ...

  5. C# 读取保存xml文件

    直接读取xml文件中的内容 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(result); XmlNode root = xmlDoc. ...

  6. ThreadPoolExecutor八种拒绝策略浅析

    转自:http://www.kailing.pub/article/index/arcid/255.html 前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5 ...

  7. 改变this指向&闭包特性

    Q:为什么用普通函数时,setTimeout里面的this指向的是window? //通过保留this的方式,通过闭包的特性去拿this let _this = this //...ajax setT ...

  8. SQLServer数据实时同步PostgreSQL

    SQLServer数据实时同步至PostgreSQL 前言: 为迎合工作需求有时候传送的数据保存在SQLServer中但由于工作需要需要保存到PostgreSQL中进行处理,本文主要通过在SQLSer ...

  9. Django分页组件——Paginator

    from django.core.paginator import Paginator #导入Paginator objects = ['john','paul','george','ringo',' ...

  10. Git 系列教程(1)- Git 简介

    前言 因为工作中目前要大量使用 Git,虽然之前已经会用了,但没有系统的总结过,现在来重新总结 概念篇会直接搬网上的教程,比如:菜鸟.廖雪峰.老张.中文版Git,就不再花时间自己总结过概念了 Git ...