-
Notifications
You must be signed in to change notification settings - Fork 33
/
TODO.moxi
328 lines (271 loc) · 11.3 KB
/
TODO.moxi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
moxi ideas, internals, notes...
moxi used to be called "cproxy".
TODO ideas...
- tests!
- add OS version to stats.
- histogram of request codes.
- histogram of response codes.
- stats of bandwidth
- stats of front cache bandwidth
- stats for inline latency, statistical
- key-level stats, by command, with bandwidth
- prefix stats [A-Za-z][A-Za-z0-9]+
- session stats (between session GET and SET)
- command pattern/signature stats
- between GET and SET
- cache miss latency, between GET miss and SET
- too many gettimeofday()'s?
- keepalive on the connections with a timer
- add stats to see if this is a problem?
- request retry
- revisit timeout/retry logic.
- revisit settings.verbose levels
- revisit error msg strings
- revisit DONE list, add tests as necessary
- optimization: have free item list per proxy_td
- so don't need to hit item/cache locks.
- optimization: use trond's allocator instead of malloc/free
- for multiget hashtable
- for multiget hashtable entries.
- failover/drain mode
- sort of an edge case of replication
- if we know a server's going to be going down in the future
and we know where keys should end up, do "simple"
cooling/warming-up replication.
- not so simple when new server goes down.
- or when old/new servers are flapping.
- or net-split.
- or different moxi/clients see different old/new servers.
- need configuration, possibly...
- svr-111
- host = aaa
- port = 11211
- drain = 222
- svr-222
- host = aaa
- port = 11211
- doxygen for moxi
- timeouts
- request is taking longer than X ms -- must be a failure.
- need timeout for upstream conns waiting in the queue
for an available downstream -- DONE
- if no downstreams are available, then upstream conn
might wait forever, if there's no timeout.
- need timeout for downstream requests -- DONE
- on timeout, closes the downstream connection
- pipelining/streaming
- instead of 100% store-and-forward
- store-and-forward is helpful for replay.
- use a tee design?
- per facebook conversation
- pipelining for GET value bodies.
- consider multiget key-deduplication case. Should work.
- consider non-uniform protocol case. Should work.
- need to keep item refcount sane.
- pipelining for SET value bodies.
- handling binary protocol
- on upstream
- on downstream - DONE
- when downstreams are not uniform protocol
- some ascii, some binary
- easiest - binary upstream and binary downstream
- binary quiet commands are similar to ascii noreply?
- there are state assumptions so we can't just
jump to another downstream.
- need to associate upstream with a favored downstream
- retry SET's and DELETE's
- so that upstream can continue fast and just fire-&-forget.
- but, need to respect serializability, similar to noreply bug?
- log and replay these?
- possibly in separate datacenter?
- 1000 customers per box -- php hosting scenario.
- fall back to set-password approach.
- use unix-domain-sockets, and filesystem security/access control.
- optimization to use SETQ for downstream binary SET's
- optimization: use opaque's instead of GETK during binary multiget smush.
- issue: ascii-to-ascii uses same codepath, and ascii doesn't have opaques.
- issue: non-uniform downstream would be more complicated
if we used opaques.
- authorization
- login/auth after creating downstream conn.
- PLAIN support - DONE.
- need mech support one day.
- should support more mech's later.
- should mcp/libconflate msgs have version numbers?
- added note to mcp issue tracker.
- message aggregation
- aka, get key squashing or key-dedupe.
- take popular get keys in wait queue and only get them once.
- think through binary get/getq,getk,getkq issues before
building this.
- because we want one codebase/logic that handles both
ascii and binary situations.
- might need to convert get/getq's into getk/getkq's
on the downstream.
- also think through protocol conversions,
with ascii on the front and binary on the back,
and vice versa.
- idea: if num(upstream_conn's) > 0 or need a inflight hashmap
- what if conn goes down during scatter/gather
==========================================================
below, "a2b" means ascii upstream to binary downstream...
scatter/gather-multiget
----------------------------------------------------------
a2a done
a2b easy, because we have all keys and can just
use getq+noop pattern. we don't need to use opaque
on the downstream conns.
a2ab need track the allowed protocols of downstream servers.
b2a need multiple read/nreads, so we can gather all
keys first until final upstream no-op or non-quiet get,
or see an upstream conn_closing.
then we can do a downstream multiget.
b2b need multiple read/nreads, so we can gather all
keys first until final upstream no-op or non-quiet get
or see an upstream conn_closing.
or, need noreply-style soft/hard affinity between
upstream and downstream with timeouts.
b2ab
key-squashing, when upstream protocols are uniform
----------------------------------------------------------
a2a easy, with inflight hashtable
a2b easy, with inflight hashtable
a2ab
b2a ascii has no opaques, so need to remember and match them.
b2b can't squash opaques, so need to remember them and rematch.
b2ab the inflight hashtable value shoul have...
upstream conns, and their opaques
- key squashing inflight hashtable might have bitfield values
that tell us which upstream conns are interested in
a particular key. (NO, too tricky, just use memory
like a normal person vs over-optimizing.)
- better stats
- hot keys
failure modes...
- downstream conn closes or in weird state (just close).
- normally, downstream *wants* to get to released state.
- it should end up there even when its upstream closes,
or when there are swallowable bytes that can
return the downstream conn to a conn_pause state.
- goal: no deadlock
- goal: no leak
- upstream sees what?
- depends on config?
- depends on the command that was inflight?
- depends on when the downstream failure was noticed?
- while reserving?
- while writing?
- while mwriting?
- while reading?
- while nreading?
- while alloc'ing?
- borrow failure recovery modes from spymemcached
- ISSUE: we don't see downstream conn close until we actually
try to read from the downstream conn, very late in state
machine.
- see the retry logic in on_close_downstream_conn().
- upstream *wants* to get to conn_new_cmd state,
after swallowing bad downstream data and sending an ERROR.
- when to reconnect?
- backoff period?
- borrowing from libmemcached to handle connects.
- when to failover?
- when to failback?
- when to report?
known bugs
- t/getset.t fails
- during a process_update_command(), when handling
a "set" that is too big (>1MB), the key is not
deleted on downstream server.
- noreply.t fails
- happens because we're using multiple downstreams for concurrency,
which is ok when using synchronous, request/response commands.
but, this breaks the serialized assumptions of noreplies.
- the same pattern here is needed for binary getq/getkq handling.
- solution 1 <<< this path needs timeout experimentation.
- keep upstream assigned to a downstream even after
the downstream write is done and the downstream
goes into conn_pause state. The upstream goes
into conn_new_cmd state.
also, put a timer to wake up so we can release
an unused downstream.
- negatives: a bunch of upstreams whose last action
was a noreply can really reduce throughput by
keeping their downstreams reserved and unavailable
to other clients.
- might never see this, depending on on the upstream
usage pattern. if the last thing upstream does
is fire off some noreply updates, it could be bad.
- also, the upstream conn will need a pointer to the
downstream its assigned to.
- also, more complexity when downstreams and upstreams go down.
- solution 2
- never use noreply for downstreams. always use
synchronous request/reply commands.
- negatives: this is always slow, rather than
just sometimes slow.
- positives: simpler. and, upstream conns don't
need pointer to downstream.
- solution 3
- keep upstream assigned to a preferred downstream,
but in a soft fashion.
- add a waiting_for_downstream_head/tail slot to downstream.
- allow downstream to be stealable on concurrency pressure.
- could really slow down an upstream that uses noreply,
if it has to wait for a specific downstream.
- but also keep others connects good.
- also, more complexity when downstreams and upstreams go down.
- also, need more pointers to track the assignment preference?
------------------------------------------------------------
- submodules, easy low-dependency build steps.
- git submodule and script magic to make the
right metaproject. this is proxybuild.
- need a faster way to test end-to-end, with mcp.
faster edit-compile-test-debug cycle
- servers owned by others.
- on proxy config change of a proxy's name, but which keeps the
same port as an old proxy, we should close any old
upstream connections.
- proxy shtudown thru agent_config doesn't close the
listening port?
- test command, described by dustina.
- ping timings
- time between request and response on each downstream conn.
- initial version DONE.
- need version that can use small "ping test" buckets.
- bucket selection
- after auth -- DONE.
- need server side of this.
------------------------------------------------------------
- FIXED: multiversioning.t fails / deadlocks
- when the cproxy is the final downstream.
- does not deadlock when a real memcached server
running in a separate process is the final downstream.
- FIXED: by putting libmemcached in noblock mode.
- DONE: upstream conn closes
- goal: any reserved downstreams do not leak
and, downstreams ideally go back into the free,
released list.
- upstream conn needs way to find its attached, reserved downstream.
- solution 1
- add an extra2 pointer to the conn?
- solution 2 << we choose this path.
- walk the reserved downstreams, comparing upstream_conn values.
- since upstream conn close is infrequent, this might be ok.
- need to see why else we'd need this.
- need to keep a reserved downstreams list? yes, we do this.
- also, need to remove the closing upstream conn from the wait list.
- done
- WONTFIX: change from proxy config keyed by port to keyed by name.
- actually, config algorithm key'ed by port is right.
- DONE: need debug/log in libconflate.
- DONE: agent_stats returns current config and VERSION.
- DONE: no thread-id in agent_stats. Now aggregating results.
- DONE: optimized connection to self, where moxi is running
as a memcached server.
- DONE: release downstreams back to head of list, not to tail
- DONE: make clock timer resolution configurable
- DONE: allow apikey to not be on the cmdline, instead optionally
readable from secure 600 file
- usage:
- moxi -z ./path/to/apikeyfile