新闻通讯微服务使用.NETCORE,REDISJSON和AZURE
#dotnet #redis #microservices #redishackathon

Image description

介绍

在本文中,您将使用Redisjson,.Net Core和Azure创建基于微服务架构的新闻通讯服务。
您将使用Redisjson作为持久商店,以保持我们的数据与订阅有关。 Redisjson是Redis提供的基于NOSQL文档的高性能存储。
您将使用.NET Core创建REST API,该核心将提供围绕订阅并为订阅用户创建新闻通讯的CRUD操作。
您还将使用Azure创建无服务器功能来处理新闻通讯,并使用SendGrid电子邮件服务将其发送给所有用户。这将是教程上的全部端到头。

先决条件

  1. 您将使用RedisOmâ.NET库来处理Redis中的文档。对于您将使用.NET CORE 6。
  2. 编写.NET代码的IDE。 Visual Studio,VS Code或Rider,其中任何一个都可以工作。
  3. 存储队列和发送电子邮件的Azure帐户。您可以在此处创建一个免费的Azure帐户。
  4. Azure功能核心工具

新闻通讯微服务的设计

在本文中,您将设计一个新闻通讯微服务,该新闻通讯将使用户能够订阅或取消订阅新闻通讯,并允许新闻通讯的所有者在他们想要的时候发送电子邮件。
您将创建一个REST API,该API将提供从新闻通讯订阅/取消订阅的操作,并发送新闻通讯。为了发送新闻通讯,您将创建一个异步操作,您将在其中持续到队列上的新闻通讯信息(Azure Storage Queue),您将创建一个新闻通讯处理器,该新闻通讯处理器将从队列中选择新闻通讯项目,然后发送电子邮件至使用sendgrid订阅的成员。
在这里,最重要的是范围。您需要设计一些实体来存储与订阅和新闻通讯有关的数据。
以下是订阅实体,它将有助于我们存储与redis中订阅相关的数据。

string Id
string Email
DateTime SubscribedOn
bool IsSubscribed

下面是新闻通讯实体,它将有目的是使数据与新闻通讯有关,并且当用户要求创建新闻通讯时,它将在队列中排名。您不会存储此信息,因为它只是发送邮件。(保持设计简单)

List<string> Emails
string Subject
string Body

设计实体后,您将创建3个休息端点,以订阅,并订阅新闻通讯和发送新闻通讯。之后,您将创建一个Azure功能来处理新闻通讯,即发送电子邮件。
在下一节中,您将详细介绍所有步骤。让我们潜水:)

设置redis群集

使用此链接进行REDIS云的注册。他们提供200美元的免费积分以通过优惠券代码Tiger200开始。
注册并登录后。登录时,将要求您从Azure,Google Cloud,AWS中选择云提供商。选择您喜欢的任何一个,之后将为您创建免费订阅。
创建订阅后,还将为您创建一个数据库,该数据库具有REDISJSON,REDIS搜索,Redis Bloom,Redis Graph和Redis Limeseries的模块。对于我们的应用程序,您只需要Redis JSON和REDIS搜索。因此,您将删除现有的数据库。
为了删除,请单击订阅下选项左侧的数据库。您将看到为您创建的默认数据库。之后,单击数据库名称,您将降落在数据库配置页面上。向下滚动页面,您将在底部的危险区域看到删除选项。

Image description

之后,您需要创建一个新的数据库。为此,单击订阅选项。现在,在您的订阅下,没有数据库,您将获得一个选项新数据库按钮来创建数据库。单击该内容,您将获得为数据库设置名称的选项,您将获得为数据库设置的类型。在这里选择Redis而不是Redis堆栈,然后选择Redisjson和Redissearch。之后,单击激活,您的数据库将在几分钟内准备好使用。
准备好数据库后,将公共端点和密码值放在一般和安全部分的一个位置,因为您稍后将使用它来创建我们的连接字符串。

Image description

设置SendGrid和Storage -efeue的Azure帐户

注册并登录到您的Azure帐户后,转到Azure Portal,在顶部搜索栏中搜索“ SendGrid”,然后单击它。在这里,您将为Twilio Sendgrid SaaS(软件)创建资源。您将降落在资源创建页面上,您需要填写有关资源,计划名称等的一些详细信息。
为此资源提供名称,并选择“免费100 -1个月”的计划,因为这将是免费的,您每天将收到100封电子邮件,该计划足以容纳本教程。之后,单击“评论 +订阅”,您将登陆评论 +订阅选项卡,您可以在其中查看填写的详细信息。单击“订阅”按钮和Azure将为您创建SendGrid SaaS订阅(准备使用需要几分钟才能使用)。
准备就绪后,您需要配置SendGrid帐户,因此请单击“立即配置帐户”按钮。

Image description

单击“立即配置帐户”按钮后,您将被重定向到需要输入凭据的新选项卡(与Azure帐户相同的电子邮件),此后您将降落在SendGrid应用程序上您需要提供信息来设置您的SendGrid帐户。填写所有详细信息,然后单击“入门”。
执行上述所有步骤后,您将降落在SendGrid帐户的主页上,如下所示。

Image description

您需要获取一个API密钥,您将使用它来调用SendGrid API通过Azure功能发送电子邮件。为此,您需要单击“ SendGrid”页面左侧的设置选项,然后单击“ Actialion菜单”(上图中标记为蓝色检查)的API键选项。
之后,单击创建API键按钮。您将移至一个页面,在该页面上,您需要为API键提供详细信息,例如名称和API键的权限。
输入任何名称,然后为您的API密钥权限选择完整的访问权限。然后单击底部的创建和查看按钮。

Image description

sendgrid现在向您显示您的新API密钥。复制钥匙并将其保存在安全的地方,因为出于安全原因,您将无法再次访问密钥。最后,单击完成。
哇!您已经通过Azure成功设置了一个SendGrid帐户,并为您自己创建了一个API键,您将在以后使用。
同样,您需要创建一个Azure存储队列,并且可以按照此处提到的步骤进行相同的步骤。

设置.NET核心休息API

打开Visual Studio并创建.NET Core Web API项目。您可以选择.NET 6作为目标框架,并保持其余配置。单击创建项目后,Visual Studio将为您引导一个项目。
首先,您需要添加用于订阅的实体,该实体将用于建模Redis数据库中的文档。
以下是您将使用的实体:

[Document]
public partial class Subscription
{
[RedisIdField]
public string Id { get; set; }
[Indexed(Sortable = true)]
public string Email { get; set; }
[Indexed(Sortable = true)]
public DateTime SubscribedOn { get; set; }
[Searchable(Sortable = true)]
public bool IsSubscribed { get; set; }
}

之后,您需要为我们的新闻通讯服务添加REST端点,为此您将首先创建一个用于订阅的控制器。

[ApiController]
[Route("[controller]")]
public class SubscriptionController : ControllerBase
{
}

之后,您将在下方端点下创建

POST
/subscription
Body: Email 
---------------------------------------------------
DELETE
/subscription
Body: {Email}
---------------------------------------------------
POST
/InitializeStorage
---------------------------------------------------
POST
/newsletter
Body: {string Subject, string Body }

redisomâ.net库和Azure存储队列库安装

在添加休息端点之前,您需要添加RedisOmâ.net Nuget,我们将使用它来连接到REDIS数据库并在其上执行操作。
要安装redisomânet,您需要做的就是将redis.om nuget软件包添加到您的项目中。这可以通过运行
来完成

dotnet add package Redis.OM

同样,您需要添加Nuget,以使用Azure存储队列库,您将使用该库将消息推向以前创建的Azure排队。这可以通过在命令下方运行。

dotnet add package Azure.Storage.Queues

设置redis连接提供商依赖性
RedisOmâ.NET使用RedisconnectionProvider类来处理与Redis的连接,并提供可以与Redis交互的功能。要使用它,您需要通过使用.NET Core依赖注入将重新构成程序的实例注入您的应用程序。为此,您需要在program.cs文件中放置下面的代码。

builder.Services.AddSingleton(new RedisConnectionProvider(builder.Configuration["REDIS_CONNECTION_STRING"]));

您还需要在我们的appSettings.json文件中添加redis_connection_string。为了获得我们的连接字符串,您可以使用以下模式:
“ redis:// username:password@hostname:port/4”
用户名,密码和公共端点(主机)可以在数据库的“配置”选项卡下找到。在上面的模式中替换这些值,您将获得连接字符串,需要将其放在AppSettings.json文件下。
此后,提供商现在将在您的控制器/服务中使用。

设置Azure队列客户端依赖性
您需要以相同的方式注册Azure存储队列客户端。您需要在program.cs文件中放置以下代码才能注册队列客户端。

builder.Services.AddAzureClients(builder =>
{
builder.AddClient<QueueClient, QueueClientOptions>((options, _, _) =>
{
options.MessageEncoding = QueueMessageEncoding.Base64;
var credential = new DefaultAzureCredential();
var queueUri = new Uri(queueURI);
return new QueueClient(queueUri, credential, options);
});
});

休息端点

前3个终点是用于在订阅和新闻通讯资源上执行CRUD操作,最后一个是出于特定目的,即为我们在Redis数据库上创建订阅实体的索引,您在上一步中已在Redis Cloud上创建了索引。
1。创建订阅端点
您需要提供一个端点,将电子邮件地址作为创建订阅的输入。
您将创建一个帖子端点,该端点将采用您需要通过电子邮件的sisscriptrequest,这将在邮政请求的正文中传递。
以下代码将通过电子邮件,订阅日期和ISSUBSCRIBED标志设置为True。

[HttpPost]
public async Task<IActionResult> Subscribe([FromBody]SubscribeRequest subscribeRequest)
{
if (string.IsNullOrWhiteSpace(subscribeRequest.Email))
{
return BadRequest();
}
Subscription subscription = new Subscription();
subscription.Email = subscribeRequest.Email;
subscription.IsSubscribed = true;
subscription.SubscribedOn = DateTime.UtcNow;
var subscriptionCollection = _provider.RedisCollection<Subscription
();
await subscriptionCollection.InsertAsync(subscription);
return Created("/subscription", subscription.Id);
}

2。删除订阅(退订)
您需要提供一个端点,使用户可以退订新闻通讯。
您将创建一个删除端点,该端点将取消订阅,您将在其中通过电子邮件。这将通过删除请求的主体传递。通过此请求,如果我们系统中存在电子邮件的用户,则将将ISSUBSCRIP的标志设置为False。以下是相同的代码

[HttpDelete]
public async Task<IActionResult> UnSubscribe([FromBody] UnSubscribeRequest unSubscribeRequest)
{
if (string.IsNullOrWhiteSpace(unSubscribeRequest.Email))
{
return BadRequest();
}
var subscriptionCollection = _provider.RedisCollection<Subscription>();
var existingSubscription = await subscriptionCollection.FirstOrDefaultAsync(x => x.Email == unSubscribeRequest.Email);
if(existingSubscription == null)
{
return NotFound();
}
existingSubscription.IsSubscribed = false;
_provider.Connection.Set(existingSubscription);
return Ok("/unsubscribed");
}

3。创建新闻通讯
接下来,您将创建一个端点,该端点可用于由所有者创建新闻通讯,并将其发布在Azure队列上,后来将由新闻通讯处理器接收来处理。
您将创建一个帖子端点,该端点将采用新闻通讯的新闻通讯,您需要通过新闻通讯的主题和正文。该数据将通过Post Postelect的主体传递。
下面的代码将根据请求和主体创建新闻通讯,并从订阅的订阅中获取电子邮件。创建新闻通讯后,您将在Azure队列上发布新闻通讯处理器服务的Azure队列。

[HttpPost]
public async Task<IActionResult> SendNewsLetter(NewsletterRequest newsletterRequest)
{
var subscriptionCollection = _provider.RedisCollection<Subscription>();
var existingSubscription = await subscriptionCollection.ToListAsync();
if (existingSubscription != null && existingSubscription.Count > 0)
{
Newsletter newsletter = new Newsletter();
newsletter.Subject = newsletterRequest.Subject;
newsletter.Body = newsletterRequest.Body;
newsletter.Emails = existingSubscription.Where(x => x.IsSubscribed).Select(x => x.Email).ToList();
string serializedNewsLetterObject =
JsonConvert.SerializeObject(newsletter);
await _queueClient.SendMessageAsync(serializedNewsLetterObject);
}
return Accepted();
}

4。初始化存储
有了实体,下一步是为您创建的订阅模型创建REDIS数据库中的索引。此操作只需要一次完成一次,因此您要为此创建一个端点端点,并仅运行一次。
下面的代码将使用Redis Connection String创建RedisconnectionProvider创建RedisnectionProvider,然后在Redis中创建类型订阅的索引。如果成功,它将返回201(创建)否则会有一些例外。

[HttpPost("/InitializeStorage")]
public async Task<IActionResult> InitializeStorage()
{
var provider = new RedisConnectionProvider(_configuration["REDIS_CONNECTION_STRING"]);
var isSuccess = await provider.Connection.CreateIndexAsync(typeof(Subscription));
return Created("Storage", null);
}

为新闻通讯处理设置Azure功能

完成了REST端点后,您将下一个致力于创建Azure功能,该功能将处理在Azure队列上发布的新闻通讯并将电子邮件发送给订户。
Azure函数是云本机设计的无服务器体系结构,它允许在无需配置或维护服务器基础结构或配置的情况下部署和执行一块代码。简而言之,您可以将Azure函数视为可以直接在云中执行代码的方法,而不必担心服务器是什么,其OS,运行时等。您只需要提供代码并指定您的编程平台正在编写诸如.net,Java,PHP,GO等的代码。与基础结构相关的所有内容都将由云服务提供商照顾。有关更多详细信息,请在此处阅读有关Azure功能的文档。
现在,您将使用Azure Core命令行工具创建一个Azure函数,您已将其作为先决条件的一部分安装。
打开命令提示壳并运行下面的命令:

func init NewsletterProcessor --dotnet

此命令将创建一个新的文件夹新闻通讯处理器,并为Azure函数生成.NET项目。通过运行以下命令来导航到新文件夹:

cd NewsletterProcessor

该项目尚未包含任何功能。运行以下命令以生成基于队列触发的Azure函数。

func new -name NewsletterQueueProcessor -template "Queue trigger"

此命令将创建一个名为新闻通讯的c#函数。
您需要更新该功能以处理新闻通讯。为此,您将使用您从队列收到的新闻通讯项目创建SendGrid消息,此SendGrid消息将为您发送电子邮件。
以下是相同的代码。

public class NewsletterQueueProcessor
{
[FunctionName("NewsletterQueueProcessor")]
[return: SendGrid(ApiKey = "SENDGRID_API_KEY")]
public SendGridMessage Run([QueueTrigger("NewsletterQueue", Connection = "NewsletterQueueURI")] Newsletter newsletter, ILogger log, ExecutionContext context)
{
log.LogInformation($"C# Queue trigger function processed at: {DateTime.UtcNow}");
var config = GetConfiguration(context);
SendGridMessage message = CreateSendGridEmailMessage(newsletter, config);
return message;
}
private IConfiguration GetConfiguration(ExecutionContext context){
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
return config;
}
private SendGridMessage CreateSendGridEmailMessage(Newsletter newsletter, IConfiguration config)
{
var msg = new SendGridMessage()
{
From = new EmailAddress(config["FromEmail"], config["FromName"]),
Subject = newsletter.Subject,
PlainTextContent = newsletter.Body
};
msg.AddTo(config["FromEmail"]);
List<EmailAddress> emailAddresses = new List<EmailAddress>();
foreach (var email in newsletter.Emails)
{
emailAddresses.Add(new EmailAddress(email));
}
msg.AddBccs(emailAddresses);
return msg;
}
}

添加REDIS数据库和Azure队列的连接字符串

为了与REDIS数据库和Azure队列进行交互,您需要在我们的API项目中为Azure队列指定REDIS数据库和连接字符串的连接字符串。为此,您需要在AppSettings.json文件中添加键redis_connection_string和azure_storage_queue_uri的连接字符串值。

同样,您需要添加sendgrid api键和azure队列
Azure功能项目中的ConnectInsTring。为此,您需要在local.settings.json
中添加键sendgrid_api_key和newsletterqueuuri的值 设置这些配置值后,您将能够在本地运行服务。

结论

在本文中,您可以了解如何将Redisjson与.NET Core一起使用Azure函数。
如果您在本地设置该项目时面临任何问题,您可以在此处通过电子邮件与我联系:rajivsn007@gmail.com
如果您在此新闻通讯微服务方面对我有任何反馈,则可以在my GitHub repo本身上分享。直到继续学习和编码:)