(7)学習ノート)ASP.NET COREマイクロサービスMicro-Service---Polly+AOP+依存注入パッケージのダウングレードフレームワークを利用...
12691 ワード
単純な融解降格フレームの作成
目的は、ダウングレードに関与するメソッドパラメータと同様に、HelloAsyncがエラーを実行したときにHelloFallBackAsyncメソッドを実行することです.
public class Person
{
[HystrixCommand("HelloFallBackAsync")]
public virtual async Task HelloAsync(string name)
{
Console.WriteLine("hello"+name);
return "ok";
}
public async Task HelloFallBackAsync(string name)
{
Console.WriteLine(" "+name);
return "fail";
}
}
1.HystrixCommandAttributeの作成
using AspectCore.DynamicProxy;
using System;
using System.Threading.Tasks;
namespace hystrixtest1
{
//
[AttributeUsage(AttributeTargets.Method)]
public class HystrixCommandAttribute : AbstractInterceptorAttribute { public HystrixCommandAttribute(string fallBackMethod) { this.FallBackMethod = fallBackMethod; } public string FallBackMethod { get; set; } public override async Task Invoke(AspectContext context, AspectDelegate next) { try { await next(context);// } catch (Exception ex) { //context.ServiceMethod 。context.ServiceMethod.DeclaringType //context.Implementation p //context.Parameters // , FallBackMethod // //1. ( , ) var fallBackMethod = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod); //2. Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters); //3. context.ReturnValue = fallBackResult; } } } }
2、編纂類
public class Person// public
{
[HystrixCommand(nameof(HelloFallBackAsync))]
public virtual async Task HelloAsync(string name)//
{
Console.WriteLine("hello"+name);
String s = null;
// s.ToString();
return "ok";
}
public async Task HelloFallBackAsync(string name) { Console.WriteLine(" "+name);
return "fail"; } [HystrixCommand(nameof(AddFall))]
public virtual int Add(int i,int j) { String s = null;
//s.ToArray();
return i + j; } public int AddFall(int i, int j) { return 0; } }
3、代理オブジェクトの作成
ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();
using (IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build())
{
Person p = proxyGenerator.CreateClassProxy();
Console.WriteLine(p.HelloAsync("yzk").Result);
Console.WriteLine(p.Add(1, 2));
}
上記のコードは、[HystrixCommand]と表示され、virtualで複数のダウングレードもサポートしています.
public class Person// public
{
[HystrixCommand(nameof(Hello1FallBackAsync))]
public virtual async Task HelloAsync(string name)//
{
Console.WriteLine("hello" + name);
String s = null;
s.ToString();
return "ok";
}
[HystrixCommand(nameof(Hello2FallBackAsync))]
public virtual async Task Hello1FallBackAsync(string name)
{
Console.WriteLine("Hello 1" + name);
String s = null;
s.ToString();
return "fail_1";
}
public virtual async Task Hello2FallBackAsync(string name) { Console.WriteLine("Hello 2" + name); return "fail_2"; } [HystrixCommand(nameof(AddFall))]
public virtual int Add(int i, int j) { String s = null;
s.ToString();
return i + j; } public int AddFall(int i, int j) { return 0; } }
フレームの微細化
上で原理を理解して、それから直接書いたもっと複雑なHystrixCommandAttributeを展示して、コードを説明します.
これは楊中科先生が維持しているオープンソースプロジェクトです.
githubの最新アドレスhttps://github.com/yangzhongke/RuPeng.HystrixCore
Nugetアドレス:https://www.nuget.org/packages/RuPeng.HystrixCore
再試行:MaxRetryTimesは最大数回の再試行を表し、0の場合は再試行しない.RetryIntervalMillisecondsは再試行間隔のミリ秒数を表す.
溶断:E n a b l e CircuitBreakerが溶断を有効にしているかどうか、ExceptionsAllowedBeforeBreakingは溶断前に許容エラーが何回か発生したことを示し、MillisecondsofBreakは溶断の時間(ミリ秒)を示している.
タイムアウト:TimeOutMillisecondsが何ミリ秒以上実行するとタイムアウトとみなされます(0はタイムアウトを検出しないことを示します)
キャッシュ:CacheTTLMillisecondsは何ミリ秒キャッシュ(0はキャッシュしないことを示す)し、「クラス名+メソッド名+すべてのパラメータ値ToString接合」でキャッシュキーを作成します(唯一の要件はパラメータのタイプToStringが異なるオブジェクトに対して必ず異なることです).
キャッシュコンポーネントが使用されました:Install-Package Microsoft.Extensions.Caching.Memory
using System;
using AspectCore.DynamicProxy;
using System.Threading.Tasks;
using Polly;
namespace RuPeng.HystrixCore
{
[AttributeUsage(AttributeTargets.Method)]
public class HystrixCommandAttribute : AbstractInterceptorAttribute { /// /// , 0 /// public int MaxRetryTimes { get; set; } = 0; /// /// /// public int RetryIntervalMilliseconds { get; set; } = 100; /// /// /// public bool EnableCircuitBreaker { get; set; } = false; /// /// /// public int ExceptionsAllowedBeforeBreaking { get; set; } = 3; /// /// ( ) /// public int MillisecondsOfBreak { get; set; } = 1000; /// /// (0 ) /// public int TimeOutMilliseconds { get; set; } = 0; /// /// (0 ), “ + + ToString ” Key /// public int CacheTTLMilliseconds { get; set; } = 0; // CircuitBreaker Policy 。 // Attribute , Attribute 。 // , Person , , ExceptionsAllowedBeforeBreaking , , , , 。 // Attribute Policy , Policy 。 private Policy policy; private static readonly Microsoft.Extensions.Caching.Memory.IMemoryCache memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions()); /// /// /// /// public HystrixCommandAttribute(string fallBackMethod) { this.FallBackMethod = fallBackMethod; } public string FallBackMethod { get; set; } public override async Task Invoke(AspectContext context, AspectDelegate next) { // HystrixCommand policy // CircuitBreaker policy // , HystrixCommandAttribute, , // HystrixCommandAttribute , policy // policy, CircuitBreaker 。 //Attribute , policy lock (this)// Invoke , policy { if (policy == null) { policy = Policy.NoOpAsync();// Policy if (EnableCircuitBreaker) // { policy = policy.WrapAsync(Policy.Handle().CircuitBreakerAsync(ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(MillisecondsOfBreak))); } if (TimeOutMilliseconds > 0) // { policy = policy.WrapAsync(Policy.TimeoutAsync(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), Polly.Timeout.TimeoutStrategy.Pessimistic)); } if (MaxRetryTimes > 0) // MaxRetryTimes { policy = policy.WrapAsync(Policy.Handle().WaitAndRetryAsync(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds))); } Policy policyFallBack = Policy .Handle() // .FallbackAsync(async (ctx, t) => { // ExecuteAsync(ctx => next(context), pollyCtx); pollyCtx AspectContext aspectContext = (AspectContext)ctx["aspectContext"]; var fallBackMethod = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod); Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters); // , , Invoke context // , Polly AspectContext //context.ReturnValue = fallBackResult; aspectContext.ReturnValue = fallBackResult; }, async (ex, t) => { }); policy = policyFallBack.WrapAsync(policy); } } // AspectContext Polly, FallbackAsync , Context pollyCtx = new Context();//Context polly Execute FallBack、Execute pollyCtx["aspectContext"] = context;//context aspectCore //Install-Package Microsoft.Extensions.Caching.Memory if (CacheTTLMilliseconds > 0) { // + + key string cacheKey = "HystrixMethodCacheManager_Key_" + context.ServiceMethod.DeclaringType + "." + context.ServiceMethod + string.Join("_", context.Parameters); // 。 , if (memoryCache.TryGetValue(cacheKey, out var cacheValue)) { context.ReturnValue = cacheValue; } else { // , await policy.ExecuteAsync(ctx => next(context), pollyCtx); // using (var cacheEntry = memoryCache.CreateEntry(cacheKey)) { cacheEntry.Value = context.ReturnValue;// cacheEntry.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMilliseconds(CacheTTLMilliseconds); } } } else// , { await policy.ExecuteAsync(ctx => next(context), pollyCtx); } } } }
フレームワークは万能ではなく、過度なフレームワークを使わないで、過度なフレームワークがもたらす複雑さは急増し、誰もが好きから誰もが恐怖になる.
結合asp.Netcore依存注入
asp.Netcoreプロジェクトではaspを借りることができる.Netcoreの依存注入は,プロキシクラスオブジェクトの注入を簡略化し,ProxyGeneratorBuilderを呼び出してプロキシクラスオブジェクトの注入を行う必要がなくなった.
Install-Package AspectCore.Extensions.DependencyInjection
Startupを変更します.csのConfigureServicesメソッドは,戻り値をvoidからIServiceProviderに変更する.
using AspectCore.Extensions.DependencyInjection;
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton();
return services.BuildAspectCoreServiceProvider();
}
ここでservices.AddSingleton(); Personを注入する.
BuildAspectCoreServiceProviderは、aspectcoreに注入を引き継ぐものです.
Controllerでは、コンストラクション関数による依存注入が可能になります.
public class ValuesController : Controller
{
private Person p;
public ValuesController(Person p)
{
this.p = p;
}
}
クラスにCustomInterceptorAttributeがマークされている限り、すべてのサービスクラスを反射的にスキャンする方法をサービス実装クラスとします.すべてのクラスを一気にスキャンしないようにするには、RegisterServicesはどのプログラムセットからロードするかを手動で指定します.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
RegisterServices(this.GetType().Assembly, services); return services.BuildAspectCoreServiceProvider();
}
private static void RegisterServices(Assembly asm, IServiceCollection services)
{
// public
foreach (Type type in asm.GetExportedTypes())
{
// CustomInterceptorAttribute
bool hasCustomInterceptorAttr = type.GetMethods().Any(m => m.GetCustomAttribute(typeof(CustomInterceptorAttribute)) != null);
if (hasCustomInterceptorAttr) { services.AddSingleton(type); } } }
注:この文章は私が楊中科の先生を見たのです.Net Coreマイクロサービス第2版と.Net Coreマイクロサービス第2版レッスンをまとめた
転載先:https://www.cnblogs.com/qhbm/p/9229779.html