Elasticsearch и .NET
-
20-12-2019 - |
Вопрос
Мы рассматриваем возможность перехода с Solr/Solr.net на Elasticsearch.Мы начали с ГНЕЗДО.У нас всего 4 документа в поисковом индексе.
private static void Main(string[] args)
{
var node = new Uri("http://localhost:9200");
var settings = new ConnectionSettings(
node, "my-application");
var client = new ElasticClient(settings);
var stopwatch = Stopwatch.StartNew();
var sr = client.Get<Movie>(1);
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
Приведенный выше код занимает ок.250 мс, в то время как тот же код с HttpClient
и JsonSerializer
занимает 30-45 мс.250 мс — слишком много времени для всего 4 документов.
Можно ли использовать NEST на новостном веб-сайте с высокой посещаемостью или вы рекомендуете HttpClient
+ JsonSerializer
комбо?Страница поиска была самой посещаемой страницей нашего сайта в 2013 году.
Заранее спасибо.
Решение
Чтобы NEST выполнил первый запрос, должны произойти две вещи.
Сериализатор Json (Json.net) в этом случае должен кэшировать тип, чтобы знать, как сериализовать и десериализовать объект, который вы отправляете туда и обратно.
У Nest есть собственный свободный язык для запросов, которые необходимо преобразовать из начальных типов, представляющих свободный язык запросов, и доставить в виде JSON в эластичный поиск.Эти типы документов также должны быть изучены сериализатором Json.
Для выполнения запроса необходимо запустить HTTP-клиент.
В настоящее время у меня есть более 4 миллионов документов в одном индексе, который я использую с NEST, и мои поиски от сервера до клиента через Интернет занимают 50-70 мс с использованием NEST.Как и у вас, однако, после холодного старта первый запрос идет медленно.
Другие советы
Я предлагаю вам использовать https://github.com/ServiceStack/ServiceStack.Text, самый быстрый сериализатор JSON для C#.
Для драйвера используйте низкоуровневый, http://nest.azurewebsites.net/elasticsearch-net/quick-start.html
ниже кода, который я начал писать, чтобы подробно регистрировать свои приложения и анализировать их.Еще предстоит поработать, но это может быть хорошим началом.
using System;
using System.Configuration;
using Elasticsearch.Net;
using Elasticsearch;
using Elasticsearch.Net.Connection;
using Elasticsearch.Net.ConnectionPool;
namespace Common {
/// <summary>
/// Elastic search. Singletone, open connection and thread safe to be open for all the time
/// the app is running, so we send ours logs to ealsticsearch to be analyzed, assychronly
/// See the fourth version;
/// http://csharpindepth.com/articles/general/singleton.aspx
/// </summary>
public sealed class ElasticSearch {
// our instance of ourself as a singleton
private static readonly ElasticSearch instance = new ElasticSearch();
ElasticsearchClient client;
string connectionString = ConfigurationManager.ConnectionStrings["Elasticsearch"].ConnectionString;
/// <summary>
/// Initializes a new instance of the <see cref="Common.ElasticSearch"/> class.
/// Follow this: http://nest.azurewebsites.net/elasticsearch-net/connecting.html
/// We use a ConnectionPool to make the connection fail-over, that means, if the
/// connection breaks, it reconnects automatically
/// </summary>
private ElasticSearch() {
var node = new Uri(connectionString);
var connectionPool = new SniffingConnectionPool(new[] { node });
var config = new ConnectionConfiguration(connectionPool);
client = new ElasticsearchClient(config); // exposed in this class
}
static ElasticSearch() {
}
/// <summary>
/// Gets the instance of our singleton class
/// </summary>
/// <value>The instance.</value>
public static ElasticSearch Instance {
get {
return instance;
}
}
/// <summary>
/// Log the specified module, id and json.
/// </summary>
/// <param name="type">Here the entity you want to save your log,
/// let's use it based on classes and StateMachines</param>
/// <param name="id">Identifier. alwayes the next</param>
/// <param name="json">Json.</param>
public void Log(string type, string id, string json) {
client.Index("mta_log", type, id, json);
}
}
}