Skip to content

Commit 328b9de

Browse files
anmolnarphunt
authored andcommitted
ZOOKEEPER-2940: Deal with maxbuffer as it relates to large requests from clients
https://issues.apache.org/jira/browse/ZOOKEEPER-2940 This PR covers the other part of Jute buffer monitoring which relates to client response sizes. `jute.maxbuffer` is often set too small or the default (4MB) value is not enough to receive large responses from the server which causes the client unable to operate. e.g. `getChildren()` on a node which has lots of children or execution of a large multi. These new metrics lets operators to monitor the size of generated responses to get an idea on how to properly set client's `jute.maxbuffer`. The other part of monitoring which relates to proposal size has already been merged apache#415 Author: Andor Molnar <[email protected]> Reviewers: [email protected] Closes apache#466 from anmolnar/ZOOKEEPER-2940 and squashes the following commits: 29224d0 [Andor Molnar] ZOOKEEPER-2940. Test fixes 486d496 [Andor Molnar] ZOOKEEPER-2940. Removed support of 4lw commands, because master is targeted 60916e0 [Andor Molnar] ZOOKEEPER-2940. Code review fixes b39c4c8 [Andor Molnar] ZOOKEEPER-2940. Code review: variable names renamed to proposalStats 87e72ff [Andor Molnar] ZOOKEEPER-2940. Some code review cleanups 6f0adb1 [Andor Molnar] ZOOKEEPER-2940. Code review fixes: stats class renamed, added comments to unit test asserts, updated docs bcb6d4c [Andor Molnar] ZOOKEEPER-2940. Added new metrics to python files 77a5f0a [Andor Molnar] ZOOKEEPER-2940. Fixed failing unit tests 2def61c [Andor Molnar] ZOOKEEPER-2940. Track size of client responses Change-Id: I68df371097cc355b1f41b8dbb0168da4fa5dee43
1 parent c2e7ed1 commit 328b9de

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+368
-199
lines changed

docs/index.pdf

0 Bytes
Binary file not shown.

docs/javaExample.pdf

0 Bytes
Binary file not shown.

docs/linkmap.pdf

0 Bytes
Binary file not shown.

docs/recipes.pdf

0 Bytes
Binary file not shown.

docs/zookeeperAdmin.html

+38-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,9 @@ <h3 class="h4">Clustered (Multi-Server) Setup</h3>
638638
consists of a single line containing only the text of that machine's
639639
id. So <span class="codefrag filename">myid</span> of server 1 would contain the text
640640
"1" and nothing else. The id must be unique within the
641-
ensemble and should have a value between 1 and 255.</p>
641+
ensemble and should have a value between 1 and 255. <strong>IMPORTANT:</strong> if you
642+
enable extended features such as TTL Nodes (see below) the id must be
643+
between 1 and 254 due to internal limitations.</p>
642644

643645
</li>
644646

@@ -1345,6 +1347,37 @@ <h4>Advanced Configuration</h4>
13451347
feature. Default is "true"</p>
13461348
</dd>
13471349

1350+
1351+
<dt>
1352+
<term>zookeeper.extendedTypesEnabled</term>
1353+
</dt>
1354+
<dd>
1355+
<p>(Java system property only: <strong>zookeeper.extendedTypesEnabled</strong>)</p>
1356+
<p>
1357+
<strong>New in 3.5.4, 3.6.0:</strong> Define to "true" to enable
1358+
extended features such as the creation of <a href="zookeeperProgrammers.html#TTL+Nodes">TTL Nodes</a>.
1359+
They are disabled by default. IMPORTANT: when enabled server IDs must
1360+
be less than 255 due to internal limitations.
1361+
</p>
1362+
</dd>
1363+
1364+
1365+
<dt>
1366+
<term>zookeeper.emulate353TTLNodes</term>
1367+
</dt>
1368+
<dd>
1369+
<p>(Java system property only: <strong>zookeeper.emulate353TTLNodes</strong>)</p>
1370+
<p>
1371+
<strong>New in 3.5.4, 3.6.0:</strong> Due to
1372+
<a href="https://issues.apache.org/jira/browse/ZOOKEEPER-2901">ZOOKEEPER-2901</a> TTL nodes
1373+
created in version 3.5.3 are not supported in 3.5.4/3.6.0. However, a workaround is provided via the
1374+
zookeeper.emulate353TTLNodes system property. If you used TTL nodes in ZooKeeper 3.5.3 and need to maintain
1375+
compatibility set <strong>zookeeper.emulate353TTLNodes</strong> to "true" in addition to
1376+
<strong>zookeeper.extendedTypesEnabled</strong>. NOTE: due to the bug, server IDs
1377+
must be 127 or less. Additionally, the maximum support TTL value is 1099511627775 which is smaller
1378+
than what was allowed in 3.5.3 (1152921504606846975)</p>
1379+
</dd>
1380+
13481381

13491382
</dl>
13501383
<a name="sc_clusterOptions"></a>
@@ -2216,6 +2249,7 @@ <h4>The Four Letter Words</h4>
22162249
zk_min_latency 0
22172250
zk_packets_received 70
22182251
zk_packets_sent 69
2252+
zk_num_alive_connections 1
22192253
zk_outstanding_requests 0
22202254
zk_server_state leader
22212255
zk_znode_count 4
@@ -2227,6 +2261,9 @@ <h4>The Four Letter Words</h4>
22272261
zk_pending_syncs 0 - only exposed by the Leader
22282262
zk_open_file_descriptor_count 23 - only available on Unix platforms
22292263
zk_max_file_descriptor_count 1024 - only available on Unix platforms
2264+
zk_last_proposal_size 23
2265+
zk_min_proposal_size 23
2266+
zk_max_proposal_size 64
22302267
</pre>
22312268
<p>The output is compatible with java properties format and the content
22322269
may change over time (new keys added). Your scripts should expect changes.</p>

docs/zookeeperAdmin.pdf

2.31 KB
Binary file not shown.

docs/zookeeperHierarchicalQuorums.pdf

0 Bytes
Binary file not shown.

docs/zookeeperInternals.pdf

0 Bytes
Binary file not shown.

docs/zookeeperJMX.pdf

0 Bytes
Binary file not shown.

docs/zookeeperObservers.pdf

0 Bytes
Binary file not shown.

docs/zookeeperOver.pdf

0 Bytes
Binary file not shown.

docs/zookeeperProgrammers.html

+4
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,10 @@ <h4>TTL Nodes</h4>
596596
you can optionally set a TTL in milliseconds for the znode. If the znode
597597
is not modified within the TTL and has no children it will become a candidate
598598
to be deleted by the server at some point in the future.</p>
599+
<p>Note: TTL Nodes must be enabled via System property as
600+
they are disabled by default. See the <a href="zookeeperAdmin.html#sc_configuration">Administrator's
601+
Guide</a> for details. If you attempt to create TTL Nodes without the proper System property set the server
602+
will throw <em>KeeperException.UnimplementedException</em>.</p>
599603
<a name="sc_timeInZk"></a>
600604
<h3 class="h4">Time in ZooKeeper</h3>
601605
<p>ZooKeeper tracks time multiple ways:</p>

docs/zookeeperProgrammers.pdf

580 Bytes
Binary file not shown.

docs/zookeeperQuotas.pdf

0 Bytes
Binary file not shown.

docs/zookeeperReconfig.pdf

0 Bytes
Binary file not shown.

docs/zookeeperStarted.pdf

0 Bytes
Binary file not shown.

docs/zookeeperTutorial.pdf

0 Bytes
Binary file not shown.

src/contrib/monitoring/check_zookeeper.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,14 @@ def _parse_stat(self, data):
293293
result['zk_zxid_epoch'] = int(m.group(1), 16) >>32 # high 32 bits
294294
continue
295295

296-
return result
296+
m = re.match('Proposal sizes last/min/max: (\d+)/(\d+)/(\d+)', line)
297+
if m is not None:
298+
result['zk_last_proposal_size'] = int(m.group(1))
299+
result['zk_min_proposal_size'] = int(m.group(2))
300+
result['zk_max_proposal_size'] = int(m.group(3))
301+
continue
302+
303+
return result
297304

298305
def _parse_line(self, line):
299306
try:

src/contrib/monitoring/ganglia/zookeeper.pyconf

+3
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,8 @@ collection_group {
4646
metric { name = "zk_followers" }
4747
metric { name = "zk_synced_followers" }
4848
metric { name = "zk_pending_syncs" }
49+
metric { name = "zk_last_proposal_size" }
50+
metric { name = "zk_min_proposal_size" }
51+
metric { name = "zk_max_proposal_size" }
4952
}
5053

src/contrib/monitoring/ganglia/zookeeper_ganglia.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,10 @@ def metric_init(params=None):
214214
'zk_max_file_descriptor_count': {'units': 'descriptors'},
215215
'zk_followers': {'units': 'nodes'},
216216
'zk_synced_followers': {'units': 'nodes'},
217-
'zk_pending_syncs': {'units': 'syncs'}
217+
'zk_pending_syncs': {'units': 'syncs'},
218+
'zk_last_proposal_size': {'units': 'bytes'},
219+
'zk_min_proposal_size': {'units': 'bytes'},
220+
'zk_max_proposal_size': {'units': 'bytes'}
218221
}
219222
metric_handler.descriptors = {}
220223
for name, updates in metrics.iteritems():

src/java/main/org/apache/zookeeper/ClientCnxnSocket.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ void updateLastSendAndHeard() {
115115
this.lastHeard = now;
116116
}
117117

118-
protected void readLength() throws IOException {
118+
void readLength() throws IOException {
119119
int len = incomingBuffer.getInt();
120120
if (len < 0 || len >= packetLen) {
121121
throw new IOException("Packet len " + len + " is out of range!");

src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java

+1-19
Original file line numberDiff line numberDiff line change
@@ -678,8 +678,6 @@ public static void closeSock(SocketChannel sock) {
678678
}
679679
}
680680

681-
private final static byte fourBytes[] = new byte[4];
682-
683681
/*
684682
* (non-Javadoc)
685683
*
@@ -689,23 +687,7 @@ public static void closeSock(SocketChannel sock) {
689687
@Override
690688
public void sendResponse(ReplyHeader h, Record r, String tag) {
691689
try {
692-
ByteArrayOutputStream baos = new ByteArrayOutputStream();
693-
// Make space for length
694-
BinaryOutputArchive bos = BinaryOutputArchive.getArchive(baos);
695-
try {
696-
baos.write(fourBytes);
697-
bos.writeRecord(h, "header");
698-
if (r != null) {
699-
bos.writeRecord(r, tag);
700-
}
701-
baos.close();
702-
} catch (IOException e) {
703-
LOG.error("Error serializing response");
704-
}
705-
byte b[] = baos.toByteArray();
706-
ByteBuffer bb = ByteBuffer.wrap(b);
707-
bb.putInt(b.length - 4).rewind();
708-
sendBuffer(bb);
690+
super.sendResponse(h, r, tag);
709691
if (h.getXid() > 0) {
710692
// check throttling
711693
if (outstandingRequests.decrementAndGet() < 1 ||

src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java

+1-18
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ public void process(WatchedEvent event) {
160160
}
161161
}
162162

163-
private static final byte[] fourBytes = new byte[4];
164163
static class ResumeMessageEvent implements MessageEvent {
165164
Channel channel;
166165
ResumeMessageEvent(Channel channel) {
@@ -182,23 +181,7 @@ public void sendResponse(ReplyHeader h, Record r, String tag)
182181
if (closingChannel || !channel.isOpen()) {
183182
return;
184183
}
185-
ByteArrayOutputStream baos = new ByteArrayOutputStream();
186-
// Make space for length
187-
BinaryOutputArchive bos = BinaryOutputArchive.getArchive(baos);
188-
try {
189-
baos.write(fourBytes);
190-
bos.writeRecord(h, "header");
191-
if (r != null) {
192-
bos.writeRecord(r, tag);
193-
}
194-
baos.close();
195-
} catch (IOException e) {
196-
LOG.error("Error serializing response");
197-
}
198-
byte b[] = baos.toByteArray();
199-
ByteBuffer bb = ByteBuffer.wrap(b);
200-
bb.putInt(b.length - 4).rewind();
201-
sendBuffer(bb);
184+
super.sendResponse(h, r, tag);
202185
if (h.getXid() > 0) {
203186
// zks cannot be null otherwise we would not have gotten here!
204187
if (!zkServer.shouldThrottle(outstandingCount.decrementAndGet())) {

src/java/main/org/apache/zookeeper/server/ServerCnxn.java

+26-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
package org.apache.zookeeper.server;
2020

21+
import java.io.ByteArrayOutputStream;
2122
import java.io.IOException;
2223
import java.io.PrintWriter;
2324
import java.io.StringWriter;
@@ -34,6 +35,7 @@
3435
import java.util.concurrent.ConcurrentHashMap;
3536
import java.util.concurrent.atomic.AtomicLong;
3637

38+
import org.apache.jute.BinaryOutputArchive;
3739
import org.apache.jute.Record;
3840
import org.apache.zookeeper.WatchedEvent;
3941
import org.apache.zookeeper.Watcher;
@@ -55,6 +57,8 @@ public abstract class ServerCnxn implements Stats, Watcher {
5557

5658
private Set<Id> authInfo = Collections.newSetFromMap(new ConcurrentHashMap<Id, Boolean>());
5759

60+
private static final byte[] fourBytes = new byte[4];
61+
5862
/**
5963
* If the client is of old version, we don't send r-o mode info to it.
6064
* The reason is that if we would, old C client doesn't read it, which
@@ -66,8 +70,26 @@ public abstract class ServerCnxn implements Stats, Watcher {
6670

6771
abstract void close();
6872

69-
public abstract void sendResponse(ReplyHeader h, Record r, String tag)
70-
throws IOException;
73+
public void sendResponse(ReplyHeader h, Record r, String tag) throws IOException {
74+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
75+
// Make space for length
76+
BinaryOutputArchive bos = BinaryOutputArchive.getArchive(baos);
77+
try {
78+
baos.write(fourBytes);
79+
bos.writeRecord(h, "header");
80+
if (r != null) {
81+
bos.writeRecord(r, tag);
82+
}
83+
baos.close();
84+
} catch (IOException e) {
85+
LOG.error("Error serializing response");
86+
}
87+
byte b[] = baos.toByteArray();
88+
serverStats().updateClientResponseSize(b.length - 4);
89+
ByteBuffer bb = ByteBuffer.wrap(b);
90+
bb.putInt(b.length - 4).rewind();
91+
sendBuffer(bb);
92+
}
7193

7294
/* notify the client the session is closing and close/cleanup socket */
7395
abstract void sendCloseSession();
@@ -133,12 +155,12 @@ protected void packetSent() {
133155
incrPacketsSent();
134156
ServerStats serverStats = serverStats();
135157
if (serverStats != null) {
136-
serverStats().incrementPacketsSent();
158+
serverStats.incrementPacketsSent();
137159
}
138160
}
139161

140162
protected abstract ServerStats serverStats();
141-
163+
142164
protected final Date established = new Date();
143165

144166
protected final AtomicLong packetsReceived = new AtomicLong();

src/java/main/org/apache/zookeeper/server/ServerStats.java

+15
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@
2121

2222

2323
import org.apache.zookeeper.common.Time;
24+
import org.apache.zookeeper.server.quorum.BufferStats;
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
2427

2528
import java.util.concurrent.atomic.AtomicLong;
2629

2730
/**
2831
* Basic Server Statistics
2932
*/
3033
public class ServerStats {
34+
private static final Logger LOG = LoggerFactory.getLogger(ServerStats.class);
35+
3136
private long packetsSent;
3237
private long packetsReceived;
3338
private long maxLatency;
@@ -36,6 +41,8 @@ public class ServerStats {
3641
private long count = 0;
3742
private AtomicLong fsyncThresholdExceedCount = new AtomicLong(0);
3843

44+
private final BufferStats clientResponseStats = new BufferStats();
45+
3946
private final Provider provider;
4047

4148
public interface Provider {
@@ -167,6 +174,14 @@ public void resetFsyncThresholdExceedCount() {
167174
synchronized public void reset() {
168175
resetLatency();
169176
resetRequestCounters();
177+
clientResponseStats.reset();
170178
}
171179

180+
public void updateClientResponseSize(int size) {
181+
clientResponseStats.setLastBufferSize(size);
182+
}
183+
184+
public BufferStats getClientResponseStats() {
185+
return clientResponseStats;
186+
}
172187
}

src/java/main/org/apache/zookeeper/server/ZooKeeperServerBean.java

+15
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,19 @@ public long getTxnLogElapsedSyncTime() {
182182
public int getJuteMaxBufferSize() {
183183
return BinaryInputArchive.maxBuffer;
184184
}
185+
186+
@Override
187+
public int getLastClientResponseSize() {
188+
return zks.serverStats().getClientResponseStats().getLastBufferSize();
189+
}
190+
191+
@Override
192+
public int getMinClientResponseSize() {
193+
return zks.serverStats().getClientResponseStats().getMinBufferSize();
194+
}
195+
196+
@Override
197+
public int getMaxClientResponseSize() {
198+
return zks.serverStats().getClientResponseStats().getMaxBufferSize();
199+
}
185200
}

src/java/main/org/apache/zookeeper/server/ZooKeeperServerMXBean.java

+15
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,19 @@ public interface ZooKeeperServerMXBean {
143143
* @return Returns the value of the following config setting: jute.maxbuffer
144144
*/
145145
public int getJuteMaxBufferSize();
146+
147+
/**
148+
* @return size of latest generated client response
149+
*/
150+
public int getLastClientResponseSize();
151+
152+
/**
153+
* @return size of smallest generated client response
154+
*/
155+
public int getMinClientResponseSize();
156+
157+
/**
158+
* @return size of largest generated client response
159+
*/
160+
public int getMaxClientResponseSize();
146161
}

src/java/main/org/apache/zookeeper/server/admin/Commands.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -330,12 +330,20 @@ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs)
330330
response.put("open_file_descriptor_count", osMbean.getOpenFileDescriptorCount());
331331
response.put("max_file_descriptor_count", osMbean.getMaxFileDescriptorCount());
332332

333+
response.put("last_client_response_size", stats.getClientResponseStats().getLastBufferSize());
334+
response.put("max_client_response_size", stats.getClientResponseStats().getMaxBufferSize());
335+
response.put("min_client_response_size", stats.getClientResponseStats().getMinBufferSize());
336+
333337
if (zkServer instanceof LeaderZooKeeperServer) {
334338
Leader leader = ((LeaderZooKeeperServer) zkServer).getLeader();
335339

336340
response.put("followers", leader.getLearners().size());
337341
response.put("synced_followers", leader.getForwardingFollowers().size());
338342
response.put("pending_syncs", leader.getNumPendingSyncs());
343+
344+
response.put("last_proposal_size", leader.getProposalStats().getLastBufferSize());
345+
response.put("max_proposal_size", leader.getProposalStats().getMaxBufferSize());
346+
response.put("min_proposal_size", leader.getProposalStats().getMinBufferSize());
339347
}
340348

341349
return response;
@@ -415,9 +423,13 @@ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs)
415423
response.put("version", Version.getFullVersion());
416424
response.put("read_only", zkServer instanceof ReadOnlyZooKeeperServer);
417425
response.put("server_stats", zkServer.serverStats());
426+
response.put("client_response", zkServer.serverStats().getClientResponseStats());
427+
if (zkServer instanceof LeaderZooKeeperServer) {
428+
Leader leader = ((LeaderZooKeeperServer)zkServer).getLeader();
429+
response.put("proposal_stats", leader.getProposalStats());
430+
}
418431
response.put("node_count", zkServer.getZKDatabase().getNodeCount());
419432
return response;
420-
421433
}
422434
}
423435

src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ public void commandRun() {
7575
print("synced_followers", leader.getForwardingFollowers().size());
7676
print("pending_syncs", leader.getNumPendingSyncs());
7777

78-
print("last_proposal_size", leader.getProposalStats().getLastProposalSize());
79-
print("max_proposal_size", leader.getProposalStats().getMaxProposalSize());
80-
print("min_proposal_size", leader.getProposalStats().getMinProposalSize());
78+
print("last_proposal_size", leader.getProposalStats().getLastBufferSize());
79+
print("max_proposal_size", leader.getProposalStats().getMaxBufferSize());
80+
print("min_proposal_size", leader.getProposalStats().getMinBufferSize());
8181
}
8282
}
8383

0 commit comments

Comments
 (0)