Проблемы с развертыванием проекта Service Fabric с помощью Owin в Azure Service Fabric Cluster
Я работаю над проектом Service Fabric с Owin, и у меня возникают проблемы с его развертыванием в облаке. Я искал других с такой же проблемой, но нашел только ответ, говорящий о том, что ошибка в кластере указывает, где в коде происходит ошибка. Я следовал учебному руководству Microsoft о том, как написать метод, который терпит неудачу, но безуспешно. Я могу запустить проект на Localhost напрямую из Visual Studio, но проблема начинается, когда я развертываю его в кластере Service Fabric в Azure. У меня работает кластер из 5 узлов, и при развертывании на нем он начинает выдавать предупреждения через 2 минуты, а ошибки - через 5 минут. статус приложения "встроенный". Изображение предупреждения и Изображение ошибки.
У меня есть две службы, и ошибка из моего кластера дает ошибку в этих двух методах (один и тот же метод в каждой службе (OpenAsync)):
public Task<string> OpenAsync(CancellationToken cancellationToken)
{
var serviceEndpoint =
_parameters
.CodePackageActivationContext
.GetEndpoint("ServiceEndpoint");
var port = serviceEndpoint.Port;
var root =
String.IsNullOrWhiteSpace(_appRoot)
? String.Empty
: _appRoot.TrimEnd('/') + '/';
_listeningAddress = String.Format(
CultureInfo.InvariantCulture,
"http://+:{0}/{1}",
port,
root
);
_serverHandle = WebApp.Start(
_listeningAddress,
appBuilder => _startup.Configuration(appBuilder)
);
var publishAddress = _listeningAddress.Replace(
"+",
FabricRuntime.GetNodeContext().IPAddressOrFQDN
);
ServiceEventSource.Current.Message("Listening on {0}", publishAddress);
return Task.FromResult(publishAddress);
}
ошибка из кластера говорит об ошибке в этом разделе:
_serverHandle = WebApp.Start(
_listeningAddress,
appBuilder => _startup.Configuration(appBuilder)
);
другой метод (из другого сервиса):
public Task<string> OpenAsync(CancellationToken cancellationToken)
{
var serviceEndpoint =
_parameters
.CodePackageActivationContext
.GetEndpoint("ServiceEndpoint");
var port = serviceEndpoint.Port;
var root =
String.IsNullOrWhiteSpace(_appRoot)
? String.Empty
: _appRoot.TrimEnd('/') + '/';
_listeningAddress = String.Format(
CultureInfo.InvariantCulture,
"http://+:{0}/{1}",
port,
root
);
try
{
_serverHandle = WebApp.Start(
_listeningAddress,
appBuilder => _startup.Configuration(appBuilder)
);
}
catch (Exception e)
{
Console.WriteLine(e);
throw e;
}
var publishAddress = _listeningAddress.Replace(
"+",
FabricRuntime.GetNodeContext().IPAddressOrFQDN
);
ServiceEventSource.Current.Message("Listening on {0}", publishAddress);
return Task.FromResult(publishAddress);
}
ошибка из кластера говорит об ошибке в этом разделе:
try
{
_serverHandle = WebApp.Start(
_listeningAddress,
appBuilder => _startup.Configuration(appBuilder)
);
}
catch (Exception e)
{
Console.WriteLine(e);
throw e;
}
Мои стартап классы:
public void Configuration(IAppBuilder appBuilder)
{
var corsAttr = new EnableCorsAttribute(origins: "*", headers: "*", methods: "*");
var config = new HttpConfiguration();
config.WithWindsorSetup();
config.WithJsonSetup();
config.MapHttpAttributeRoutes(); //Enable Attribute-routing
config.WithSwaggerSetup();
config.EnsureInitialized();
config.EnableCors(corsAttr);
appBuilder.UseWebApi(config);
}
и где я создаю новый OwenCommunicationListener:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[] {
new ServiceInstanceListener(initParams => new OwinCommunicationListener("", new Startup.Startup(), initParams))
};
}
Мне бы очень хотелось иметь возможность развернуть его в кластере Azure Service Fabric без каких-либо ошибок. Хорошего дня и спасибо за помощь.
2 ответа
Проблема решена. Я отредактировал этот код:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return Context.CodePackageActivationContext.GetEndpoints()
.Where(endpoint => endpoint.Protocol.Equals(EndpointProtocol.Http) || endpoint.Protocol.Equals(EndpointProtocol.Https))
.Select(endpoint => new ServiceInstanceListener(serviceContext => new OwinCommunicationListener("", new Startup.Startup(), serviceContext)));
//return new[] {
// new ServiceInstanceListener(initParams => new OwinCommunicationListener("", new Startup.Startup(), initParams))
//};
}
Вам нужно написать свой собственный класс, который настраивает маршрутизацию и конфигурацию http для прослушивателя Owin. Вот класс, который я использую для настройки маршрутизации, попробуйте с ним:
/// <summary>
/// This is the startup class that configure the routing and http configuration for Owin listener.
/// </summary>
public static class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public static void ConfigureApp (IAppBuilder appBuilder)
{
appBuilder.UseCors(CorsOptions.AllowAll);
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
config.Formatters.Remove(config.Formatters.XmlFormatter);
appBuilder.UseWebApi(config);
}
}
передать этот класс как действие экземпляру, в котором вы создаете экземпляр прослушивателя OwinCommunication. Вот мой код
endpoints.Select(endpoint => new ServiceInstanceListener(
serviceContext => new OwinCommunicationListener(Startup.ConfigureApp, serviceContext,
null, endpoint), endpoint));
Этот подход работает для меня. Попробуйте с этим, надеюсь, это будет работать и для вас