~jan-kneschke/mysql-proxy/packet-tracking-assertions

« back to all changes in this revision

Viewing changes to doc/architecture.txt

  • Committer: Kay Roepke
  • Date: 2009-06-03 12:51:29 UTC
  • mto: This revision was merged to the branch mainline in revision 639.
  • Revision ID: kay@sun.com-20090603125129-26oso9ov7yinwocg
add autoconf/aclocal files we should never commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
@li query analysis
12
12
@li ... and much more
13
13
 
14
 
Internally the MySQL Proxy is a stack of:
15
 
 
16
 
@dotfile architecture-overview.dot
17
 
 
18
 
It is based on a @subpage page-core that exposes the phases of the
19
 
@subpage protocol to a @ref page-plugins.
20
 
 
21
 
@dot
22
 
digraph {
23
 
connect -> auth;
24
 
auth -> command;
25
 
command -> disconnect;
26
 
command -> command;
27
 
connect -> disconnect;
28
 
auth -> disconnect;
29
 
}
30
 
 
31
 
@enddot
32
 
 
33
 
Each of the phases of the life-cycle lead to several more protocol-states. For example the auth phase is made up of at least 3 packets:
34
 
 
35
 
@msc
36
 
        Client, Proxy, Server;
37
 
 
38
 
        Client -> Proxy [ label = "accept()" ];
39
 
        Proxy -> Proxy [ label = "script: connect_server()" ];
40
 
        Proxy -> Server [ label = "connect()" ];
41
 
        ...;
42
 
        Server -> Proxy [ label = "recv(auth-challenge)" ];
43
 
        Proxy -> Proxy [ label = "script: read_handshake()" ];
44
 
        Proxy -> Client [ label = "send(auth-challenge)" ];
45
 
        Client -> Proxy [ label = "recv(auth-response)" ];
46
 
        Proxy -> Proxy [ label = "script: read_auth()" ];
47
 
        Server -> Proxy [ label = "send(auth-response)" ];
48
 
        Server -> Proxy [ label = "recv(auth-result)" ];
49
 
        Proxy -> Proxy [ label = "script: read_auth_result()" ];
50
 
        Proxy -> Client [ label = "send(auth-result)" ];
51
 
        ...;
52
 
        
53
 
@endmsc
54
 
 
55
 
While the @ref page-core is scalable to a larger number of connections, the plugin/scripting
56
 
layer hides the complexity from the end-users and simplifies the customization. 
57
 
 
58
 
@section section-stack-of-libs Chassis, libraries and Plugins
59
 
 
60
 
It is built as a stack of libraries:
61
 
 
62
 
The @subpage page-chassis provides the common functions that all commandline and daemon applications
63
 
need: 
64
 
@li commandline and configfiles
65
 
@li logging
66
 
@li daemon/service support
67
 
@li plugin loading
68
 
 
69
 
The MySQL Procotol libraries which can encode and decode:
70
 
@li client protocol
71
 
@li binlog protocol
72
 
@li myisam files
73
 
@li frm files
74
 
@li masterinfo files
75
 
 
76
 
The @ref page-core and the @subpage page-plugins.
77
 
 
78
 
@dotfile architecture.dot
 
14
It is built of different components that which are stacked and can be used independently:
 
15
 
 
16
@li @ref page.chassis
 
17
  * commandline and configfiles
 
18
  * logging
 
19
  * daemon/service support
 
20
  * plugin loading
 
21
@li @ref protocol libraries
 
22
  * MySQL
 
23
    * client protocol
 
24
    * binlog protocol
 
25
    * myisam files
 
26
    * frm files
 
27
    * masterinfo files
 
28
@li @ref page.core
 
29
  * connection life-cycle
 
30
@li plugins 
 
31
 
 
32
@page page.chassis Chassis
 
33
 
 
34
@section section-chassisconfigfile Configfile and Commandline Options
 
35
 
 
36
GLib2 provides us with config-file parser and a command-line option parser. We want to expose 
 
37
most options in the same way and accept them from the config-file and the command-line.
 
38
 
 
39
The options are parsed in two steps:
 
40
 
 
41
@li extract the basic command-line options:
 
42
  \c --help
 
43
  \c --version
 
44
  \c --defaults-file
 
45
@li process the defaults-file 
 
46
@li process the other command-line options to override the defaults-file
 
47
 
 
48
@see src/chassis-keyfile.h and src/chassic.c
 
49
 
 
50
@section section-chassisplugin Plugin Interface
 
51
 
 
52
The chassis provides the fundamentals for the plugin interface:
 
53
 
 
54
@li it can resolve the path for plugins
 
55
@li can load them in a portable way
 
56
@li does version checks
 
57
@li calls init and shutdown functions 
 
58
@li exposes the configuration options to the plugins
 
59
 
 
60
@see src/chassis-plugin.h and struct chassis_plugin
 
61
 
 
62
As the chassis is not MySQL specific it can load any kind of plugin as long as it 
 
63
exposes the init and shutdown functions. 
 
64
 
 
65
For the MySQL Proxy you usually load plugins like:
 
66
 
 
67
@li proxy
 
68
@li debug
 
69
 
 
70
... which interface with MySQL @ref section-lifecycle (see below). 
 
71
 
 
72
@page page.core Network Core
 
73
 
 
74
The core exposes Connection Life Cycle to the plugins through callbacks. The plugins can
 
75
decide how get from one state to the next. 
 
76
 
 
77
@section section-lifecycle Connection Life Cycle
 
78
 
 
79
The MySQL Proxy protocol has 4 phases:
 
80
 
 
81
@li connect
 
82
@li authentification
 
83
@li query
 
84
@li disconnect
 
85
 
 
86
@see lifecycle.msc
 
87
 
 
88
The lifecycle image shows the default implementation of the proxy plugin. It implements all 
 
89
the callbacks and exposes them to its scripting layer. It implements the listening and the
 
90
connecting side and forwards packets between them
 
91
 
 
92
Other plugins may implement only one side of the callbacks:
 
93
@li admin plugin implements only the listening side
 
94
@li client plugins implement only the connection side
 
95
 
 
96
@subsection section-scripting Scripting
 
97
 
 
98
Most plugins implement a set of those callbacks and expose them to a scripting layer. 
 
99
 
 
100
For now the scriping is provided by Lua, a simple, fast and easy to embed scripting language.
 
101
We expose most of the internals into the scripting layer and provide modules to operate
 
102
on the data that we pass into the scripting layer
 
103
 
 
104
@section section-network-core-layer Network Core Layer
 
105
 
 
106
  The MySQL Proxy network engine is meant to handle several thousands connections at the same time. We 
 
107
want to use it for load-balancing and fail-over which means we have to handle the connections for
 
108
a larger group of MySQL backend servers nicely. We aim for 5k to 10k connections.
 
109
  Up to MySQL Proxy 0.7 we use a pure event-driven, non-blocking networking approach is described in
 
110
http://kegel.com/c10k.html#nb using libevent 1.4.x. 
 
111
  A event-driven design has a very small foot-print for idling connections: we just store the
 
112
connection state and let it wait for a event. 
 
113
 
 
114
@section section-threaded-io Threaded IO
 
115
 
 
116
  In MySQL 0.8 we added threaded network-io to allow the proxy to scale out with the numbers of CPUs 
 
117
and network cards available.
 
118
 
 
119
To enable network-threading you just start the proxy with:
 
120
 
 
121
@verbatim
 
122
  --event-threads={2 * no-of-cores} (default: 0)
 
123
@endverbatim
 
124
 
 
125
A event-thread is a simple small thread around "event_base_dispatch()" which on a network- or time-event
 
126
executes our core functions. These threads either execute the core functions or idle. If they idle 
 
127
they can read new events to wait for and add them to their wait-list.
 
128
 
 
129
A connection can jump between event-threads: the idling event-thread is taking the wait-for-event
 
130
request and executes the code. Whenever the connection has to wait for a event again it is unregister
 
131
itself from the thread, send its wait-for-event request to the global event-queue again.
 
132
 
 
133
  Up to MySQL Proxy 0.8 the execution of the scripting code is single-threaded: a global mutex protects
 
134
the plugin interface. As a connection is either sending packets or calling plugin function the network 
 
135
events will be handled in parallel and only wait if several connections want to call a plugin function
 
136
 
 
137
@subsection section-threaded-io-impl Implementation
 
138
 
 
139
In chassis-event-thread.c the chassis_event_thread_loop() is the event-thread itself. It gets setup by
 
140
chassis_event_threads_init_thread() which registers itself to a pipe(), a classic simple pipe. That
 
141
pipe is a common hack in libevent to map any kind of event to a the fd-based event-handlers like poll:
 
142
 
 
143
@li the @c event_base_dispatch() blocks until a fd-event triggers
 
144
@li timers, signals, ... can't interrupt @c event_base_dispatch() directly
 
145
@li instead they cause a @c write(pipe_fd, ".", 1); which triggers a fd-event
 
146
    which afterwards gets handled
 
147
 
 
148
In chassis-event-thread.c we use the pipe to signal that something is in the global event-queue to be
 
149
processed by one of the event-threads ... see chassis_event_handle(). All idling threads will process
 
150
that even and will pull from the event queue in parallel to add the event to their events to listen for.
 
151
 
 
152
To add a event to the event-queue you can call chassis_event_add() or chassis_event_add_local(). See 
 
153
the source when to use which.
 
154
 
 
155
@subsection section-threaded-scripting Threaded Scripting
 
156
 
 
157
Usually the scripts are small and only make simple decisions leaving most of the work to the network layer.
 
158
In 0.9 we will make the scripting layer multi-threaded allow several scripting threads at the same time,
 
159
working from a small pool threads.
 
160
 
 
161
That will allow the scripting layer to call blocking or slow functions without infecting the execution of
 
162
other connections.
 
163
 
 
164
Lifting the global plugin mutex will mean we have to handle access to global structure differently. Most 
 
165
of the access is happening on connection-level (the way we do the event-threading) and only access to
 
166
global structures like "proxy.global.*" has to synchronized. For that we will look into using Lua lanes
 
167
to send data around between independent Lua-states.
 
168
 
 
169
 
79
170
 
80
171
*/