通過celery提高crontab配置效率

這是學習筆記的第 1777篇文章

今天在接入備份任務配置的時候也是一波三折,解決了業務元數據的問題,也逐步熟悉了業務,對於現有的備份情況會越來越有把握。

業務問題過去之後很快就碰到了性能問題,這個也是之前的處理中沒有意識到的。比如現在我嘗試逐步介入備份任務的時候,每次接入10個,添加了配置任務,會在系統的crontab中生成一條定時任務配置。

整個平臺暫時只負責任務並行調度,即分成幾組並行任務,任務時間調度,即任務什麼時候開始,怎麼去銜接任務的執行時間。

大體的使用界面如下:

在接入之後,確認元數據沒有問題的時候,我們開啓數據同步操作,會在元數據中同步配置,然後下推crontab的配置到系統任務中,但是這個時候原有的異步請求AJAX拋出了異常,大體的日誌如下:

/usr/local/DBA_SCRIPTS/mysql/crontab_automanage.sh -h 1 -m 59 -o add -c mysqlfullbackup -H xxxx -P 4306
{u'mission_id': u'25089', u'failed': {}, u'success': {u'xxxxx': [u'20181018 17:54:43 Create crontab task...', u'20181018 17:54:43 Clear crontab tmp file', u'20181018 17:54:43 remove crontab xtraback
up_innodb_full_v6 on tmp file', u'20181018 17:54:43 Job complete']}, u'unreachable': {}}
{u'mission_id': u'25089', u'failed': {}, u'success': {u'xxxxx': [u'20181018 17:54:43 Create crontab task...', u'20181018 17:54:43 Clear crontab tmp file', u'20181018 17:54:43 remove crontab xtraback
up_innodb_full_v6 on tmp file', u'20181018 17:54:43 Job complete']}, u'unreachable': {}}
Thu Oct 18 17:54:43 2018 - uwsgi_response_writev_headers_and_body_do(): Broken pipe [core/writer.c
 line 306] during POST /backup/mysql_backupconf_batch_sync/ (192.168.xxxx)
IOError: write error

可以看到這個問題是在請求的過程中發生了異常,根據配置很可能是超時導致,使用ansible_adhoc觸發每次執行大約需要2秒,30多個剛好觸發了臨界點。

這裏恰好就是程序端實現的一個瓶頸,目前的任務執行是輪詢,也即爲串行執行模式,按照這種方式,如果任務的數量增加,那麼系統的交互時長會直線上升,體驗會很差,而且任務的執行很可能會中斷。

整體的一個流程設計圖如下:

注意這裏是可以稱爲執行器,但是還離調度器有點距離。

這個部分怎麼改進呢,可以參考下面的圖:

我們下發的任務都可以先接受,然後慢慢執行,這樣就好比對於前端馬上有了反饋,整個任務的後端執行是真正的異步方式,這個時候是串行還是並行就沒那麼敏感了,如果想要提高執行效率,那麼可以配置多個worker,否則就是串行的方式。

從代碼的層面來簡單說一下如何改進,代碼中我們封裝了ansible_adhoc,通過裝飾器,我們可以把它封裝爲一個異步任務。

@shared_task
def ansible_adhoc(user, hosts, module, command, sudo=False):
    url = 'http://xxxxxx:8000/dba/ansible/adhoc'
    body = {"hosts": hosts, "module": module, "module_args": command, "sudo": sudo}
    return_dict = {}
    。。。。。

後端的業務邏輯如下,是會通過循環的方式調用ansible_adhoc

def mysql_backupconf_batch_sync(request):
    return_dict = {}
    mysql_xtrabackup_schedulers = mysql_xtrabackup_scheduler.objects.all()
    for temp in mysql_xtrabackup_schedulers:
        print temp.os_crontab
        mysql_backupconfig.objects.filter(backup_ip=temp.backup_ip,backup_instanceport=temp.backup_instanceport).update(
            os_crontab=temp.os_crontab
            )
        begin_hour = int(temp.os_crontab.split(":")[0])
        begin_minute = int(temp.os_crontab.split(":")[1])
        commend = "/usr/local/DBA_SCRIPTS/mysql/crontab_automanage.sh -h %s -m %s -o add -c mysqlfullbackup -H %s -P %s" % (
        begin_hour, begin_minute,temp.backup_ip,temp.backup_instanceport)
        print(commend)
        result = ansible_adhoc('dba_mysql', temp.backup_ip, "script", commend, True)
        print(result)
    return JsonResponse({'msg': '更新成功', "code": 200, 'data': return_dict})

在這個代碼的基礎上,只需要添加一個函數,即可變得高大上,切換爲隊列模式,間接實現了併發。

def mysql_backupconf_batch_sync(request):
    return_dict = {}
    mysql_xtrabackup_schedulers = mysql_xtrabackup_scheduler.objects.all()
    for temp in mysql_xtrabackup_schedulers:
        print temp.os_crontab
        mysql_backupconfig.objects.filter(backup_ip=temp.backup_ip,backup_instanceport=temp.backup_instanceport).update(
            os_crontab=temp.os_crontab
            )
        begin_hour = int(temp.os_crontab.split(":")[0])
        begin_minute = int(temp.os_crontab.split(":")[1])
        commend = "/usr/local/DBA_SCRIPTS/mysql/crontab_automanage.sh -h %s -m %s -o add -c mysqlfullbackup -H %s -P %s" % (
        begin_hour, begin_minute,temp.backup_ip,temp.backup_instanceport)
        print(commend)
        result = ansible_adhoc.delay('dba_mysql', temp.backup_ip, "script", commend, True)
        print(result)
    return JsonResponse({'msg': '更新成功', "code": 200, 'data': return_dict})

當然程序端的併發也是需要視情況而定,而不要一位爲了技術酸爽而本末倒置。

按照這種方式,整個任務的串行,並行都可以做到基本可控。

後續在這個基礎上,在celery方向上需要考慮五類任務的接入:

1)異步任務,這個是celrey原生支持的

2)定時任務,這個是celery原生支持的

3)crontab,這個是保留原本的crontab,但是執行時間可以根據配置靈活的調度產生,這樣執行和時間就可以做到解耦合。

4)API,這個計劃作爲內部和外部使用兩種模式,通過API的方式把執行結果封裝到隊列裏面,對於變更執行類的需求,通過這種方式是比較適合的,可以極大提高系統吞吐率。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章