Перезапустить одноэлементную службу в ASP.Net Core

У меня есть несколько сервисов, которые я внедряю с помощью DI в приложение ASP.Net Core. Эти сервисы используют пару доступных для записи объектов конфигурации, которые я также добавляю с помощью DI. Однако, поскольку эти службы должны быть одиночными, объект конфигурации передается только при запуске службы, поэтому любые изменения в нем не будут приняты. Поэтому мне нужно либо перезапустить эти синглтоны, либо каким-то образом передать им новый IOptionsSnapshot.

Чтобы уточнить, вот мой код:

Startup.cs:

//Inject service and config object
services.ConfigureWritable<DataSettings>(Configuration.GetSection("DataSettings"));
services.AddSingleton<IHostedService, DataService>();

DataService.cs:

public DataService(IOptionsSnapshot<DataSettings> data)                   
{
    //_options is used to configure the service
    this._options = data.Value;
}

DataController.cs:

public DataController(IWritableOptions<DataSettings> data)
{
    _data = data;
}

[HttpPost("conf/data/new")]
public void InsertData([FromBody] IEnumerable<ModuleSettings> newData)
{
    var data = _data.Value.Data.ToList();
    data.AddRange(newData.ToList());
    _data.Update(d => d.Data = data.ToArray());
}

Как видите, я настроил свою службу с помощью объекта конфигурации в Startup.cs. Затем я передаю объект конфигурации как своей службе, так и контроллеру, используемому для настройки службы. Интерфейс IWritableOptions является производным от IOptionsSnapshot и может использоваться для обратной записи изменений в appsettings.json. Все это работает, однако, когда я вношу изменения в свой объект конфигурации и обновляю appsettings.json, изменения не передаются в мою службу. Было бы излишним перезапускать все приложение, поэтому я ищу способ просто перезапустить эту одну службу или как-то установить в ней объект конфигурации. Я не могу раскрыть свойство _options службы, потому что эти службы настроены динамически, поэтому в фоновом режиме могут работать 2, 3 и т. Д.


person LeonidasFett    schedule 31.01.2018    source источник
comment
В Config и Options есть система уведомлений об изменениях, на которую стоит обратить внимание.   -  person Tratcher    schedule 31.01.2018


Ответы (1)


Некоторые идеи, которые могут помочь:

  1. Вы уверены, что ваша служба нуждается в том, чтобы быть одноэлементной? В большинстве случаев подобная служба доступа к данным этого не делает, и вместо этого может быть сделана Scoped (1 экземпляр на веб-запрос). Это устранило бы вашу проблему, если бы вы могли ее поддержать.

  2. Вместо передачи IOptionsSnapshot вы можете передать IOptions или какой-нибудь настраиваемый тип OptionsReader, который вы создадите, который будет активно считывать значение current из конфигурации через метод. Вызовите этот метод из своей одноэлементной службы, и вы сможете получить сведения о текущем соединении для любого данного вызова.

  3. Измените службу, чтобы она принимала сведения о подключении как часть сигнатуры метода. Не идеально, поскольку вам, вероятно, придется добавить его ко многим методам, но он достигнет вашей цели.

  4. Я не пробовал, но вы, вероятно, можете заменить (или удалить) одноэлементную службу в коллекции служб во время выполнения (после запуска). Если вы удалили его при каждом обновлении конфигурации, новое будет создано при следующем запросе. Вот связанный ответ, в котором показано, как это сделать из запуска: https://stackoverflow.com/a/42946802/13729

person ssmith    schedule 02.02.2018