<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Abp vNext異常處理的缺陷/改造方案

          共 15240字,需瀏覽 31分鐘

           ·

          2020-12-28 01:08

          之前吐槽Abp的用戶/租戶管理模塊!今天我又來了,這次我給Abp官方repo提了一個issue。

          目前Website使用Abp vNext開發(fā),免不了要全局處理異常、提示服務器異常信息。

          1. Abp官方異常處理

          Abp項目默認會啟動內(nèi)置的異常處理,默認不將異常信息發(fā)送到客戶端。
          在AppModule文件ConfigureServices方法中使用以下代碼:

          Configure
               
                (options =>
                
          {
              options.SendExceptionsDetailsToClients =  true;
          });

          可將異常信息發(fā)送到客戶端:如下圖:

          {
          "error": {
          "code": null,
          "message""ERROR [42000] [Cloudera][ImpalaODBC] (360) Syntax error occurred during query execution: [HY000] : AnalysisException: Could not resolve column/field reference: 'ug_fed89221846a42dc8427932b2965a020'\n",
          "details""OdbcException: ERROR [42000] [Cloudera][ImpalaODBC] (360) Syntax error occurred during query execution: [HY000] : AnalysisException: Could not resolve column/field reference: 'ug_fed89221846a42dc8427932b2965a020'\n\nSTACK TRACE: at Gridsum.EAP.Olap.ExecuteQueryLayer.HandleQueryAsync(QueryContext queryContext, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/Olap/ExecuteQueryLayer.cs:line 81\n at Gridsum.EAP.Olap.DistributedCacheLayer.HandleQueryAsync(QueryContext queryContext, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/Olap/DistributedCacheLayer.cs:line 50\n at Gridsum.EAP.DataQuery.AbstractQueryExecutor`1.ExecuteQueryAsync(TQuery query, DistributedCacheEntryOptions options, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/AbstractQueryExecutor.cs:line 60\n at Gridsum.EAP.DataQuery.AbstractQueryExecutor`1.ExecuteQueryAsync(TQuery query, CancellationToken token) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/AbstractQueryExecutor.cs:line 47\n at Gridsum.EAP.Application.UserGroupService.ClearUserGroupUserAsync(UserGroupUpdateUserDto updateDto, String idshort, CancellationToken cancelToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.Application/UserGroup/UserGroupService.cs:line 332\n at Gridsum.EAP.Application.UserGroupService.UpdateUserGroupUserAsync(UserGroupUpdateUserDto updateDto, CancellationToken cancelToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.Application/UserGroup/UserGroupService.cs:line 370\n at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo "42000] [Cloudera][ImpalaODBC] (360 "42000] [Cloudera][ImpalaODBC] (360) Syntax error occurred during query execution: [HY000] : AnalysisException: Could not resolve column/field reference: 'ug_fed89221846a42dc8427932b2965a020'\n\nSTACK TRACE: at Gridsum.EAP.Olap.ExecuteQueryLayer.HandleQueryAsync(QueryContext queryContext, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/Olap/ExecuteQueryLayer.cs:line 81\n at Gridsum.EAP.Olap.DistributedCacheLayer.HandleQueryAsync(QueryContext queryContext, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/Olap/DistributedCacheLayer.cs:line 50\n at Gridsum.EAP.DataQuery.AbstractQueryExecutor`1.ExecuteQueryAsync(TQuery query, DistributedCacheEntryOptions options, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/AbstractQueryExecutor.cs:line 60\n at Gridsum.EAP.DataQuery.AbstractQueryExecutor`1.ExecuteQueryAsync(TQuery query, CancellationToken token) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/AbstractQueryExecutor.cs:line 47\n at Gridsum.EAP.Application.UserGroupService.ClearUserGroupUserAsync(UserGroupUpdateUserDto updateDto, String idshort, CancellationToken cancelToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.Application/UserGroup/UserGroupService.cs:line 332\n at Gridsum.EAP.Application.UserGroupService.UpdateUserGroupUserAsync(UserGroupUpdateUserDto updateDto, CancellationToken cancelToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.Application/UserGroup/UserGroupService.cs:line 370\n at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult") Syntax error occurred during query execution: [HY000] : AnalysisException: Could not resolve column/field reference: 'ug_fed89221846a42dc8427932b2965a020'\n\nSTACK TRACE: at Gridsum.EAP.Olap.ExecuteQueryLayer.HandleQueryAsync(QueryContext queryContext, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/Olap/ExecuteQueryLayer.cs:line 81\n at Gridsum.EAP.Olap.DistributedCacheLayer.HandleQueryAsync(QueryContext queryContext, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/Olap/DistributedCacheLayer.cs:line 50\n at Gridsum.EAP.DataQuery.AbstractQueryExecutor`1.ExecuteQueryAsync(TQuery query, DistributedCacheEntryOptions options, CancellationToken cancellationToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/AbstractQueryExecutor.cs:line 60\n at Gridsum.EAP.DataQuery.AbstractQueryExecutor`1.ExecuteQueryAsync(TQuery query, CancellationToken token) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.DataQuery/AbstractQueryExecutor.cs:line 47\n at Gridsum.EAP.Application.UserGroupService.ClearUserGroupUserAsync(UserGroupUpdateUserDto updateDto, String idshort, CancellationToken cancelToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.Application/UserGroup/UserGroupService.cs:line 332\n at Gridsum.EAP.Application.UserGroupService.UpdateUserGroupUserAsync(UserGroupUpdateUserDto updateDto, CancellationToken cancelToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.Application/UserGroup/UserGroupService.cs:line 370\n at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult")\n at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()\n at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)\n at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed "TResult")\n at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo "TResult")\n at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()\n at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)\n at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed "TResult")\n at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo "TResult")\n at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()\n at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)\n at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed "TResult")\n at Gridsum.EAP.Controllers.UserGroupController.UpdateUserGroupUserAsync(String id, CancellationToken cancelToken) in /home/gitlab-runner/builds/ttRjAPVA/0/eap/website/app/src/Gridsum.EAP.HttpApi/Controllers/UserGroupController.cs:line 320\n at lambda_method3440(Closure , Object )\n at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker. g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker. g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker. g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker. g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\n" ,
          "data": null,
          "validationErrors": null
          }
          }

          經(jīng)過幾天倒騰,發(fā)現(xiàn)Abp vNext的異常處理有幾個問題。

          2.Abp異常處理存在的缺陷

          1. 并沒有如官方所述:自動處理所有異常,實際需要滿足官方所說的某個條件:

          這就導致當Controller Action方法返回的不是object result時,則根本捕獲不到異常(我們暫時不說middleware產(chǎn)生的異常),這應該算Abp的一個Bug

          1. 輸出的異常沒有TraceId, 不利于日志排查
          2. 發(fā)送到客戶端的日志字段message,detail過于詳細冗長,不適合前端顯示

          也可以配置SendExceptionsDetailsToClients,不將異常信息發(fā)送到客戶端,但這樣就因噎廢食了。

          3. 異常處理的目標

          雖然Abp的異常處理有缺陷, 但只是異常信息應用上的缺陷,
          Abp異常處理①對異常的劃分、②異常信息的本地化、③出現(xiàn)異常時寫日志  支持的還是相當好。

          基于Abp的異常處理現(xiàn)狀,考慮做一些改進:

          1. 對所有Controller-Action方法捕獲異常, [修復Abp Bug]
          2. 在Abp的異常處理結(jié)果中添加 TraceId
          3. 希望將服務端異常分類,簡化后給到前端;同時也不妨礙開發(fā)者查看詳細異常信息。

          4. 揪出Abp異常處理缺陷的根源

          Abp異常處理的核心對象AbpExceptionFilter,實現(xiàn)IAsyncExceptionFilter過濾器, ITransientDependency瞬時注入接口。

          這是一個ServiceFilterAttribute, 你可以理解有個特性作用在每一個Controller的Action方法上

          [ServiceFilter(typeof(AbpExceptionFilter))]

          一旦某個Controller的Action方法發(fā)生異常, 會執(zhí)行如下代碼:

          public async Task OnExceptionAsync(ExceptionContext context)
          {
             if (!ShouldHandleException(context))
             {
                  return;
             }
             await HandleAndWrapException(context);
          }
          1. ShouldHandleException(context) :監(jiān)測是否應該處理異常,據(jù)查該函數(shù)確實存在我上文說的問題:并不能捕獲所有的Action方法的異常。
          2. HandleAndWrapException(context):異常處理步驟:
            • 根據(jù)Abp內(nèi)置的異常類型,自動確定狀態(tài)碼 (這個在Abp官方文檔有講)
            • 序列化異常對象,并向客戶端輸出如下格式:
          {
          "error": {
          "code": null,
          "message""ERROR [42000] [Cloudera][ImpalaODBC] (360) Syntax error occurred during query execution: [HY000] : AnalysisException: Could not resolve column/field reference: 'ug_fed89221846a42dc8427932b2965a020'\n",
          "details":xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx......,
          "data": null,
          "validationErrors": null
          }
          }

          ① 輸出的信息,從一開始就沒有包含TraceId;
          ② Abp標準格式化后的異常信息,過于冗長,messagedetails字段均不適合前端顯示。

          • 寫日志,默認異常級別為Error

          掌握以上源碼,我們可以針對性的改造Abp的核心異常處理類AbpExceptionFilter

          5. Abp異常處理: 缺陷修復方案

          光說不練假把式

          Abp的AbpExceptionFilter不是抽象類,沒法重載,為達到我們設定的3個目標。
          考慮使用針對性的ExceptionFilter替換默認有缺陷的AbpExceptionFilter

          ①.  新建EapExceptionFilter,內(nèi)容拷貝自AbpExceptionFilter, 并做出如下針對性修改:

          ②. 在AppModule中,替換默認的AbpExceptionFilter為新的EapExceptionFilter過濾器:

          context.Services.AddMvc(options =>
          {
              options.Filters.ReplaceOne(x=> (x as ServiceFilterAttribute)?.ServiceType?.Name==nameof(AbpExceptionFilter), new ServiceFilterAttribute(typeof(EapExceptionFilter)));  
          })

          改造的效果如下:

          That's  All

          如果大家真切使用了Abp vNext最新版,

          相信我在第2點提到的Abp異常處理的缺陷,Abp使用者會感同身受;

          第3點提出的幾個目標也是企業(yè)級異常處理要解決的痛點。

          此異常處理的思路也可推及到其他非Abp項目.

          改造方案在Abp官方github issue上:  https://github.com/abpframework/abp/issues/6761

          一家之言,如有其他看法,請不吝賜教!

          (btw,公眾號文章發(fā)布之后,限制修改;若有后續(xù),請 [閱讀原文]!)

          Reference

          1. https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs
          2. https://docs.abp.io/zh-Hans/abp/latest/Exception-Handling
          3. https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-5.0
            ??
          回復 【關閉】
          回復 【實戰(zhàn)】獲取20套實戰(zhàn)源碼
          回復 【被刪】
          回復 【訪客】
          回復 【小程序】學獲取15套【入門+實戰(zhàn)+賺錢】小程序源碼
          回復 【python】學微獲取全套0基礎Python知識手冊
          回復 【2019】獲取2019 .NET 開發(fā)者峰會資料PPT
          回復 【加群】加入dotnet微信交流群

          再見,VIP,臥槽又來一個看片神器!


          對抗流氓app開屏廣告,你需要這款神器!



          瀏覽 66
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉午夜视频 | 熟女作爱一区二区视频 | www.97.色色 | 豆花成人无码视频 | 国产超清无码片内射 |