-
Notifications
You must be signed in to change notification settings - Fork 140
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
Feat[MQB, MWC]: report the number of tcp connections #384
Changes from 1 commit
2ceb0f5
1a98e23
29506cc
d2171c8
3d29a39
3555a56
4cf0b83
0565d51
2e5e9e8
eff0b97
3c3025e
7f29d3a
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 | ||||
---|---|---|---|---|---|---|
|
@@ -59,6 +59,7 @@ | |||||
#include <bdlf_bind.h> | ||||||
#include <bdlf_placeholder.h> | ||||||
#include <bdlma_localsequentialallocator.h> | ||||||
#include <bdlpcre_regex.h> | ||||||
#include <bdlt_timeunitratio.h> | ||||||
#include <bsl_algorithm.h> | ||||||
#include <bsl_cstdlib.h> | ||||||
|
@@ -100,6 +101,21 @@ const int k_SESSION_DESTROY_WAIT = 20; | |||||
const int k_CLIENT_CLOSE_WAIT = 20; | ||||||
// Time to wait incrementally (in seconds) for all clients and | ||||||
// proxies to be destroyed during stop sequence. | ||||||
const char k_PORT_PATTERN[] = ":(\\d{1,5})"; | ||||||
|
||||||
bsl::string portFromUri(const bsl::string& endpoint) | ||||||
{ | ||||||
bdlpcre::RegEx regEx; | ||||||
bsl::string errorMessage; | ||||||
size_t errorOffset; | ||||||
std::vector<bsl::string_view> matchVector; | ||||||
|
||||||
BSLS_ASSERT_SAFE( | ||||||
0 == regEx.prepare(&errorMessage, &errorOffset, k_PORT_PATTERN)); | ||||||
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. It's not necessary to prepare the same |
||||||
BSLS_ASSERT_SAFE(0 == regEx.match(&matchVector, endpoint)); | ||||||
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. I think it's better to use |
||||||
|
||||||
return bsl::string(matchVector[1]); | ||||||
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. We can return a |
||||||
} | ||||||
|
||||||
char calculateInitialMissedHbCounter(const mqbcfg::TcpInterfaceConfig& config) | ||||||
{ | ||||||
|
@@ -280,36 +296,30 @@ TCPSessionFactory::channelStatContextCreator( | |||||
const bsl::shared_ptr<mwcio::Channel>& channel, | ||||||
const bsl::shared_ptr<mwcio::StatChannelFactoryHandle>& handle) | ||||||
{ | ||||||
mwcst::StatContext* parent = 0; | ||||||
|
||||||
int peerAddress; | ||||||
channel->properties().load(&peerAddress, k_CHANNEL_PROPERTY_PEER_IP); | ||||||
|
||||||
ntsa::Ipv4Address ipv4Address(static_cast<bsl::uint32_t>(peerAddress)); | ||||||
ntsa::IpAddress ipAddress(ipv4Address); | ||||||
if (!mwcio::ChannelUtil::isLocalHost(ipAddress)) { | ||||||
parent = d_statController_p->channelsStatContext( | ||||||
mqbstat::StatController::ChannelSelector::e_LOCAL); | ||||||
} | ||||||
else { | ||||||
parent = d_statController_p->channelsStatContext( | ||||||
mqbstat::StatController::ChannelSelector::e_REMOTE); | ||||||
} | ||||||
mqbstat::StatController::ChannelSelector::Enum selector = | ||||||
mwcio::ChannelUtil::isLocalHost(ipAddress) | ||||||
? mqbstat::StatController::ChannelSelector::e_REMOTE | ||||||
: mqbstat::StatController::ChannelSelector::e_LOCAL; | ||||||
|
||||||
BSLS_ASSERT_SAFE(parent); | ||||||
|
||||||
bsl::string name; | ||||||
bsl::string name, localPort; | ||||||
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. Would rather use the provided allocator. If we do so, we can see in the stats table any small allocations within this component, and debug it if needed
Suggested change
|
||||||
if (handle->options().is<mwcio::ConnectOptions>()) { | ||||||
name = handle->options().the<mwcio::ConnectOptions>().endpoint(); | ||||||
name = handle->options().the<mwcio::ConnectOptions>().endpoint(); | ||||||
localPort = portFromUri(channel->peerUri()); | ||||||
} | ||||||
else { | ||||||
name = channel->peerUri(); | ||||||
name = channel->peerUri(); | ||||||
localPort = portFromUri( | ||||||
handle->options().the<mwcio::ListenOptions>().endpoint()); | ||||||
} | ||||||
|
||||||
bdlma::LocalSequentialAllocator<2048> localAllocator(d_allocator_p); | ||||||
mwcst::StatContextConfiguration statConfig(name, &localAllocator); | ||||||
|
||||||
return parent->addSubcontext(statConfig); | ||||||
return d_statController_p->addChannelStatContext(selector, | ||||||
localPort, | ||||||
name); | ||||||
} | ||||||
|
||||||
void TCPSessionFactory::negotiate( | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -53,6 +53,7 @@ | |||||||||||||||||||||||
#include <bdlbb_blob.h> | ||||||||||||||||||||||||
#include <bdlf_bind.h> | ||||||||||||||||||||||||
#include <bdlf_placeholder.h> | ||||||||||||||||||||||||
#include <bdlma_localsequentialallocator.h> | ||||||||||||||||||||||||
#include <bdlmt_eventscheduler.h> | ||||||||||||||||||||||||
#include <bdlt_timeunitratio.h> | ||||||||||||||||||||||||
#include <bsl_algorithm.h> | ||||||||||||||||||||||||
|
@@ -81,6 +82,20 @@ const bsls::Types::Int64 k_NS_PER_MESSAGE = 15 * | |||||||||||||||||||||||
|
||||||||||||||||||||||||
const char k_PUBLISHINTERVAL_SUFFIX[] = ".PUBLISHINTERVAL"; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
void portsDeleter( | ||||||||||||||||||||||||
bsl::unordered_map<bsl::string, bslma::ManagedPtr<mwcst::StatContext> >* | ||||||||||||||||||||||||
map, | ||||||||||||||||||||||||
bslmt::Mutex* mutex, | ||||||||||||||||||||||||
const mwcst::StatContext& context) | ||||||||||||||||||||||||
{ | ||||||||||||||||||||||||
// Lookup the port's StatContext and remove it from the 'map' | ||||||||||||||||||||||||
bslmt::LockGuard<bslmt::Mutex> guard(mutex); // LOCK | ||||||||||||||||||||||||
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. With this change, you introduce a synchronization between different threads. We might assume it's okay, but if it's not, it's difficult to diagnose. I think it's possible to avoid this, by storing 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. Unfortunately, the threadsafety of blazingmq/src/groups/mwc/mwcst/mwcst_statcontext.h Lines 96 to 98 in 7d4b3d7
For example, I can't iterate over subcontexts that can be added/deleted without additional synchronisation anywhere except the snapshot() method or its synchronious pre- or post- steps, as handling the deleted subcontexts happens inside this method. Please find below some arguments in favor of the current imlementation:Each channel stores its own StatContext , and this approach hasn't changed. What I have done is another 'layer' of StatContext s between channel contexts and their parent. This layer serves for breaking down the channels stats by ports. I really need to have only one StatContext for each port as I report aggregated stats. The inter-thread synchronisation is required here, because:
So, in order to add a channel StatContext, I need to check if there is a port StatContext for that port and use it, otherways I have to create a new port If you have an idea how to reach it without the synchronization, please let me know 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.
@waldgange let me think about this for some time 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. Hi @waldgange blazingmq/src/groups/mwc/mwcio/mwcio_statchannelfactory.cpp Lines 126 to 133 in a6a6cef
So, Note that it requires to change |
||||||||||||||||||||||||
if (context.numSnapshots() != 0 && !context.isDeleted() && | ||||||||||||||||||||||||
context.numSubcontexts() == 0) { | ||||||||||||||||||||||||
map->erase(context.name()); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
typedef bsl::unordered_set<mqbplug::PluginFactory*> PluginFactories; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
/// Post on the optionally specified `semaphore`. | ||||||||||||||||||||||||
|
@@ -983,5 +998,43 @@ int StatController::processCommand( | |||||||||||||||||||||||
return -1; | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
StatController::StatContextMp | ||||||||||||||||||||||||
StatController::addChannelStatContext(ChannelSelector::Enum selector, | ||||||||||||||||||||||||
const bsl::string& port, | ||||||||||||||||||||||||
const bsl::string& endpoint) | ||||||||||||||||||||||||
{ | ||||||||||||||||||||||||
mwcst::StatContext* parent = channelsStatContext(selector); | ||||||||||||||||||||||||
BSLS_ASSERT_SAFE(parent); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
bdlma::LocalSequentialAllocator<2048> localAllocator(d_allocator_p); | ||||||||||||||||||||||||
mwcst::StatContextConfiguration portConfig(port, &localAllocator); | ||||||||||||||||||||||||
mwcst::StatContextConfiguration statConfig(endpoint, &localAllocator); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
bslma::ManagedPtr<mwcst::StatContext> channelStatContext; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
{ | ||||||||||||||||||||||||
bslmt::LockGuard<bslmt::Mutex> guard(&d_portsMutex); // LOCK | ||||||||||||||||||||||||
StatContextMap::iterator portIt = d_portsMap.find(port); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
if (portIt == d_portsMap.end()) { | ||||||||||||||||||||||||
bslma::ManagedPtr<mwcst::StatContext> portStatContext = | ||||||||||||||||||||||||
parent->addSubcontext( | ||||||||||||||||||||||||
portConfig.storeExpiredSubcontextValues(true) | ||||||||||||||||||||||||
.preSnapshotCallback( | ||||||||||||||||||||||||
bdlf::BindUtil::bind(portsDeleter, | ||||||||||||||||||||||||
&d_portsMap, | ||||||||||||||||||||||||
&d_portsMutex, | ||||||||||||||||||||||||
bdlf::PlaceHolders::_1))); | ||||||||||||||||||||||||
channelStatContext = portStatContext->addSubcontext(statConfig); | ||||||||||||||||||||||||
d_portsMap.emplace(portStatContext->name(), portStatContext); | ||||||||||||||||||||||||
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. Unfortunately, it doesn't compile on
You might introduce parallel structures Or you might find another solution |
||||||||||||||||||||||||
} | ||||||||||||||||||||||||
else { | ||||||||||||||||||||||||
channelStatContext = portIt->second->addSubcontext(statConfig); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
return channelStatContext; | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
} // close package namespace | ||||||||||||||||||||||||
} // close enterprise namespace |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,11 +81,12 @@ StatChannel::StatChannel(const StatChannelConfig& config, | |
{ | ||
// PRECONDITIONS | ||
BSLS_ASSERT_SAFE(config.d_statContext_sp); | ||
d_config.d_statContext_sp->adjustValue(Stat::e_CONNECTIONS, 1); | ||
} | ||
|
||
StatChannel::~StatChannel() | ||
{ | ||
// NOTHING | ||
d_config.d_statContext_sp->adjustValue(Stat::e_CONNECTIONS, -1); | ||
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. If we do per-channel stat contexts, then the number of connections will always be 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. Correct, I utilize the aggregation functionality Of StatContextTable here in order to deal only with the Channel's StatContext here. Otherways I would have to deal with its parent (port's |
||
} | ||
|
||
// MANIPULATORS | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -799,6 +799,10 @@ class StatContext { | |||||||||||||||
/// all sibling subcontexts. | ||||||||||||||||
int uniqueId() const; | ||||||||||||||||
|
||||||||||||||||
/// Return te number of times this 'StatContext' had 'snapshot' called on | ||||||||||||||||
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.
Suggested change
|
||||||||||||||||
/// it. | ||||||||||||||||
bsls::Types::Int64 numSnapshots() const; | ||||||||||||||||
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. This is useful, but also it's an interface change in 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. I need to check it in
Then it moves them to d_statContext vector on next StatContext::snapshot()
However StatContext::numSubcontexts() doesn't take into account d_newSubcontext and will return 0 if there haven't been any stapshots yet.blazingmq/src/groups/mwc/mwcst/mwcst_statcontext.h Lines 1136 to 1140 in 7d4b3d7
So if we don't check the number of snapshots in portsDeleter() we can unintentionally delete the StatContext that has just been added.
|
||||||||||||||||
|
||||||||||||||||
/// Return the number of subcontexts held by this `StatContext` | ||||||||||||||||
int numSubcontexts() const; | ||||||||||||||||
|
||||||||||||||||
|
@@ -1133,6 +1137,11 @@ inline int StatContext::uniqueId() const | |||||||||||||||
return d_uniqueId; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
inline bsls::Types::Int64 StatContext::numSnapshots() const | ||||||||||||||||
{ | ||||||||||||||||
return d_numSnapshots; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
inline int StatContext::numSubcontexts() const | ||||||||||||||||
{ | ||||||||||||||||
return static_cast<int>(d_subcontexts.size() + | ||||||||||||||||
|
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.