ServiceStack - 由最大应用程序池大小引起的超时过期

时间:2014-06-17 02:18:15

标签: servicestack idisposable

我正在使用ServiceStack的funq,我的AppHost文件中有以下代码。由于应用程序池大小达到最大限制,API命中超时过期错误。

    var dbFactory = new OrmLiteConnectionFactory(string.Empty, SqlServerDialect.Provider);

... 

// Loop to get multiple different country connection string
foreach (string server in countryCodeList)
{
    dbFactory.RegisterConnection(server, connectionString, SqlServerDialect.Provider);
}

this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
{
    requestInfo = requestDto.Dump();
    ...
    container.Register<IReferenceRepository>(c => new ReferenceRepository(dbFactory, baseModel.db_country_code));
    container.Register<ICompanyRepository>(c => new CompanyRepository(dbFactory, baseModel.db_country_code));
    ...
});

我在我的Repository基类中实现了IDisposable。但它似乎并没有在每个请求结束时处理连接。在perfmon.exe中可以看到NumberOfPooledConnections在不丢弃的情况下为每个请求保持增加。

Repository bass class中的代码:

public class Repository : IDisposable
{
    protected IDbConnectionFactory dbFactory { get; set; }
    public string CountryCode { get; set; }
    private IDbConnection db;

    public Repository(IDbConnectionFactory dbConnectionFactory, string countryCode)
    {
        this.dbFactory = dbConnectionFactory;
        this.CountryCode = countryCode;
    }

    protected virtual IDbConnection Db(string connectionKey)
    {
        return db ?? (db = dbFactory.OpenDbConnection(connectionKey));
    }

    public virtual void Dispose()
    {
        if (db != null)
            db.Dispose();
    }
}

只是想知道是否将 ReusedWithin(ReuseScope.Request)添加到container.Register部分会有帮助吗?

如果我以正确的方式做事,有人可以指导我吗?提前致谢。

已编辑:API请求将从一个服务调用另一个服务,并从不同的存储库获取数据。

1 个答案:

答案 0 :(得分:1)

ServiceStack中的所有依赖项都应该在AppHost.Configure()中注册,它在StartUp上运行一次,之后应该被认为是不可变的。

你不应该在RequestFilter中对注册依赖关系(在每个请求上运行)。

OrmLiteConnectionFactory(与ServiceStack中的所有工厂一样)被设计为注册为单例,这也是Funq中的默认生命周期,即:

container.Register<IDbConnectionFactory>(
    c => new OrmLiteConnectionFactory(connString, SqlServerDialect.Provider));

然后,您可以从IOC解析它以注册您的命名连接,例如:

var factory=(OrmLiteConnectionFactory)container.Resolve<IDbConnectionFactory>();
foreach (string server in countryCodeList)
{
    factory.RegisterConnection(server, connString, SqlServerDialect.Provider);
}

您的存储库之类的所有其他依赖项也应在AppHost.Configure()中注册。如果它实现IDisposable且ReuseScope为NoneRequest,则会在请求结束时将其处理。

使用请求数据创建依赖关系

由于需要在StartUp上注册依赖项,因此它无法访问请求数据。如果需要,那么需要在运行时传递它。

您可以通过将样板添加到基本服务类来减少样板,例如:

public abstract class AppServiceBase : Service
{
    public IDbConnectionFactory DbFactory 
    { 
        get { return TryResolve<IDbConnectionFactory>(); }
    }

    ReferenceRepository refRepo;
    public ReferenceRepository ReferenceRepo
    {
        get
        {
            if (refRepo == null)
                refRepo = new ReferenceRepository(
                    DbFactory.OpenDbConnection(Request.Param("c_code")));

            return refRepo;
        }
    }

    public override Dispose()
    {
        base.Dispose();

        if (refRepo != null)
           refRepo.Dispose();
    }
}

然后您的服务可以像普通依赖一样访问,即:

public class MyService : AppServiceBase
{
    public object Get(Request request)
    {
        var foo = ReferenceRepo.GetById(request.Id);
    }
}