我正在尝试使用Pluralsight课程(See here)和Microsoft文档(here)学习Microsft Azure服务结构,但遇到异常 FabricServiceNotFoundException
请参阅codbase-请参见代码库-Here
如果有人不想下载整个解决方案,我也会在这里放置源代码的一些地方。
问题 我目前面临的问题是无状态服务(ECommerce.API)和有状态服务(Ecommerce.ProductCatalog)之间的交互。 ECommerce.API调用Ecommerce.ProductCatalog来显示产品。
相关文件
Ecommerce.ProductCatalog-> ProductCatalog.cs
using System;
using System.Collections.Generic;
using System.Fabric;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ECommerce.ProductCatalog.Model;
using Microsoft.ServiceFabric.Data.Collections;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Remoting;
using Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;
using ECommerceProductCatalog.Common;
namespace ECommerce.ProductCatalog
{
/// <summary>
/// An instance of this class is created for each service replica by the Service Fabric runtime.
/// </summary>
internal sealed class ProductCatalog : StatefulService, IProductCatalogService
{
private IProductRepository _repo;
public ProductCatalog(StatefulServiceContext context)
: base(context)
{ }
public async Task AddProduct(Product product)
{
await _repo.AddProduct(product);
}
public async Task<IEnumerable<Product>> GetAllProducts()
{
return await _repo.GetAllProducts();
}
/// <summary>
/// Optional override to create listeners (e.g., HTTP, Service Remoting, WCF, etc.) for this service replica to handle client or user requests.
/// </summary>
/// <remarks>
/// For more information on service communication, see https://aka.ms/servicefabricservicecommunication
/// </remarks>
/// <returns>A collection of listeners.</returns>
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new[]
{
new ServiceReplicaListener((context) =>
{
return new FabricTransportServiceRemotingListener(context, this, serializationProvider: new CustomDataContractProvider());
})
};
}
/// <summary>
/// This is the main entry point for your service replica.
/// This method executes when this replica of your service becomes primary and has write status.
/// </summary>
/// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param>
protected override async Task RunAsync(CancellationToken cancellationToken)
{
_repo = new ServiceFabricProductRepository(this.StateManager);
var product1 = new Product
{
Id = Guid.NewGuid(),
Name = "Dell Monitor",
Description = "Computer Monitor",
Price = 500,
Availability = 100
};
var product2 = new Product
{
Id = Guid.NewGuid(),
Name = "Surface Book",
Description = "Microsoft's Latest Laptop, i7 CPU, 1Tb SSD",
Price = 2200,
Availability = 15
};
var product3 = new Product
{
Id = Guid.NewGuid(),
Name = "Arc Touch Mouse",
Description = "Computer Mouse, bluetooth, requires 2 AAA batteries",
Price = 60,
Availability = 30
};
await _repo.AddProduct(product1);
await _repo.AddProduct(product2);
await _repo.AddProduct(product3);
IEnumerable<Product> all = await _repo.GetAllProducts();
}
}
}
Ecommerce.ProductCatalog-> ProductCatalog.cs
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.ServiceFabric.Services.Runtime;
using Microsoft.ServiceFabric.Services.Remoting.V2;
using ECommerceProductCatalog;
using ECommerce.ProductCatalog;
namespace Ecommerce.ProductCatalog
{
internal static class Program
{
/// <summary>
/// This is the entry point of the service host process.
/// </summary>
private static void Main()
{
try
{
// The ServiceManifest.XML file defines one or more service type names.
// Registering a service maps a service type name to a .NET type.
// When Service Fabric creates an instance of this service type,
// an instance of the class is created in this host process.
ServiceRuntime.RegisterServiceAsync("ProductCatalogType",
context => new ECommerce.ProductCatalog.ProductCatalog(context)).GetAwaiter().GetResult();
ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(ECommerce.ProductCatalog.ProductCatalog).Name);
// Prevents this host process from terminating so services keep running.
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
throw;
}
}
}
}
Ecommerce.ProductCatalog-> ServiceManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="Ecommerce.ProductCatalogPkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatefulServiceType ServiceTypeName="ProductCatalogType" HasPersistedState="true" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>Ecommerce.ProductCatalog.exe</Program>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="ServiceEndpoint" />
<!-- This endpoint is used by the replicator for replicating the state of your service.
This endpoint is configured through a ReplicatorSettings config section in the Settings.xml
file under the ConfigPackage. -->
<Endpoint Name="ReplicatorEndpoint" />
</Endpoints>
</Resources>
</ServiceManifest>
ECommerce.API-> ProductController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using ECommerce.API.Model;
using ECommerce.ProductCatalog.Model;
using Microsoft.ServiceFabric.Services.Remoting.Client;
using Microsoft.ServiceFabric.Services.Client;
using ECommerce.ProductCatalog.Model;
namespace ECommerce.API.Controllers
{
[Route("api/[controller]")]
public class ProductsController : Controller
{
private readonly IProductCatalogService _catalogService;
public ProductsController()
{
_catalogService = ServiceProxy.Create<IProductCatalogService>(
new Uri("fabric:/ECommerce/ProductCatalog"),
new ServicePartitionKey(0));
}
[HttpGet]
public async Task<IEnumerable<ApiProduct>> Get()
{
IEnumerable<Product> allProducts = await _catalogService.GetAllProducts();
return allProducts.Select(p => new ApiProduct
{
Id = p.Id,
Name = p.Name,
Description = p.Description,
Price = p.Price,
IsAvailable = p.Availability > 0
});
//return new[] { new ApiProduct() { Id = Guid.NewGuid(), Description = "fake" } };
}
[HttpPost]
public async Task Post([FromBody] ApiProduct product)
{
var newProduct = new Product()
{
Id = Guid.NewGuid(),
Name = product.Name,
Description = product.Description,
Price = product.Price,
Availability = 100
};
await _catalogService.AddProduct(newProduct);
}
}
}
ECommerce.API-> Program.cs
using Microsoft.ServiceFabric.Services.Runtime;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ECommerce.API
{
internal static class Program
{
/// <summary>
/// This is the entry point of the service host process.
/// </summary>
private static void Main()
{
try
{
// The ServiceManifest.XML file defines one or more service type names.
// Registering a service maps a service type name to a .NET type.
// When Service Fabric creates an instance of this service type,
// an instance of the class is created in this host process.
ServiceRuntime.RegisterServiceAsync("ECommerce.APIType",
context => new API(context)).GetAwaiter().GetResult();
ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(API).Name);
// Prevents this host process from terminating so services keeps running.
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
throw;
}
}
}
}
ApplicationManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="EcommerceType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="ECommerce.API_ASPNETCORE_ENVIRONMENT" DefaultValue="" />
<Parameter Name="ECommerce.API_InstanceCount" DefaultValue="-1" />
</Parameters>
<!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion
should match the Name and Version attributes of the ServiceManifest element defined in the
ServiceManifest.xml file. -->
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="ECommerce.APIPkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
<EnvironmentOverrides CodePackageRef="code">
<EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value="[ECommerce.API_ASPNETCORE_ENVIRONMENT]" />
</EnvironmentOverrides>
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="Ecommerce.ProductCatalogPkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<DefaultServices>
<!-- The section below creates instances of service types, when an instance of this
application type is created. You can also create one or more instances of service type using the
ServiceFabric PowerShell module.
The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
<Service Name="ECommerce.API" ServicePackageActivationMode="ExclusiveProcess">
<StatelessService ServiceTypeName="ECommerce.APIType" InstanceCount="[ECommerce.API_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
调查
答案 0 :(得分:0)
在ProductController.cs文件中,从以下位置更改URI:
new Uri("fabric:/ECommerce/ProductCatalog")
收件人:
new Uri("fabric:/ECommerce/ECommerce.ProductCatalog")