Google app engine 如何调试具有数百万次写入的长时间运行的mapreduce作业?

Google app engine 如何调试具有数百万次写入的长时间运行的mapreduce作业?,google-app-engine,mapreduce,Google App Engine,Mapreduce,我正在使用库的简单控件.start\u map()函数来启动mapreduce作业。此作业成功完成,并在生成的/mapreduce/detail?mapreduce\u id=页面上显示约43M个映射器调用。但是,本页没有提到reduce步骤或任何我认为仍在运行的底层appengine管道进程。是否有某种方法返回此调用生成的管道ID,以便我可以查看底层管道以帮助调试此长期运行的作业?我想检索足够的信息来打开此页面:/mapreduce/pipeline/status?root= 下面是我最初用于

我正在使用库的简单
控件.start\u map()
函数来启动mapreduce作业。此作业成功完成,并在生成的
/mapreduce/detail?mapreduce\u id=
页面上显示约43M个映射器调用。但是,本页没有提到reduce步骤或任何我认为仍在运行的底层appengine管道进程。是否有某种方法返回此调用生成的管道ID,以便我可以查看底层管道以帮助调试此长期运行的作业?我想检索足够的信息来打开此页面:
/mapreduce/pipeline/status?root=

下面是我最初用于启动mapreduce作业的代码示例:

from third_party.mapreduce import control
mapreduce_id = control.start_map(
    name="Backfill",
    handler_spec="mark_tos_accepted",
    reader_spec=(
        "third_party.mapreduce.input_readers.DatastoreInputReader"),
    mapper_parameters={
        "input_reader": {
            "entity_kind": "ModelX"
        },
    },
    shard_count=64,
    queue_name="backfill-mapreduce-queue",
 )
以下是映射函数:

# This is where we keep our copy of appengine-mapreduce
from third_party.mapreduce import operation as op

def mark_tos_accepted(modelx):
    # Skip users who have already been marked
    if (not modelx
        or modelx.tos_accepted == myglobals.LAST_MATERIAL_CHANGE_TO_TOS):
    return

    modelx.tos_accepted = user_models.LAST_MATERIAL_CHANGE_TO_TOS
    yield op.db.Put(modelx)
以下是ModelX的相关部分:

class BackupModel(db.Model):
    backup_timestamp = db.DateTimeProperty(indexed=True, auto_now=True)

class ModelX(BackupModel):
    tos_accepted = db.IntegerProperty(indexed=False, default=0)
为了了解更多的上下文,我正在尝试调试一个我看到的问题,即数据仓库中出现的写操作

2013年3月23日,我们启动了一项MapReduce作业(我们称之为
a
),该作业覆盖了一个数据库模型(我们称之为
ModelX
),拥有约4300万个实体。7小时后,作业“完成”且
/mapreduce/detail
页面显示我们已成功映射所有实体,如下所示

mapper-calls: 43613334 (1747.47/sec avg.)
mapper-calls: 43803632 (964.24/sec avg.)
2013年3月31日,我们在
ModelX
上启动了另一个MapReduce作业(我们称之为B)。12小时后,作业完成,状态成功,
/mapreduce/detail
页面显示我们已成功映射所有实体,如下所示

mapper-calls: 43613334 (1747.47/sec avg.)
mapper-calls: 43803632 (964.24/sec avg.)
我知道job先生给所有的
ModelX
实体写了一封信,因为我们引入了一个新的属性,以前没有一个实体包含这个属性。
ModelX
包含如下自动添加属性

backup_timestamp = ndb.DateTimeProperty(indexed=True, auto_now=True)
我们的数据仓库流程在
ModelX
上运行查询,以查找在某一天发生更改的实体,然后下载这些实体并将其存储在单独的(AWS)数据库中,以便我们可以对其进行分析。此查询的一个示例是:

db.GqlQuery('select * from ModelX where backup_timestamp >= DATETIME(2013, 4, 10, 0, 0, 0) and backup_timestamp < DATETIME(2013, 4, 11, 0, 0, 0) order by backup_timestamp')
这让我想到,尽管mapreduce作业发出的op.db.Put()调用仍在某些管道或队列中运行,并导致这种涓涓效应

此外,如果我查询具有旧
备份\u时间戳的实体,我可以回溯到相当远的地方,仍然可以得到大量实体,但我希望所有这些查询都返回0:

In [4]: ModelX.all().filter('backup_timestamp <', 'DATETIME(2013,2,23,1,1,1)').count()
Out[4]: 1000L

In [5]: ModelX.all().filter('backup_timestamp <', 'DATETIME(2013,1,23,1,1,1)').count()
Out[5]: 1000L

In [6]: ModelX.all().filter('backup_timestamp <', 'DATETIME(2012,1,23,1,1,1)').count()
Out[6]: 1000L

[4]中的
:ModelX.all().filter('backup\u timestamp我认为你不会在那里有任何reducer函数,因为你所做的只是启动一个映射器。要完成一个完整的mapreduce,你必须显式地实例化一个,并在它上面调用
start
。作为奖励,这回答了你的问题,因为它返回了管道ID,然后你可以在状态URL中使用它。

试试看g了解具体问题。您是否希望AWS数据库中有更多的实体?我怀疑问题在于将旧的ModelX实体下载到AWS数据库的过程中,不知何故,它没有捕获所有更新的实体

AWS下载过程是否以任何方式修改了ModelX?如果不是,那么您为什么会对发现带有旧的
修改的
时间戳的实体感到惊讶?
修改的
只会在写入操作时更新,而不会在读取操作时更新


有点不相关-关于限制,我通常发现限制的任务队列是问题所在,因此,也许可以检查您的任务在那里有多旧,或者您的应用程序是否由于在其他地方发生大量错误而被限制。

control.start\u map不使用管道,并且没有洗牌/减少步骤。当mapreducetus页面显示其已完成,所有与mapreduce相关的taskqueue任务都应已完成。您可以检查队列,甚至暂停队列


我怀疑存在与旧模型的旧索引或最终一致性相关的问题。若要调试MR,请筛选警告/错误日志并按MR id进行搜索。若要帮助处理特定情况,请查看地图处理程序。

感谢您的响应,但我不想启动另一个43M写入管道调试这一点。如果这有帮助,我已经为问题添加了一些额外的上下文。我还与GAE企业支持部门联系,希望能够更深入地了解正在发生的事情,我们拭目以待。是的,我希望mapreduce报告写入成功的速率与我的下载脚本检测到它们的速率相同。相反,mapreduce报告4300万次写入成功已完成,但我的下载脚本仅检测到3M。我很惊讶有旧的修改时间戳,因为mapreduce告诉我它已经完成了对每个
ModelX
实体的编写。AWS下载程序是只读的。
回填mapreduce队列
没有显示异常排队的任务。GAE das中没有任何内容hboards显示我的mapreduce仍在运行,因此出现了这个问题。