使用HttpClient发送给LogStash的PUT请求失败,使用cURL发送时成功

时间:2019-04-10 11:55:28

标签: rest elasticsearch logstash elasticsearch-plugin

Here是我的logstash.conf文件。 (不直接在此处粘贴代码的道歉; StackOverflow不允许帖子超出特定的代码与文本比率。)

我的远程VM(也托管我的ElasticSearch和LogStash服务器)在端口8080上侦听。

在本地计算机上,我定期通过TCP将压缩的文件夹(包含JSON文档)发送到我的远程服务器,该服务器将数据接收到内存流中,解压缩文件夹,然后将内容发送到LogStash。 LogStash依次将数据转发到ElasticSearch。

我目前正在使用一些虚拟数据测试工作流程。

在我的远程服务器上,这是通过TCP接收数据的方法:

private static void ReceiveAndUnzipElasticSearchDocumentFolder(int numBytesExpectedToReceive)
{
    int numBytesLeftToReceive = numBytesExpectedToReceive;

    using (MemoryStream zippedFolderStream = new MemoryStream(new byte[numBytesExpectedToReceive]))
    {
        while (numBytesLeftToReceive > 0)
        {
            // Receive data in small packets
        }

        zippedFolderStream.Unzip(afterReadingEachDocument: LogStashDataSender.Send);
    }
}

以下是用于解压缩收到的文件夹的代码:

public static class StreamExtensions
{
    public static void Unzip(this Stream zippedElasticSearchDocumentFolderStream, Action<ElasticSearchJsonDocument> afterReadingEachDocument)
    {
        JsonSerializer jsonSerializer = new JsonSerializer();

        foreach (ZipArchiveEntry entry in new ZipArchive(zippedElasticSearchDocumentFolderStream).Entries)
        {
            using (JsonTextReader jsonReader = new JsonTextReader(new StreamReader(entry.Open())))
            {
                dynamic jsonObject = jsonSerializer.Deserialize<ExpandoObject>(jsonReader);

                string jsonIndexId = jsonObject.IndexId;
                string jsonDocumentId = jsonObject.DocumentId;

                afterReadingEachDocument(new ElasticSearchJsonDocument(jsonObject, jsonIndexId, jsonDocumentId));
            }
        }
    }
}

这是将数据发送到LogStash的方法:

public static async void Send(ElasticSearchJsonDocument document)
{
    HttpResponseMessage response = 
        await httpClient.PutAsJsonAsync(
            IsNullOrWhiteSpace(document.DocumentId) 
                ? $"{document.IndexId}" 
                : $"{document.IndexId}/{document.DocumentId}",
            document.JsonObject);

    try
    {
        response.EnsureSuccessStatusCode();
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);
    }

    Console.WriteLine($"{response.Content}");
}

httpClient方法中引用的public static async void Send(ElasticSearchJsonDocument document)是使用以下代码创建的:

private const string LogStashHostAddress = "http://127.0.0.1";
private const int LogStashPort = 31311;

httpClient = new HttpClient { BaseAddress = new Uri($"{LogStashHostAddress}:{LogStashPort}/") };
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

当我进入一个新的调试实例时,该程序运行平稳,但是对压缩文件夹中包含的每个文档执行await httpClient.PutAsJsonAsync后立即死掉了–从未命中response.EnsureSuccessStatusCode();Console.WriteLine(exception.Message);Console.WriteLine($"{response.Content}");都不是。

以下是ElasticSearchJsonDocument传递给public static async void Send(ElasticSearchJsonDocument document)方法的示例:

enter image description here

当我使用cURL运行相同的PUT请求时,Book索引已成功创建,然后我可以发起GET请求从ElasticSearch检索数据。

我的问题是:

  1. 为什么对接收到的压缩文件夹中的每个JSON文档执行await httpClient.PutAsJsonAsync(...)之后程序立即死亡(没有可见的异常消息)?
  2. 我应该进行哪些更改以确保我可以使用PUT实例向LogStash发出成功的HttpClient请求?

1 个答案:

答案 0 :(得分:0)

我从{p>更改了我的httpClient实例化代码

httpClient = new HttpClient { BaseAddress = new Uri($"{LogStashHostAddress}:{LogStashPort}/") };
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

然后我将await http.Client.PutAsJsonAsync(...)更改为

HttpResponseMessage response =                
    await httpClient.PutAsJsonAsync(
        IsNullOrWhiteSpace(document.DocumentId)
            ? $"{LogStashHostAddress}:{LogStashPort}/{document.IndexId}"
            : $"{LogStashHostAddress}:{LogStashPort}/{document.IndexId}/{document.DocumentId}",
        document.JsonObject);

response.EnsureSuccessStatusCode();

事实证明,BaseAddress中的HttpClient字段是extremely user-unfriendly,所以我决定不完全浪费它,而不是浪费更多的时间。