Вставьте EF DatabaseContext в пользовательский ScopedService

Мне кажется, что производительность внедренного EF внутри сервисной области действительно низкая.

Существует высокая вероятность того, что я неправильно использую EF в этом случае, но я не смог найти надлежащего описания / документации, как использовать EF в этом случае (внедрить его в пользовательский хостинг-сервис).

В EasyRabbit/startup.cs (ConfigureServices) зарегистрированы следующие сервисы:

// db
services.AddDbContext<ApplicationDbContext>(options =>
{
    options.UseSqlServer("Server=localhost; Database=RabbitTest; MultipleActiveResultSets=true; User ID=sa; Password=Admin1234");
});

// default REST Api
services.AddMvc();
// Configuration for Rabbit connector
services.Configure<RabbitConfig>(Configuration.GetSection("RabbitConfig"));
// Rabbit Connector
services.AddSingleton<RabbitConnector>();
// Subscriber which listens if some new message arrives
services.AddSingleton<IHostedService, GenericHostedSubscriber<CalculatorInputs>>();

// Every arival message is then processed in following scope
// ApplicationDbContext dbContext is injected into this RabbitSubscribers.Adder
services.AddScoped<IScopedProcessingService<CalculatorInputs>, RabbitSubscribers.Adder>();

Теперь, если я правильно понимаю, он должен автоматически создавать область контекста БД для каждой новой области RabbitSubscribeers.Adder.

Проблема в том, что таким образом он может потреблять / обрабатывать в среднем только около 50 сообщений в секунду.

Когда я комментирую все операции с db (AddAsync и SaveChangesAsync) из следующего кода, он может обрабатывать около 2000 сообщений в секунду, что хорошо, но без db для меня бесполезно:(

namespace EasyRabbit.RabbitSubscribers
{
    public class Adder : IScopedProcessingService<CalculatorInputs>
    {
        private ILogger<Adder> _logger;
        private ApplicationDbContext _db;

        public Adder(ApplicationDbContext dbContext, ILogger<Adder> logger)
        {
            _logger = logger;
            _db = dbContext;

        }

        public async Task HandleMessageAsync(CalculatorInputs message)
        {

            Console.WriteLine($"Calculator: [{message.FirstNumber}] + [{message.SecondNumber}] = {message.FirstNumber + message.SecondNumber}");
            await _db.Calculations.AddAsync(new Calculation()
            {
                FirstNumber = message.FirstNumber,
                SecondNumber = message.SecondNumber,
                Result = message.FirstNumber + message.SecondNumber
            });

            await _db.SaveChangesAsync();

        }
    }
}

Когда я попытался заменить EF на System.Data.SqlClient (следующий фрагмент кода, непосредственно используемый в Adder.cs), он мог обрабатывать в среднем 1100 сообщений в секунду. Но работать с БД, как это действительно неудобно:-/

public static class DB
{
    private static string _connectionString = "Server=localhost; Database=RabbitTest; MultipleActiveResultSets=true; User ID=sa; Password=Admin1234";


    public static void AddRecord(MyDBObject myDBObject)
    {
        using (SqlConnection con = new SqlConnection(_connectionString))
        {
            using (SqlCommand cmd = new SqlCommand("insert into test (FirstNumber, SecondNumber, Result) values (@FirstNumber, @SecondNumber, @Result)", con))
            {
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.AddWithValue("@FirstNumber", myDBObject.FirstNumber);
                cmd.Parameters.AddWithValue("@SecondNumber", myDBObject.SecondNumber);
                cmd.Parameters.AddWithValue("@Result", myDBObject.Result);
                con.Open();
                cmd.ExecuteNonQuery();
                con.Close();
            }

        }
    }
}

public class MyDBObject
{
    public int FirstNumber { get; set; }
    public int SecondNumber { get; set; }
    public int Result { get; set; }
}

Весь код можно найти на https://github.com/suchoss/uServiceChasis

Благодарю.

Действия по воспроизведению

  1. Клонировать текущий репозиторий с: https://github.com/suchoss/uServiceChasis
  2. Установите RabbitMQ с: https://www.rabbitmq.com/
  3. Установить MSSQL
  4. Измените соединитель на БД в EasyRabbit / startup.cs (строка 31)
  5. Перейдите в папку RandomNumberPairGenerator и выполните команду dotnet run на несколько секунд, затем вы можете отменить ее с помощью ctrl+c (она создает несколько сообщений в очереди RabbitMQ)
  6. Запустите проект EasyRabbit и посмотрите, сколько сообщений в секунду обрабатывается *. Если у вас установлено управление RabbitMQ, вы можете наблюдать за производительностью по http://localhost:15672/ (логин по умолчанию: guest; пароль: guest)

Отредактировано:

Вот текущие измеренные характеристики:

  1. EF асинхронный внутри adder.cs - 230/ с
  2. EF без асинхронности внутри adder.cs - 100/ с
  3. ADO.NET async - 1300/ с
  4. ADO.NET без асинхронности - 150/ с
  5. EF вставляет контекст асинхронно - 40/ с
  6. EF вставленный контекст без асинхронности - 65/ с

сценарии 1.,2.,3.,4. иметь adder.cs как синглтон

сценарии 5.,6. у них есть adder.cs в качестве сервиса

0 ответов

Другие вопросы по тегам