首页 新闻 赞助 找找看

.net core 莫名其妙的性能消耗,请大神看一眼

0
悬赏园豆:50 [待解决问题]

一个从fw 迁移到 core 2.1 的项目,一套电商系统, 一个正常的列表查询页面非常慢,所以自定义了个中间件, 并且在 action filter  和 action 的function  开始结束都加了 时间log

 

中间件是自定义的,但是也仅仅是 log的作用。

startup类里边,都是些常规注入,仅有的几个filter 也试过注释掉,但是消耗依旧差不多

Program 类 没有做修改

  1 public class Startup
  2     {
  3         public static ILoggerRepository repository { get; set; }
  4         //public Startup(IConfiguration configuration)
  5         //{
  6         //    Configuration = configuration;
  7         //}
  8 
  9         public Startup(IConfiguration configuration)
 10         {
 11             Configuration = configuration;
 12             repository = LogManager.CreateRepository("NETCoreRepository");
 13             XmlConfigurator.Configure(repository, new FileInfo("log4net.config"));
 14             SDKProperties.LogRepository = repository;//类库中定义的静态变量
 15         }
 16 
 17 
 18         public IConfiguration Configuration { get; }
 19 
 20         public IContainer ApplicationContainer { get; private set; }
 21 
 22         // This method gets called by the runtime. Use this method to add services to the container.
 23         public IServiceProvider ConfigureServices(IServiceCollection services)
 24         {
 25             services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
 26             services.AddMvc(options =>
 27             {
 28                 options.Filters.Add<ModelValidationFilter>();
 29                 options.Filters.Add<HttpGlobalExceptionFilter>();
 30                 options.Filters.Add<MobileTemplateAttribute>();
 31             }).AddJsonOptions(op => op.SerializerSettings.ContractResolver =
 32                                           new Newtonsoft.Json.Serialization.DefaultContractResolver()); ;
 33             services.AddAutoMapper();
 34             services.AddUEditorService();
 35             //添加Session功能
 36             services.AddSession();
 37             services.AddMemoryCache();
 38             //启用目录浏览 services.AddDirectoryBrowser();
 39             services.AddSingleton<IConfiguration>(Configuration);
 40             services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); //使用 HttpContext 注入对象
 41             services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
 42             services.AddSingleton<IUrlHelperFactory, UrlHelperFactory>().AddScoped(it => it.GetService<IUrlHelperFactory>()
 43                     .GetUrlHelper(it.GetService<IActionContextAccessor>().ActionContext));
 44             
 45 
 46             #region Auth 授权cookie相关配置
 47             services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
 48                 .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, option =>
 49                 {
 50                     //系统默认无指定 Authorize 跳转登录
 51                     option.LoginPath = new PathString("/Account/Login"); //设置登陆失败或者未登录授权的情况下,直接跳转的路径这里
 52                     option.AccessDeniedPath = new PathString("/Error/Forbidden"); //没有权限时的跳转页面
 53 
 54                     //设置cookie只读情况
 55                     option.Cookie.HttpOnly = true;
 56                     //cookie过期时间
 57                     option.Cookie.Expiration = new TimeSpan(4, 0, 0);
 58                     option.ExpireTimeSpan = new TimeSpan(4, 0, 0);
 59                 })
 60                 .AddCookie(AdminAuthorizeAttribute.AdminAuthenticationScheme, option =>
 61                 {
 62                     //Areas: Admin 模块 设置LoginPath等,因为不同系统使用 不同Scheme做区分验证
 63                     option.LoginPath = new PathString("/Admin/Login/Index");
 64                     //设置cookie只读情况
 65                     option.Cookie.HttpOnly = true;
 66                     //cookie过期时间
 67                     option.Cookie.Expiration = new TimeSpan(4, 0, 0);
 68                     option.ExpireTimeSpan = new TimeSpan(4, 0, 0);
 69                 })
 70                 .AddCookie(SellerAdminAuthorizeAttribute.SellerAdminAuthenticationScheme, option =>
 71                 {
 72                     //Areas: SellerAdmin 模块 设置LoginPath等,因为不同系统使用 不同Scheme做区分验证
 73                     option.LoginPath = new PathString("/SellerAdmin/Login/Index");
 74                     //设置cookie只读情况
 75                     option.Cookie.HttpOnly = true;
 76                     //cookie过期时间
 77                     option.Cookie.Expiration = new TimeSpan(4, 0, 0);
 78                     option.ExpireTimeSpan = new TimeSpan(4, 0, 0);
 79                 });
 80             #endregion
 81             
 82 
 83             var builder = CreateBuilder(services);//实例化 AutoFac  容器 
 84 
 85             ApplicationContainer = builder.Build();
 86             return new AutofacServiceProvider(ApplicationContainer);//第三方IOC接管 core内置DI容器 
 87         }
 88 
 89         public ContainerBuilder CreateBuilder(IServiceCollection services)
 90         {
 91             var builder = new ContainerBuilder();
 92             builder.Populate(services);
 93 
 94             var assemblyServices = Assembly.Load("PPX.Mall.Service");
 95             builder.RegisterAssemblyTypes(assemblyServices).PropertiesAutowired()
 96                 .Where(t => typeof(IService).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract)
 97                 .AsImplementedInterfaces().InstancePerLifetimeScope();
 98 
 99             var assemblyCore = Assembly.Load("PPX.Mall.Core");
100             builder.RegisterAssemblyTypes(assemblyCore).PropertiesAutowired()
101                 .Where(m => typeof(IStrategy).IsAssignableFrom(m) && !m.GetTypeInfo().IsAbstract)
102                 .AsImplementedInterfaces().InstancePerLifetimeScope();
103 
104             //builder.RegisterAssemblyTypes(Assembly.Load("PPX.Mall.API")).Where(t =>
105             //                typeof(Controller).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract).PropertiesAutowired();
106 
107             //builder.RegisterAssemblyTypes(Assembly.Load("PPX.Mall.SmallProgAPI")).Where(t =>
108             //                typeof(Controller).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract).PropertiesAutowired();
109 
110             builder.RegisterAssemblyTypes(Assembly.Load("PPX.Mall.Web")).Where(t =>
111                             typeof(Controller).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract).PropertiesAutowired();
112 
113             return builder;
114         }
115 
116         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
117         public void Configure(IApplicationBuilder app, IHostingEnvironment env)
118         {
119             if (env.IsDevelopment())
120             {
121                 app.UseBrowserLink();
122                 app.UseDeveloperExceptionPage();
123             }
124             else
125             {
126                 app.UseExceptionHandler("/Home/Error");
127             }
128             app.UseResponseTime();
129             app.UseSession();
130 
131             #region 设置静态资源访问
132             app.UseStaticFiles();
133             //app.UseStaticFiles(new StaticFileOptions
134             //{
135             //    FileProvider = new PhysicalFileProvider(
136             //    Path.Combine(Directory.GetCurrentDirectory(), "Storage")),
137             //        RequestPath = "/Storage"
138             //});
139             //启用目录浏览
140             //app.UseDirectoryBrowser(new DirectoryBrowserOptions
141             //{
142             //    FileProvider = new PhysicalFileProvider(
143             //    Path.Combine(Directory.GetCurrentDirectory(), "Storage")),
144             //        RequestPath = "/Storage"
145             //});
146             #endregion
147 
148             app.UseStaticHttpContext();
149             app.UseAuthentication();
150 
151             //此处代码,是将程序管道放到一个公共静态类中,以便其他程序集,可以通过管道直接获取注入的实例对象
152             //避免有些基类等地方,不方便使用 构造函数或者属性注入的方式获取 实例对象
153             PPXMallServiceProvider.ServiceProvider = app.ApplicationServices;
154 
155             //RegistAtStart.RegistStrategies();
156             //Plugin.RegistAtStart.RegistPlugins(); //TODO 插件未移植完,暂时注释
157 
158             app.UseMvc(routes =>
159             {
160                 //routes.Routes.Add(new PayRoute(
161                 //    routes.DefaultHandler,
162                 //    "/common/site/pay"));
163 
164                 routes.MapRoute(
165                     "Mobile_default",
166                     "m-{platform}/{controller}/{action}/{id?}",
167                     new { area = "Mobile", controller = "Home", action = "Index" });
168 
169                 routes.MapRoute(
170                     name: "area",
171                     template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
172 
173                 routes.MapRoute(
174                     "Mobile_default2",
175                     "m/{controller}/{action}/{id?}",
176                     new { area = "Mobile", controller = "Home", action = "Index", platform = "Mobile" });
177 
178                 routes.MapRoute(
179                     "Mobile_isshare",
180                     "m-{platform}/{controller}/{action}/{id?}/{isShare}",
181                     new { controller = "Home", action = "Index" });
182 
183                 routes.MapRoute(
184                     "Mobile_openid_isshare",
185                     "m-{platform}/{controller}/{action}/{id?}/{openId}/{isShare}",
186                     new { controller = "Home", action = "Index" });
187 
188                 routes.MapRoute(
189                     "Web_default",
190                     "{controller}/{action}/{id?}",
191                     new { area = "Web", controller = "Home", action = "Index" });
192 
193                 routes.MapRoute(
194                     "common_default",
195                     "common/{controller}/{action}/{id?}",
196                     new { controller = "Home", action = "Index" });
197 
198                 routes.MapRoute(
199                     name: "default",
200                     template: "{controller=Home}/{action=Index}/{id?}");
201             });
202 
203             
204         }
205     }

 

所以,这一个仅仅 分页查询的request,从Action filter Executed 到 Middleware _next.Invoke(context); 执行完中间有什么环节 有可能产生这么大的消耗? 已经排除了 filter

死神的背影的主页 死神的背影 | 小虾三级 | 园豆:667
提问于:2018-08-07 10:25
< >
分享
所有回答(2)
0

问题应该出在列表查询页面的数据库操作,建议提供那部分代码

dudu | 园豆:31075 (高人七级) | 2018-08-07 10:33

dudu 大神,消耗的点已经找到了,是因为ef 查询的获取结果的时候 耗时太多了,我尝试提前进行了 tolist的操作,发现这一步操作 耗时巨大。

但是有个现象,部署在同一个服务器IIS上的两套程序,一个是 迁移之前的framework版本, 一个是迁移之后的 core,同样的一个 列表查询页面,同样的 ef 代码,fw的 查询非常快,页面响应1秒以内, core 要 好几秒, 是因为IIS 针对fw 托管的类型,有什么相关的缓存优化吗?

我尝试修改了ef部分的代码,做了优化,之前会产生几十条 sql 语句,现在 只有两三条,但是响应时间还在2s 左右,达不到预期的效果,主表的数据量也才几百条而已

支持(0) 反对(0) 死神的背影 | 园豆:667 (小虾三级) | 2018-08-07 16:04

@死神的背影: 看一下是不是这个问题引起的? 使用Entity Framework Core需要注意的一个全表查询问题

支持(0) 反对(0) dudu | 园豆:31075 (高人七级) | 2018-08-07 16:08
0

建议EF只用于修改、插入、删除、简单的单表查询操作。查询用Dapper.NET之类更灵活的工具。
比如:命令查询职责分离(CQRS)模式,EF用于命令的终端执行,Dapper.NET只用于查询

慧☆星 | 园豆:5640 (大侠五级) | 2018-10-11 14:34
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册