perf: 优化 applet 选择账号调度

pull/11222/head
ibuler 2023-08-08 15:41:55 +08:00
parent 680d31dad2
commit 9bf76ae07a
4 changed files with 25 additions and 10 deletions

View File

@ -14,6 +14,7 @@ class AccountFilterSet(BaseFilterSet):
username = drf_filters.CharFilter(field_name="username", lookup_expr='exact') username = drf_filters.CharFilter(field_name="username", lookup_expr='exact')
address = drf_filters.CharFilter(field_name="asset__address", lookup_expr='exact') address = drf_filters.CharFilter(field_name="asset__address", lookup_expr='exact')
asset_id = drf_filters.CharFilter(field_name="asset", lookup_expr='exact') asset_id = drf_filters.CharFilter(field_name="asset", lookup_expr='exact')
asset = drf_filters.CharFilter(field_name='asset', lookup_expr='exact')
assets = drf_filters.CharFilter(field_name='asset_id', lookup_expr='exact') assets = drf_filters.CharFilter(field_name='asset_id', lookup_expr='exact')
nodes = drf_filters.CharFilter(method='filter_nodes') nodes = drf_filters.CharFilter(method='filter_nodes')
node_id = drf_filters.CharFilter(method='filter_nodes') node_id = drf_filters.CharFilter(method='filter_nodes')

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ecbfbaa09e20e182a7804f2b60d7241cae6f81dbc58abede1e7a4a863b18777a oid sha256:6a49d0a2a96656a3f98a0d13f64d426be5f60110ef629bed8d871c6525c16d82
size 124596 size 124739

View File

@ -6241,9 +6241,10 @@ msgid ""
"support multiple open and the special has been used, the public account will " "support multiple open and the special has been used, the public account will "
"be used to connect" "be used to connect"
msgstr "" msgstr ""
"这些账号用于连接发布的应用,账号现在分为两种类型,一种是专用的,每个用户都有" "这些账号用于连接发布的应用,账号现在分为两种类型: <br/ >"
"一个专用账号。 另一种是公共的,当应用不支持多开且专用的已经被使用时,会使用公" "一种是专用的,每个用户都有一个专用账号。 "
"共账号连接" "另一种是公共的,当应用不支持多开且专用的已经被使用时,会使用公共账号连接; <br />"
"注意: 如果不开启自动创建账号, 当前发布机仅能被指定标签的资产调度到,默认不会放到调度池中"
#: terminal/serializers/applet_host.py:77 #: terminal/serializers/applet_host.py:77
msgid "The number of public accounts created automatically" msgid "The number of public accounts created automatically"

View File

@ -156,10 +156,11 @@ class Applet(JMSBaseModel):
spec_label = asset.labels.filter(name__in=['AppletHost', '发布机']).first() spec_label = asset.labels.filter(name__in=['AppletHost', '发布机']).first()
if spec_label: if spec_label:
host = [host for host in hosts if host.name == spec_label.value] matched = [host for host in hosts if host.name == spec_label.value]
if host: if matched:
return host[0] return matched[0]
hosts = [h for h in hosts if h.auto_create_accounts]
prefer_key = 'applet_host_prefer_{}'.format(user.id) prefer_key = 'applet_host_prefer_{}'.format(user.id)
prefer_host_id = cache.get(prefer_key, None) prefer_host_id = cache.get(prefer_key, None)
pref_host = [host for host in hosts if host.id == prefer_host_id] pref_host = [host for host in hosts if host.id == prefer_host_id]
@ -213,22 +214,26 @@ class Applet(JMSBaseModel):
private_account = valid_accounts.filter(username='js_{}'.format(user.username)).first() private_account = valid_accounts.filter(username='js_{}'.format(user.username)).first()
if not private_account: if not private_account:
logger.debug('Private account not found ...')
return None return None
# 优先使用 private account支持并发或者不支持并发时如果私有没有被占用则使用私有 # 优先使用 private account支持并发或者不支持并发时如果私有没有被占用则使用私有
account = None account = None
# 如果都支持,不管私有是否被占用,都使用私有 # 如果都支持,不管私有是否被占用,都使用私有
if all_can_concurrent: if all_can_concurrent:
logger.debug('All can concurrent, use private account')
account = private_account account = private_account
# 如果主机都不支持并发,则查询一下私有账号有没有任何应用使用,如果没有被使用,则使用私有 # 如果主机都不支持并发,则查询一下私有账号有没有任何应用使用,如果没有被使用,则使用私有
elif not host_can_concurrent: elif not host_can_concurrent:
private_using_key = self.accounts_using_key_tmpl.format(host.id, private_account.username, '*') private_using_key = self.accounts_using_key_tmpl.format(host.id, private_account.username, '*')
private_is_using = len(cache.keys(private_using_key, [])) > 0 private_is_using = len(cache.keys(private_using_key))
logger.debug("Private account is using: {}".format(private_is_using))
if not private_is_using: if not private_is_using:
account = private_account account = private_account
# 如果主机支持,但是应用不支持并发,则查询一下私有账号有没有被这个应用使用, 如果没有被使用,则使用私有 # 如果主机支持,但是应用不支持并发,则查询一下私有账号有没有被这个应用使用, 如果没有被使用,则使用私有
elif host_can_concurrent and not app_can_concurrent: elif host_can_concurrent and not app_can_concurrent:
private_app_using_key = self.accounts_using_key_tmpl.format(host.id, private_account.username, self.name) private_app_using_key = self.accounts_using_key_tmpl.format(host.id, private_account.username, self.name)
private_is_using_by_this_app = cache.get(private_app_using_key, False) private_is_using_by_this_app = cache.get(private_app_using_key, False)
logger.debug("Private account is using {} by {}".format(private_is_using_by_this_app, self.name))
if not private_is_using_by_this_app: if not private_is_using_by_this_app:
account = private_account account = private_account
return account return account
@ -236,24 +241,32 @@ class Applet(JMSBaseModel):
def select_host_account(self, user, asset): def select_host_account(self, user, asset):
# 选择激活的发布机 # 选择激活的发布机
host = self.select_host(user, asset) host = self.select_host(user, asset)
logger.info('Select applet host: {}'.format(host.name))
if not host: if not host:
return None return None
valid_accounts = host.accounts.all().filter(is_active=True, privileged=False) valid_accounts = host.accounts.all().filter(is_active=True, privileged=False)
account = self.try_to_use_private_account(user, host, valid_accounts) account = self.try_to_use_private_account(user, host, valid_accounts)
if not account: if not account:
logger.debug('No private account, try to use public account')
account = self.select_a_public_account(user, host, valid_accounts) account = self.select_a_public_account(user, host, valid_accounts)
if not account:
logger.debug('No available account for applet host: {}'.format(host.name))
return None
ttl = 60 * 60 * 24 ttl = 60 * 60 * 24
lock_key = self.accounts_using_key_tmpl.format(host.id, account.username, self.name) lock_key = self.accounts_using_key_tmpl.format(host.id, account.username, self.name)
cache.set(lock_key, account.username, ttl) cache.set(lock_key, account.username, ttl)
return { res = {
'host': host, 'host': host,
'account': account, 'account': account,
'lock_key': lock_key, 'lock_key': lock_key,
'ttl': ttl 'ttl': ttl
} }
logger.debug('Select host and account: {}'.format(res))
return res
def delete(self, using=None, keep_parents=False): def delete(self, using=None, keep_parents=False):
platform = self.get_related_platform() platform = self.get_related_platform()