morningman commented on PR #63363:
URL: https://github.com/apache/doris/pull/63363#issuecomment-5084049517

   ## 1. Fix the condition-variable lost-wakeup in the destructor (Medium)
   
   In `be/src/util/dns_cache.cpp`, the destructor sets `stop_refresh` and calls 
`_cv.notify_all()`
   **without holding `_cv_mutex`**:
   
   ```cpp
   DNSCache::~DNSCache() {
       stop_refresh = true;      // not under _cv_mutex
       _cv.notify_all();
       ...
   }
   ```
   
   The refresh thread waits with `_cv.wait_for(lk, 1min, [this]{ return 
stop_refresh.load(); })`. Even
   though `stop_refresh` is atomic, `std::condition_variable` requires the 
predicate to be mutated while
   holding the wait mutex; otherwise the notification can be lost if it lands 
in the window after the
   thread evaluates the predicate as `false` but before it actually blocks. 
When that happens the thread
   sleeps until the 1-minute timeout, so `~DNSCache()` stalls on `join()` for 
up to ~60 s at BE
   shutdown — defeating the whole reason for switching from `sleep_for` to a 
condition variable.
   
   **Fix** — set the flag under the lock, then notify:
   
   ```cpp
   DNSCache::~DNSCache() {
       {
           std::lock_guard<std::mutex> lk(_cv_mutex);
           stop_refresh = true;
       }
       _cv.notify_all();
       if (refresh_thread.joinable()) {
           refresh_thread.join();
       }
   }
   ```
   
   ## 2. Add a short negative-result cache to avoid blocking re-resolves after 
eviction (Medium)
   
   Before this PR, a host that had ever resolved stayed in the cache, so 
`get()` was a fast read-lock
   hit returning the (stale) IP instantly. After eviction the host is gone from 
the cache, so **every**
   subsequent `get()` falls through to `_update()` → `_resolve_hostname()` → 
`hostname_to_ip()`, which
   is a **blocking `getaddrinfo`** that can stall for seconds on a DNS timeout. 
There is no negative
   cache and no single-flight, so multiple caller threads asking for the same 
dead host each block on
   their own lookup. All callers hit this on the request path 
(`brpc_client_cache.h`, `client_cache.cpp`,
   `proto_util.h`, `peer_file_cache_reader.cpp`, `vtablet_writer.cpp`, and the 
cloud paths).
   
   In practice the impact is bounded — once a backend is dropped and the FE 
stops routing to it, callers
   stop asking — but during the transition this converts "fast stale-IP 
returns" into "repeated
   multi-second blocking resolves." Consider a small negative-result cache 
(remember "unresolvable until
   now + backoff", or keep a tombstone entry with a short retry interval) so an 
evicted-but-still-requested
   host returns an error cheaply instead of re-incurring a full DNS timeout on 
every call.
   
   
   ## 3. Reconcile the two configuration defaults (Low)
   
   With the shipped defaults `dns_cache_log_every_n_failures = 60` and
   `dns_cache_max_consecutive_failures = 30`, a cached host is evicted at 
failure 30 — before the
   `failures % 60 == 0` periodic log can ever fire. So on the cached-IP path 
only the first-failure log
   is emitted (then the eviction log), and `dns_cache_log_every_n_failures` 
effectively has no influence
   under defaults, which is surprising. Either document this interaction or 
default
   `dns_cache_log_every_n_failures <= dns_cache_max_consecutive_failures` so at 
least one periodic
   progress log appears before eviction.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to