You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by mz...@apache.org on 2019/09/23 20:43:09 UTC
[mesos] 02/04: Refactored framework role tracking logic in the
allocator.
This is an automated email from the ASF dual-hosted git repository.
mzhu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git
commit 81e10fc023cafda0570658dc7288c7b1f71df618
Author: Meng Zhu <mz...@mesosphere.io>
AuthorDate: Wed Sep 18 15:16:24 2019 -0700
Refactored framework role tracking logic in the allocator.
A framework is tracked under the role if the framework:
(1) is subscribed to the role;
Or
(2) has resources allocated under the role.
(2) could be true without (1). This is because we allow
frameworks to update their roles without revoking their
allocated or offered resources.
This patch recognizes this fact and encapsulates the related
checks in the helper.
Benchmark result: no major performance impact.
Master
BENCHMARK_HierarchicalAllocator_WithQuotaParam.LargeAndSmallQuota/2
Added 3000 agents in 90.816373ms
Added 3000 frameworks in 17.202199348secs
Made 3500 allocations in 15.46714944secs
Made 0 allocation in 13.767830924secs
Master + this patch:
BENCHMARK_HierarchicalAllocator_WithQuotaParam.LargeAndSmallQuota/2
Added 3000 agents in 86.782773ms
Added 3000 frameworks in 18.174924815secs
Made 3500 allocations in 15.813011454secs
Made 0 allocation in 12.882917161secs
Review: https://reviews.apache.org/r/71516
---
src/master/allocator/mesos/hierarchical.cpp | 64 +++++++++++++++--------------
src/master/allocator/mesos/hierarchical.hpp | 27 ++++++++----
2 files changed, 54 insertions(+), 37 deletions(-)
diff --git a/src/master/allocator/mesos/hierarchical.cpp b/src/master/allocator/mesos/hierarchical.cpp
index 256fdce..62750cc 100644
--- a/src/master/allocator/mesos/hierarchical.cpp
+++ b/src/master/allocator/mesos/hierarchical.cpp
@@ -633,7 +633,7 @@ void HierarchicalAllocatorProcess::addFramework(
const Framework& framework = *CHECK_NOTNONE(getFramework(frameworkId));
foreach (const string& role, framework.roles) {
- trackFrameworkUnderRole(frameworkId, role);
+ trackFrameworkUnderRole(framework, role);
Sorter* frameworkSorter = CHECK_NOTNONE(getFrameworkSorter(role));
@@ -699,7 +699,10 @@ void HierarchicalAllocatorProcess::removeFramework(
untrackAllocatedResources(slaveId, frameworkId, allocated);
}
- untrackFrameworkUnderRole(frameworkId, role);
+ CHECK(tryUntrackFrameworkUnderRole(framework, role))
+ << " Framework: " << frameworkId
+ << " role: " << role
+ << " allocation: " << allocation;
}
// Transfer ownership of this framework's metrics to
@@ -790,7 +793,8 @@ void HierarchicalAllocatorProcess::updateFramework(
// under the role because a framework can unsubscribe from a role
// while it still has resources allocated to the role.
if (!isFrameworkTrackedUnderRole(frameworkId, role)) {
- trackFrameworkUnderRole(frameworkId, role);
+ // TODO(mzhu): `CHECK` the above case.
+ trackFrameworkUnderRole(framework, role);
}
frameworkSorters.at(role)->activate(frameworkId.value());
@@ -801,11 +805,7 @@ void HierarchicalAllocatorProcess::updateFramework(
frameworkSorter->deactivate(frameworkId.value());
- // Stop tracking the framework under this role if there are
- // no longer any resources allocated to it.
- if (frameworkSorter->allocation(frameworkId.value()).empty()) {
- untrackFrameworkUnderRole(frameworkId, role);
- }
+ tryUntrackFrameworkUnderRole(framework, role);
if (framework.offerFilters.contains(role)) {
framework.offerFilters.erase(role);
@@ -1485,13 +1485,6 @@ void HierarchicalAllocatorProcess::recoverResources(
if (frameworkSorter->contains(frameworkId.value())) {
untrackAllocatedResources(slaveId, frameworkId, resources);
-
- // Stop tracking the framework under this role if it's no longer
- // subscribed and no longer has resources allocated to the role.
- if ((*framework)->roles.count(role) == 0 &&
- frameworkSorter->allocation(frameworkId.value()).empty()) {
- untrackFrameworkUnderRole(frameworkId, role);
- }
}
}
@@ -2768,7 +2761,7 @@ const Quota& HierarchicalAllocatorProcess::getQuota(const string& role) const
void HierarchicalAllocatorProcess::trackFrameworkUnderRole(
- const FrameworkID& frameworkId, const string& role)
+ const Framework& framework, const string& role)
{
CHECK(initialized);
@@ -2792,28 +2785,32 @@ void HierarchicalAllocatorProcess::trackFrameworkUnderRole(
}
}
- roleTree.trackFramework(frameworkId, role);
+ roleTree.trackFramework(framework.frameworkId, role);
Sorter* frameworkSorter = CHECK_NOTNONE(getFrameworkSorter(role));
- CHECK_NOT_CONTAINS(*frameworkSorter, frameworkId.value())
+ CHECK_NOT_CONTAINS(*frameworkSorter, framework.frameworkId.value())
<< " for role " << role;
- frameworkSorter->add(frameworkId.value());
+ frameworkSorter->add(framework.frameworkId.value());
}
-void HierarchicalAllocatorProcess::untrackFrameworkUnderRole(
- const FrameworkID& frameworkId, const string& role)
+bool HierarchicalAllocatorProcess::tryUntrackFrameworkUnderRole(
+ const Framework& framework, const string& role)
{
CHECK(initialized);
- roleTree.untrackFramework(frameworkId, role);
-
Sorter* frameworkSorter = CHECK_NOTNONE(getFrameworkSorter(role));
-
- CHECK_CONTAINS(*frameworkSorter, frameworkId.value())
+ CHECK_CONTAINS(*frameworkSorter, framework.frameworkId.value())
<< " for role " << role;
- frameworkSorter->remove(frameworkId.value());
+
+ if (!frameworkSorter->allocation(framework.frameworkId.value()).empty()) {
+ return false;
+ }
+
+ roleTree.untrackFramework(framework.frameworkId, role);
+
+ frameworkSorter->remove(framework.frameworkId.value());
if (roleTree.get(role).isNone() ||
(*roleTree.get(role))->frameworks().empty()) {
@@ -2821,6 +2818,8 @@ void HierarchicalAllocatorProcess::untrackFrameworkUnderRole(
roleSorter->remove(role);
frameworkSorters.erase(role);
}
+
+ return true;
}
@@ -2961,7 +2960,7 @@ void HierarchicalAllocatorProcess::trackAllocatedResources(
// or may not be subscribed to the role. Either way, we need to
// track the framework under the role.
if (!isFrameworkTrackedUnderRole(frameworkId, role)) {
- trackFrameworkUnderRole(frameworkId, role);
+ trackFrameworkUnderRole(*CHECK_NOTNONE(getFramework(frameworkId)), role);
}
CHECK_CONTAINS(*roleSorter, role);
@@ -2991,7 +2990,7 @@ void HierarchicalAllocatorProcess::untrackAllocatedResources(
// But currently, a slave is removed first via `removeSlave()`
// and later a call to `recoverResources()` occurs to recover
// the framework's resources.
- CHECK_CONTAINS(frameworks, frameworkId);
+ Framework* framework = CHECK_NOTNONE(getFramework(frameworkId));
// TODO(bmahler): Calling allocations() is expensive since it has
// to construct a map. Avoid this.
@@ -3007,10 +3006,15 @@ void HierarchicalAllocatorProcess::untrackAllocatedResources(
roleTree.untrackOfferedOrAllocated(allocation);
- frameworkSorter->unallocated(
- frameworkId.value(), slaveId, allocation);
+ frameworkSorter->unallocated(frameworkId.value(), slaveId, allocation);
roleSorter->unallocated(role, slaveId, allocation);
+
+ // If the framework is no longer subscribed to the role, we can try to
+ // untrack the framework under the role.
+ if (framework->roles.count(role) == 0) {
+ tryUntrackFrameworkUnderRole(*framework, role);
+ }
}
}
diff --git a/src/master/allocator/mesos/hierarchical.hpp b/src/master/allocator/mesos/hierarchical.hpp
index 5ea3791..36aa2fc 100644
--- a/src/master/allocator/mesos/hierarchical.hpp
+++ b/src/master/allocator/mesos/hierarchical.hpp
@@ -168,7 +168,16 @@ private:
// By default, weights == DEFAULT_WEIGHT == 1.0.
double weight_;
- // IDs of the frameworks subscribed to the role, if any.
+ // IDs of the frameworks tracked under the role, if any.
+ // A framework is tracked under the role if the framework:
+ //
+ // (1) is subscribed to the role;
+ // *OR*
+ // (2) has resources allocated under the role.
+ //
+ // NOTE: (2) could be true without (1). This is because the allocator
+ // interface allows for a framework role to be removed without recovering
+ // resources offered or allocated to this role.
hashset<FrameworkID> frameworks_;
// Total allocated or offered scalar resources to this role, including
@@ -773,13 +782,17 @@ private:
const Quota& getQuota(const std::string& role) const;
+ // Helpers to track and untrack a framework under a role.
+ // Frameworks should be tracked under a role either if it subscribes to the
+ // role *OR* it has resources allocated/offered to that role. when neither
+ // conditions are met, it should be untracked.
+ //
+ // `tryUntrackFrameworkUnderRole` returns true if the framework is untracked
+ // under the role.
void trackFrameworkUnderRole(
- const FrameworkID& frameworkId,
- const std::string& role);
-
- void untrackFrameworkUnderRole(
- const FrameworkID& frameworkId,
- const std::string& role);
+ const Framework& framework, const std::string& role);
+ bool tryUntrackFrameworkUnderRole(
+ const Framework& framework, const std::string& role);
void suppressRoles(Framework& framework, const std::set<std::string>& roles);
void reviveRoles(Framework& framework, const std::set<std::string>& roles);