更好的练习将消息发送到使用无服务器C#funcion的Azure事件中心
这是我的代码...
namespaceMyNamespace
{
public class Ping
{
private readonly ILogger<Ping2> _logger;
public Ping2(ILogger<Ping2> log)
{
_logger = log;
}
[FunctionName("Ping2")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "v1/Ping")] HttpRequest req)
{
_logger.LogInformation("Processing: Ping");
if (req.Query["agendaId"] == Microsoft.Extensions.Primitives.StringValues.Empty)
{
return new BadRequestResult();
}
Guid agendaId = Guid.Parse(req.Query["agendaId"]);
string dataTag = "ZZZZ";
string hubName = "myHub";
EventHubProducerClient producerClient;
producerClient = new EventHubProducerClient(connString, hubName);
using EventDataBatch eventBatch = await producerClient.CreateBatchAsync();
MensagemPing data = new MensagemPing() {
ID = Guid.NewGuid(),
agendaId = agendaId,
dataTag = dataTag,
timestamp = DateTime.Now
};
string jsonString = JsonSerializer.Serialize(data);
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes(jsonString)));
await producerClient.SendAsync(eventBatch);
return new OkResult();
}
}
}
我找不到有关实现此问题的最佳方法的文档。只是为了开始,我将永远不需要分批发送消息。我发现了许多有关如何向中心发送一条消息的示例,但是在大多数情况下,是弃用示例或使用经典的ASP.NET应用程序。
另外,这个端点要在本地执行一秒钟,尤其是因为此片段在这里需要超过1秒钟:
EventHubProducerClient producerClient;
producerClient = new EventHubProducerClient(connString, hubName);
using EventDataBatch eventBatch = await producerClient.CreateBatchAsync();
MensagemPing data = new MensagemPing() {
ID = Guid.NewGuid(),
agendaId = agendaId,
dataTag = dataTag,
timestamp = DateTime.Now
};
string jsonString = JsonSerializer.Serialize(data);
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes(jsonString)));
我坚信这不是消费事件中心的最佳实践。也许有人可以给我一些好的榜样,或者给我一个很好的历史记录,如何改善它并更快地保持它?
This is my code...
namespaceMyNamespace
{
public class Ping
{
private readonly ILogger<Ping2> _logger;
public Ping2(ILogger<Ping2> log)
{
_logger = log;
}
[FunctionName("Ping2")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "v1/Ping")] HttpRequest req)
{
_logger.LogInformation("Processing: Ping");
if (req.Query["agendaId"] == Microsoft.Extensions.Primitives.StringValues.Empty)
{
return new BadRequestResult();
}
Guid agendaId = Guid.Parse(req.Query["agendaId"]);
string dataTag = "ZZZZ";
string hubName = "myHub";
EventHubProducerClient producerClient;
producerClient = new EventHubProducerClient(connString, hubName);
using EventDataBatch eventBatch = await producerClient.CreateBatchAsync();
MensagemPing data = new MensagemPing() {
ID = Guid.NewGuid(),
agendaId = agendaId,
dataTag = dataTag,
timestamp = DateTime.Now
};
string jsonString = JsonSerializer.Serialize(data);
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes(jsonString)));
await producerClient.SendAsync(eventBatch);
return new OkResult();
}
}
}
I can't find much documentation about the best way to implemment this. Just to start, I will never had a need to send a message in Batch. I found many examples about how to send a single message to the hub, but in mostly case, are deprecated examples or using classic asp.net application.
Also, this endpoint is taking one and a half second to be executed locally, specially because this snippet here take more than 1 second:
EventHubProducerClient producerClient;
producerClient = new EventHubProducerClient(connString, hubName);
using EventDataBatch eventBatch = await producerClient.CreateBatchAsync();
MensagemPing data = new MensagemPing() {
ID = Guid.NewGuid(),
agendaId = agendaId,
dataTag = dataTag,
timestamp = DateTime.Now
};
string jsonString = JsonSerializer.Serialize(data);
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes(jsonString)));
I am pretty convinced that this is not the best practice to consume event hubs. Maybe someone can give me some good example or maybe give me good hists about how to improve it and keep it more faster ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在这种情况下,由于您使用的是Azure功能,因此您可能需要考虑使用事件集线器输出输出绑定而不是直接使用客户端库。好处是它为您管理活动中心客户,包括一生和发送模式。
如果您决定直接直接使用客户端库,我会提出一些建议:
生产者旨在长期寿命;我强烈建议通过通过 di 使用 microsoft.extensions.azure library (precepable)或通过将其作为
static
类成员创建。如果您选择继续在功能主体中创建生产商,则需要关闭或处置它。否则,它拥有的连接将保持打开状态,直到约20分钟后闲置。除非您的流量确实非常低,否则这最终会导致主机上的插座耗尽。
为单个事件创建明确的批次并没有太大的好处。 I'd suggest using the
没有影响力,但是如果您想简化一点,则有一个
EventData
接受字符串的构造函数过载;无需手动执行编码:如果您要处理更高的呼叫量,则考虑使用 eventHubBufferedProducerClient ,因为它管理批处理并隐含地发送以尝试尝试并最大化吞吐量。也就是说,在功能上下文中使用很尴尬,需要在功能启动中进行更多的手动配置,以便正确地管理其寿命并确保在清理时冲洗事件。除非您在单个事件上看到瓶颈,否则这可能是不值得的,但是有一个端到端样本在ASP.NET主机中使用它,这与功能高度相似。
In this scenario, since you're using Azure Functions, you may want to consider using the Event Hubs output binding rather than using the client library directly. The benefit is that it manages the Event Hubs clients for you, including lifetimes and sending patterns.
If you decide to continue to use the client library directly, there are a few suggestions that I'd make:
The producer is intended to be long-lived; I'd strongly suggest creating it as a singleton, either by registering it via DI using the Microsoft.Extensions.Azure library (preferable) or by creating it as a
static
member of the class.If you choose to continue creating the producer in the body of the Function, you'll need to close or dispose it. Otherwise, the connection that it owns will be left open until it idles out after ~20 minutes. This will eventually cause socket exhaustion on the host unless your traffic is really, really low.
Creating an explicit batch for a single event doesn't offer much benefit. I'd suggest using the SendAsync overload that accepts an enumerable instead. For example:
Not impactful, but if you'd like to simplify a bit, there's a constructor overload for
EventData
that accepts a string; no need to manually perform the encoding:If you're dealing with a higher call volume, it may be helpful to consider using the EventHubBufferedProducerClient, as it manages the building of batches and sends implicitly to try and maximize throughput. That said, using in a Functions context is awkward and requires more manual configuration in the Function startup in order to manage its lifetime properly and ensure events are flushed at cleanup. It's probably not worth it unless you're seeing a bottleneck on the single event sends, but there's an end-to-end sample that illustrates using it in an ASP.NET host, which is highly similar to Functions.