-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interruptible throttle; DNS Resolver support filter #495
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ class throttle { | |
photon::semaphore sem; | ||
uint64_t last_retrieve = 0; | ||
uint64_t m_limit = -1UL; | ||
uint64_t m_limit_per_slice; | ||
uint64_t m_limit_per_slice = -1UL; | ||
uint64_t m_time_window; | ||
uint64_t m_time_window_per_slice; | ||
uint64_t m_slice_num; | ||
|
@@ -62,10 +62,8 @@ class throttle { | |
uint64_t fulfil_percent = get_fulfill_percent(prio); | ||
uint64_t starving_percent = m_starving_slice_percent[int(prio)]; | ||
|
||
// TODO: | ||
// if (unlikely(amount > m_limit && m_limit > 0)) { | ||
// return 0; | ||
// } | ||
// TODO: Handle the situation when throttle limit is extremely low | ||
assert(amount < m_limit); | ||
|
||
int ret = -1; | ||
int err = ETIMEDOUT; | ||
|
@@ -81,12 +79,16 @@ class throttle { | |
if (sem.count() * 100 < m_limit * fulfil_percent) { | ||
// Request are fulfilled only if they saw enough percent of tokens, | ||
// otherwise wait a `time_window_per_slice`. | ||
photon::thread_usleep(m_time_window_per_slice); | ||
ret = photon::thread_usleep(m_time_window_per_slice); | ||
if (ret != 0) { | ||
// Interrupted, just return | ||
return -1; | ||
} | ||
starving_slice_num++; | ||
continue; | ||
} | ||
break_starving: | ||
ret = sem.wait(amount, m_time_window_per_slice); | ||
ret = sem.wait_interruptible(amount, m_time_window_per_slice); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 可打断的限流在一些场合很有用,比如做了优先级限流之后,一些低优先级的任务在后台排队(睡眠),如果这时候又来了新的相同的高优先级任务,需要打断睡眠,相当于提高优先级。 |
||
err = errno; | ||
} while (ret < 0 && err == ETIMEDOUT); | ||
if (ret < 0) { | ||
|
@@ -136,7 +138,7 @@ class throttle { | |
} | ||
} | ||
|
||
uint64_t m_starving_slice_num[int(Priority::NumPriorities)]; | ||
uint64_t m_starving_slice_percent[int(Priority::NumPriorities)]; | ||
uint64_t m_starving_slice_num[int(Priority::NumPriorities)] = {}; | ||
uint64_t m_starving_slice_percent[int(Priority::NumPriorities)] = {}; | ||
}; | ||
} // namespace photon |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -264,24 +264,17 @@ class DefaultResolver : public Resolver { | |
IPAddrNode(IPAddr addr) : addr(addr) {} | ||
}; | ||
using IPAddrList = intrusive_list<IPAddrNode>; | ||
public: | ||
DefaultResolver(uint64_t cache_ttl, uint64_t resolve_timeout) | ||
: dnscache_(cache_ttl), resolve_timeout_(resolve_timeout) {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这些没变的话,就尽量不动 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 没动,只是把protected的函数移到了上面,就显得有变化 |
||
~DefaultResolver() { | ||
for (auto it : dnscache_) { | ||
((IPAddrList*)it->_obj)->delete_all(); | ||
} | ||
dnscache_.clear(); | ||
} | ||
|
||
IPAddr resolve(std::string_view host) override { | ||
IPAddr do_resolve(std::string_view host, Delegate<bool, IPAddr> filter) { | ||
auto ctr = [&]() -> IPAddrList* { | ||
auto addrs = new IPAddrList(); | ||
photon::semaphore sem; | ||
std::thread([&]() { | ||
auto now = std::chrono::steady_clock::now(); | ||
IPAddrList ret; | ||
auto cb = [&](IPAddr addr) { | ||
auto cb = [&](IPAddr addr) -> int { | ||
if (filter && !filter.fire(addr)) | ||
return 0; | ||
ret.push_back(new IPAddrNode(addr)); | ||
return 0; | ||
}; | ||
|
@@ -307,8 +300,22 @@ class DefaultResolver : public Resolver { | |
return ret->addr; | ||
} | ||
|
||
void resolve(std::string_view host, Delegate<void, IPAddr> func) override { | ||
func(resolve(host)); | ||
public: | ||
DefaultResolver(uint64_t cache_ttl, uint64_t resolve_timeout) | ||
: dnscache_(cache_ttl), resolve_timeout_(resolve_timeout) {} | ||
~DefaultResolver() { | ||
for (auto it : dnscache_) { | ||
((IPAddrList*)it->_obj)->delete_all(); | ||
} | ||
dnscache_.clear(); | ||
} | ||
|
||
IPAddr resolve(std::string_view host) override { | ||
return do_resolve(host, nullptr); | ||
} | ||
|
||
IPAddr resolve_filter(std::string_view host, Delegate<bool, IPAddr> filter) override { | ||
return do_resolve(host, filter); | ||
} | ||
|
||
void discard_cache(std::string_view host, IPAddr ip) override { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -157,8 +157,11 @@ class Resolver : public Object { | |
// When failed, return an Undefined IPAddr | ||
// Normally dns servers return multiple ips in random order, choosing the first one should suffice. | ||
virtual IPAddr resolve(std::string_view host) = 0; | ||
virtual void resolve(std::string_view host, Delegate<void, IPAddr> func) = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why old API have to be removed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 等于是用上面那个resolve的结果自己再执行一遍func? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. func(resolve(host)) is good enough (and used to be just implemented like this). |
||
virtual void discard_cache(std::string_view host, IPAddr ip = IPAddr()) = 0; // discard current cache of ip | ||
void resolve(std::string_view host, Delegate<void, IPAddr> func) { func(resolve(host)); } | ||
// If filter callback returns false, the IP will be abandoned. | ||
virtual IPAddr resolve_filter(std::string_view host, Delegate<bool, IPAddr> filter) = 0; | ||
// Discard cache of a hostname, ip can be specified | ||
virtual void discard_cache(std::string_view host, IPAddr ip = IPAddr()) = 0; | ||
}; | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1682,7 +1682,7 @@ R"( | |
splock.lock(); | ||
CURRENT->semaphore_count = count; | ||
int ret = 0; | ||
while (!try_substract(count)) { | ||
while (!try_subtract(count)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. substract is old English, which also appears in French and Spanish. In modern English it is subtract. |
||
ret = waitq::wait_defer(timeout, spinlock_unlock, &splock); | ||
ERRNO err; | ||
splock.lock(); | ||
|
@@ -1714,7 +1714,7 @@ R"( | |
prelocked_thread_interrupt(th, -1); | ||
} | ||
} | ||
bool semaphore::try_substract(uint64_t count) | ||
bool semaphore::try_subtract(uint64_t count) | ||
{ | ||
while(true) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
跟 alog-audit.h 统一
PhotonLibOS/common/alog-audit.h
Line 29 in 0db8545