.net 下集成steeltoe进行微服务客户端的注册与发现均需要使用Autofac依赖注入方式进行,且MVC,WebAPI,webForm三种项目类型所需要依赖扩展库都不一样,经过两周的踩坑,现在做个粗浅的总结吧!
以下是steeltoe官方文档给出的参考:
App Type | Package | Description |
---|---|---|
Console/ASP.NET 4.x | Steeltoe.Discovery.EurekaBase |
Base functionality. No dependency injection. |
ASP.NET Core | Steeltoe.Discovery.ClientCore |
Includes base. Adds ASP.NET Core dependency injection. |
ASP.NET 4.x with Autofac | Steeltoe.Discovery.ClientAutofac |
Includes base. Adds Autofac dependency injection. |
App Type | Package | Description |
---|---|---|
Console/ASP.NET 4.x | Pivotal.Discovery.EurekaBase |
Base functionality. No dependency injection. |
ASP.NET Core | Pivotal.Discovery.ClientCore |
Includes base. Adds ASP.NET Core dependency injection. |
ASP.NET 4.x with Autofac | Pivotal.Discovery.ClientAutofac |
Includes base. Adds Autofac dependency injection. |
经过两周的各自尝试,基于Framework4.5.2+的MVC,WebAPI,webForm等项目基本都是用Autofac方式进行服务注册和调用方法的引用,所以所需要引入的扩展库基本都是以Autofac结尾,比如上面的Steeltoe.Discovery.ClientAutofac和Pivotal.Discovery.ClientAutofac。
另外我们还需要用到的类库包括:
Steeltoe.Common.Autofac
这个类库包含了服务发现与调用的方法。
三种类型的项目目录结构是不同的,MVC与WebAPI都是有ApiController接口的,可以自己构建controller集成接口,然后直接用Autofac的依赖注入方式进行微服务调用方法的实现,代码可参考如下:
public class ValuesController : ApiController { private readonly DiscoveryHttpClientHandler _handler; public ValuesController(IDiscoveryClient client, ILoggerFactory logFactory)//这里就是注入依赖了 { _handler = new DiscoveryHttpClientHandler(client); } // GET api/values public async Task<string> Get() { var client = new HttpClient(_handler, false); return await client.GetStringAsync("http://java-server/hi?name=demo"); } // GET api/values/5 public string Get(int id) { String re = id.ToString; return re; } // POST api/values public void Post([FromBody]string value) { } // PUT api/values/5 public void Put(int id, [FromBody]string value) { } // DELETE api/values/5 public void Delete(int id) { } }
那么webForm怎么调用微服务的方法呢?这就需要我们自己写一个服务类,在类中实现自定义接口和用依赖注入的方式对steeltoe提供的方法调用,然后在Page里依赖注入自己的这个类了。参考代码:
自定义服务接口类IFetchService.cs:
public interface IFetchService { Task<string> RandomFortuneAsync(); }
自定义服务类并完成steeltoe接口方法的依赖注入与实现FetchService.cs:
public class FetchService : IFetchService { DiscoveryHttpClientHandler _handler; private const string RANDOM_FORTUNE_URL = "http://java-service/hi?name=tian"; private ILogger<FetchService> _logger; public FetchService(IDiscoveryClient client, ILoggerFactory logFactory = null) { _handler = new DiscoveryHttpClientHandler(client); _logger = logFactory?.CreateLogger<FetchServise>(); } public async Task<string> RandomFortuneAsync() { _logger?.LogInformation("RandomFortuneAsync"); var client = GetClient(); return await client.GetStringAsync(RANDOM_FORTUNE_URL); } private HttpClient GetClient() { var client = new HttpClient(_handler, false); return client; } }
接下来,最重要的步骤,在程序全局文件Global.asax中进行依赖注入的配置,这里引用到的Autofac扩展库也是有区别:
MVC直接引用Autofac即可
WebAPI引用的是Autofac.WebApi2
webForm引用的是Autofac.Web
这里主要写下 webForm的配置代码:
public class Global : System.Web.HttpApplication, IContainerProviderAccessor { // 持有应用程序容器的提供程序 static IContainerProvider _containerProvider; //将被`Autofac HttpModules`用来解析和注入依赖关系的实例属性。 public IContainerProvider ContainerProvider { get { return _containerProvider; } } protected void Application_Start(object sender, EventArgs e) { ApplicationConfig.RegisterConfig("development"); //var config = GlobalConfiguration.Configuration; var builder = new ContainerBuilder(); // Add Microsoft Options to container builder.RegisterOptions(); // Add Microsoft Logging to container builder.RegisterLogging(ApplicationConfig.Configuration); // Add Console logger to container builder.RegisterConsoleLogging(); //// Register all the controllers with Autofac builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly()); // Register IDiscoveryClient, etc. builder.RegisterDiscoveryClient(ApplicationConfig.Configuration); // Register FortuneService builder.RegisterType<FetchServise>().As<IFetchServise>(); //builder.RegisterWebApiModelBinderProvider(); // Create the Autofac container var container = builder.Build(); _containerProvider = new ContainerProvider(container); //config.DependencyResolver = new AutofacWebApiDependencyResolver(container); // Get a logger from container //var logger = container.Resolve<ILogger<WebApiApplication>>(); //logger.LogInformation("Finished container build, starting background services"); // Start the Discovery client background thread container.StartDiscoveryClient(); //logger.LogInformation("Finished starting background services"); } protected void Session_Start(object sender, EventArgs e) { } protected void Application_BeginRequest(object sender, EventArgs e) { } protected void Application_AuthenticateRequest(object sender, EventArgs e) { } protected void Application_Error(object sender, EventArgs e) { } protected void Session_End(object sender, EventArgs e) { } protected void Application_End(object sender, EventArgs e) { } }
然后在Page代码页中依赖注入实现我们自定义的接口方法:
public partial class WebForm2 : System.Web.UI.Page { public IFetchServise fetch { get; set; } protected void Page_Load(object sender, EventArgs e) { this.Page.RegisterAsyncTask(new PageAsyncTask(GetName)); } private async Task GetName() { Label1.Text = await fetch.RandomFortuneAsync(); } }