【问题标题】:Grails filter stats insert performanceGrails 过滤器统计插入性能
【发布时间】:2013-12-13 14:39:41
【问题描述】:

我在 grails 中有一个过滤器来捕获所有控制器请求,并在数据库中插入一行,其中包含控制器名称、操作名称、用户 ID、日期和 guid。这工作正常,但我想找到一种方法来提高性能。现在它需要大约 100 毫秒来完成所有这些,其中 70-80 毫秒的时间创建一个语句。我使用了域对象插入、groovy Sql 和原始 java 连接/语句。有没有更快的方法来提高在过滤器中插入单个记录的性能?或者,是否有不同的模式可用于插入?代码(使用 groovy SQL)如下:

class StatsFilters {

def grailsApplication
def dataSource
def filters =
{
    logStats(controller:'*', action:'*')
    {
        before = {
            if(controllerName == null || actionName == null)
            {
                return true
            }
            def logValue = grailsApplication.config.statsLogging
            if(logValue.equalsIgnoreCase("on") && session?.user?.uid != null & session?.user?.uid != "")
            {
                try{

                    def start = System.currentTimeMillis()
                    Sql sql = new Sql(dataSource)
                    def userId = session.user.uid
                    final String uuid = "I" + UUID.randomUUID().toString().replaceAll("-","");
                    String insert = "insert into STATS(ID, CONTROLLER, ACTION, MODIFIED_DATE, USER_ID) values ('${uuid}','${controllerName}','${actionName}',SYSDATE,'${userId}')"
                    sql.execute(insert)
                    sql.close()
                    def end = System.currentTimeMillis()
                    def total = end - start
                    println("total " + total)
                }
                catch(e)
                {
                    log.error("Stats failed to save with exception " + e.getStackTrace())
                    return true
                }
            }
            return true
        }
    }
}

}

还有我当前的数据源

dataSource {

pooled = true
dialect="org.hibernate.dialect.OracleDialect"
properties {
    maxActive = 50
    maxIdle = 10
    initialSize = 10
    minEvictableIdleTimeMillis = 1800000
    timeBetweenEvictionRunsMillis = 1800000
    maxWait = 10000
    validationQuery = "select * from resource_check"
    testWhileIdle = true
    numTestsPerEvictionRun = 3
    testOnBorrow = true
    testOnReturn = true
}
//loggingSql = true

}

----------解决方案------------ -

解决方案是简单地生成一个线程并保存统计信息。这样用户响应时间不会受到影响,但保存几乎是实时完成的。此应用程序中的用户数量(企业内部、有限的用户组)没有比这更强大的价值了。

void saveStatData(def controllerName, def actionName, def userId)
{
    Thread.start{
        Sql sql = new Sql(dataSource)
        final String uuid = "I" + UUID.randomUUID().toString().replaceAll("-","");
        String insert = "insert into STATS(ID, CONTROLLER, ACTION, MODIFIED_DATE, USER_ID) values ('${uuid}','${controllerName}','${actionName}',SYSDATE,'${userId}')"
        sql.execute(insert)
        sql.close()
    }
}

【问题讨论】:

  • 我很想知道使用 Grails Executor 插件是否会更好,Executor 是 Thread 的“正确完成”,所以可能会有性能和可靠性的提升跨度>

标签: sql performance grails groovy before-filter


【解决方案1】:

更好的模式是不要在过滤器中插入行,而是将记录添加到某个列表中,并通过异步作业定期将列表刷新到数据库中(例如使用 Quartz 插件)。

如果应用程序崩溃,您可能会丢失一些数据,但如果您安排作业经常运行(例如每 x 分钟),这应该不是问题。

【讨论】:

  • 丢失数据将是一个问题,因为这会准确跟踪应用程序中发生的情况。如果应用程序崩溃,那正是我们需要此信息的确切时间。也就是说,我认为我将研究异步解决方案,而不是批处理模式。如果我得到它的工作,我会发布它。
猜你喜欢
  • 2018-11-04
  • 1970-01-01
  • 1970-01-01
  • 2012-04-20
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多