crossroads.man (109280B)
1 .TH "Crossroads 1\&.23" "2005, 2006, ff\&." 2 .PP 3 .SH "Crossroads 1\&.23" 4 .SH "Karel Kubat" 5 .SH "e-tunity" 6 .SH "2005, 2006, ff\&." 7 8 .PP 9 10 .SH "1: Introduction" 11 Crossroads is a daemon that basically accepts TCP connections 12 at preconfigured ports, and given a list of \&'back ends\&' 13 distributes each incoming connection to one of the back ends, 14 so that a client request is 15 served\&. Additionally, crossroads maintains an internal 16 administration of the back end connectivity: if a back end isn\&'t 17 usable, then the client request is handled using another back 18 end\&. Crossroads will then periodically check whether a previously not 19 usable back end has come to life yet\&. Also, crossroads can select 20 back ends by estimating the load, so that balancing is achieved\&. 21 .PP 22 Using this approach, crossroads serves as load balancer and fail over 23 utility\&. Crossroads will very likely not be as reliable as 24 hardware based balancers, since it always will require a server to 25 run on\&. This server, in turn, may become a new Single Point of 26 Failure (SPOS)\&. However, in situations where cost efficiency is an issue, 27 crossroads may be a good choice\&. Furthermore, crossroads can be 28 deployed in situations where a hardware based balancing already 29 exists and augmenting service reliability is needed\&. Or, crossroads may be 30 run off a diskless system, which again improves reliability of the 31 underlying hardware\&. 32 .PP 33 This document describes how to use crossroads, how to configure it 34 in order to increase the reliability of your systems, and how to 35 compile the program from its sources\&. 36 .PP 37 38 .SH "1\&.1: Obtaining Crossroads" 39 40 .PP 41 As quick reference, here are some important URL\&'s for Crossroads: 42 .PP 43 .IP o 44 http:/crossroads\&.e-tunity\&.com is the site that serves 45 Crossroads\&. You can browse this at leisure 46 for documentation, sources, and so on\&. 47 .IP 48 .IP o 49 http://freshmeat\&.net/projects/crossr is the 50 Freshmeat announcement page\&. 51 .IP 52 .IP o 53 svn://svn\&.e-tunity\&.com/crossroads is the SVN 54 repository; anonymous reading (fetching) is allowed\&. In order 55 to commit changes, mail me for 56 credentials\&. 57 .PP 58 59 .SH "1\&.2: Copyright and Disclaimer" 60 61 .PP 62 Crossroads is distributed as-is, without assumptions of fitness 63 or usability\&. You are free to use crossroads to your 64 liking\&. It\&'s free, and as with everything that\&'s free: there\&'s 65 also no warranty\&. 66 .PP 67 You are allowed to make modifications to the source code of 68 crossroads, and you are allowed to (re)distribute crossroads, as 69 long as you include this text, all sources, and if applicable: all 70 your modifications, with each distribution\&. 71 .PP 72 While you are allowed to make any and all changes to the sources, 73 I would appreciate hearing about them\&. If the changes concern new 74 functionality or bugfixes, then I\&'ll include them in a next 75 release, stating full credits\&. If you want to seriously contribute (to 76 which you are heartily encouraged), then mail me and I\&'ll get you 77 access to the Crossroads SVN repository, so that you can update and 78 commit as you like\&. 79 .PP 80 81 .SH "1\&.3: Terminology" 82 83 .PP 84 Throughout this document, the following terms are used: \e (Many 85 more meanings of the terms will exist -- yes, I am aware of that\&. I\&'m 86 using the terms here in a very strict sense\&.) 87 .PP 88 .IP "A client" 89 is a process that initiates a network connection 90 to get contact with some service\&. 91 .IP "A service" 92 or \fBserver process\fP or \fBlistener\fP 93 is a central application 94 that accepts network connections from clients and sevices 95 them\&. 96 .IP "Back ends" 97 are locations where crossroads looks in 98 order to service its clients\&. Crossroads sits \&'in between\&' 99 and does its tricks\&. Therefore, as far as the back ends 100 are concerned, crossroads behaves like a client\&. As far as 101 the true client is concerned, crossroads behaves like the 102 service\&. The communication is however transparent: neither 103 client nor back end are aware of the middle position of 104 crossroads\&. 105 .IP "A connection" 106 is a network conversation between client and service, 107 where data are transferred to and fro\&. As 108 far as crossroads is concerned, success means that a 109 connection can be established without errors on 110 the network level\&. Crossroads isn\&'t aware of service 111 pecularities\&. E\&.g\&., when a webserver answers \f(CWHTTP/1\&.0 112 500 Server Error\fP then crossroads will see this as a 113 succesful connection, though the user behind a browser may 114 think otherwise\&. 115 .IP "Back end selection algorithms" 116 are methods by which 117 crossroads determines which back end it will talk to 118 next\&. Crossroads has a number of built-in algorithms, 119 which may be configured per service\&. 120 .IP "Back end states" 121 are the statusses of each back end that 122 is known to crossroads\&. A back end may be available, 123 (temporarily) unavailble or truly down\&. When a back end is 124 temporarily unavailable, then crossroads will periodically 125 check whether the back end has come to life yet (that is, 126 if configured so)\&. 127 .IP "A spike" 128 is a sudden increase in activity, leading to 129 extra load on a given service\&. When crossroads is in 130 effect and when the spike occurs in one connection, 131 then obviously the spike will also appear at one 132 of the back ends\&. However, crossroads will see the spike 133 and will make sure that a subsequent request goes to an 134 other back end\&. In contrast, when several connections 135 arrive simultaneously and cause a spike, then crossroads 136 will be able to distribute the connections over several 137 back ends, thereby \&'flattening out\&' the increase\&. 138 .IP "Load balancing" 139 means that incoming client requests are 140 distributed over more than just one back end (which wouldn\&'t be the 141 case if you wouldn\&'t be running crossroads)\&. Enabling load 142 balancing is nothing more than duplicating services over 143 more than one back end, and having something (in this 144 case: crossroads) distribute the requests, so that per 145 back end the load doesn\&'t get too high\&. 146 .IP "An HTTP session" 147 is a series of separate network connections 148 that originate from one browser\&. E\&.g\&., to fill the display 149 with text and images, the browser hits a website several times\&. 150 An HTTP session may even span several 151 screens\&. E\&.g\&., a website registration dialog may involve 3 152 screens that when called from the same browser, 153 form a logical group of some sort\&. 154 .IP "Headers" 155 or \fBheader lines\fP are specific parts of an HTTP 156 message\&. Crossroads has directives to add or modify 157 headers that are part of the request that a browser sends 158 to server, or those that are part of the server\&. 159 .IP "Session stickiness" 160 means that when a browser starts an 161 HTTP dialog, the balancer makes sure that it \&'sticks\&' to 162 the same back end (i\&.e\&., subsequent requests from the 163 browser are forced to go to the same back end, instead of 164 being balanced to other ones)\&. 165 .IP "Back end usage" 166 is measured by crossroads in order to be 167 able to determine back end selection\&. Crossroads stores 168 information about the number of active connections, the 169 transferred bytes and 170 about the connection duration\&. These numbers can be used to 171 estimate which back end is the least used -- and 172 therefore, presumably, the best candidate for a new 173 request\&. 174 .IP "Fail over" 175 is almost always used when load balancing is in 176 effect\&. The distributor of client requests (crossroads of 177 course) can also monitor back ends, so that incase a back 178 end is \&'down\&', it is no longer accessed\&. 179 .IP "Service downtime" 180 normally occurs when a service is 181 switched off\&. Downtime is obviously avoided when fail over 182 is in effect: a back end can be taken out of service in a 183 controlled manner, without any client noticing it\&. 184 185 .PP 186 187 .SH "1\&.4: Porting issues for pre-1\&.21 installations" 188 189 .PP 190 As of version 1\&.21, the event-hook directives \f(CWonsuccess\fP and 191 \f(CWonfailure\fP no longer exists\&. 192 .PP 193 .IP o 194 Please replace \f(CWonsuccess\fP by \f(CWonstart\fP; 195 .IP o 196 Please replace \f(CWonfailure\fP bu \f(CWonfail\fP; 197 .IP o 198 Note that there is a new hook \f(CWonend\fP\&. 199 .PP 200 The commands that are run via \f(CWonstart\fP, \f(CWonend\fP or \f(CWonfail\fP 201 are subject to format expansion; e\&.g\&., \f(CW%1w\fP is expanded to the 202 weight of the first back end, etc\&.\&. See section ?? for details\&. 203 .PP 204 205 .SH "1\&.5: Porting issues for pre-0\&.26 installations" 206 207 .PP 208 As of version 0\&.26 the syntax of the configuration file has 209 changed\&. In particular: 210 .PP 211 .IP o 212 The keyword \f(CWmaxconnections\fP is now used instead of 213 \f(CWmaxclients\fP; 214 .IP o 215 The keyword \f(CWconnectiontimeout\fP is now used instead of 216 \f(CWsessiontimeout\fP\&. 217 .PP 218 Therefore when converting configuration files to the new syntax, 219 the above keywords must be changed\&. (The reason for these changes 220 is that 0\&.26 introduces \fIsticky HTTP sessions\fP that span 221 multiple TCP connections, and the term 222 \fIsession\fP is used strictly in that sense -- and no longer for a 223 TCP connection\&.) 224 .PP 225 226 .SH "1\&.6: Porting issues for pre-1\&.08 installations" 227 228 .PP 229 As of version 1\&.08, the following directives no longer are 230 supported: 231 .PP 232 .IP o 233 \f(CWinsertstickycookie\fP was replaced by the more generic 234 directive \f(CWaddclientheader\fP\&. E\&.g\&., instead of 235 .br 236 \f(CWinsertstickycookie "XRID=100; Path=/";\fP 237 .br 238 the syntax is now 239 .br 240 \f(CWaddclientheader "Set-Cookie: XRID=100; Path=/";\fP 241 .IP 242 .IP o 243 \f(CWinsertrealip\fP was replaced by the more generic 244 directive \f(CWsetserverheader\fP\&. E\&.g\&., instead of 245 .br 246 \f(CWinsertrealip on;\fP 247 .br 248 the syntax is now 249 .br 250 \f(CWsetserverheader "XR-Real-IP: %r";\fP 251 .br 252 This incidentally also makes it possible to change the header 253 name (here: \f(CWXR-Real-IP\fP)\&. 254 .PP 255 256 .SH "2: Installation for the impatient" 257 For the impatient, here\&'s the very-quick-but-very-superficial recipy 258 for getting crossroads up and running: 259 .PP 260 .IP o 261 If you don\&'t have SVN or don\&'t want to use it: 262 .IP 263 .IP o 264 Obtain the crossroads source archive at 265 http://crossroads\&.e-tunity\&.com\&. 266 .IP 267 .IP o 268 Change-dir to a \&'sources\&' directory on your system and 269 unpack the archive\&. 270 .IP 271 .IP o 272 Change-dir into the create directory \f(CWcrossroads/\fP\&. 273 .IP 274 .IP o 275 If you have SVN and want to go for the newest snapshot: 276 .IP 277 .IP o 278 Get the latest sources and snapshots using SVN from 279 .br 280 \f(CWsvn://svn\&.e-tunity\&.com/crossroads\fP\&. 281 .IP 282 .IP o 283 You\&'ll find the newest alpha version under 284 \f(CWcrossroads/trunk\fP and the stable versions under 285 \f(CWcrossroads/tags\fP, 286 e\&.g\&. \f(CWcrossroads/tags/release-1\&.00\fP\&. 287 .IP 288 .IP o 289 Choose which you want to use: the latest stable 290 release, or the bleeding edge alpha? In the former case, 291 change-dir to \f(CWcrossroads/tags/release-\fP\fIX\&.YY\fP, where 292 \fIX\&.YY\fP is a release ID\&. In the latter case, change-dir to 293 \f(CWcrossroads/trunk\fP\&. 294 .IP 295 .IP o 296 Type \f(CWmake install\fP\&. This installs the crossroads 297 binary into \f(CW/usr/local/bin/\fP\&. If the compilation doesn\&'t 298 work on your system, check \f(CWetc/Makefile\&.def\fP for hints\&. 299 .IP 300 .IP o 301 Create a file \f(CW/etc/crossroads\&.conf\fP\&. In it state 302 something like: 303 .IP 304 .nf 305 service www { 306 port 80; 307 revivinginterval 15; 308 backend one { 309 server 10\&.1\&.1\&.100:80; 310 } 311 backend two { 312 server 10\&.1\&.1\&.101:80; 313 } 314 } 315 .fi 316 317 .IP 318 That\&'s off course assuming that you want to balance HTTP on 319 port 80 to two back ends at 10\&.1\&.1\&.100 and 10\&.1\&.1\&.101\&. 320 .IP 321 .IP o 322 Type \f(CWcrossroads start\fP\&. 323 .IP 324 .IP o 325 Surf to the machine where crossroads is running\&. You will 326 see the pages served by the back ends 10\&.1\&.1\&.100 or 327 10\&.1\&.1\&.101\&. 328 .IP 329 .IP o 330 To monitor the status of crossroads, type \f(CWcrossroads 331 status\fP\&. 332 333 .PP 334 335 .SH "3: Using Crossroads" 336 Crossroads is started from the commandline, and highly depends on 337 \f(CW/etc/crossroads\&.conf\fP (the default configuration file)\&. It 338 supports a number of flags (e\&.g\&., to overrule the location of the 339 configuration file)\&. The actual usage information is always obtained 340 by typing \f(CWcrossroads\fP without any arguments\&. Crossroads then 341 displays the allowed arguments\&. 342 .PP 343 344 .SH "3\&.1: General Commandline Syntax" 345 346 .PP 347 This section shows the most basic usage\&. As said above, start 348 \f(CWcrossroads\fP without arguments to view the full listing of options\&. 349 .PP 350 .IP o 351 \f(CWcrossroads start\fP and \f(CWcrossroads stop\fP are typical 352 actions that are run from system startup scripts\&. The 353 meaning is self-explanatory\&. 354 .IP o 355 \f(CWcrossroads restart\fP is a combination of the former 356 two\&. Beware that a restart may cause discontinuity in 357 service; it is just a shorthand for typing the \&'stop\&' and 358 \&'start\&' actions after one another\&. 359 .IP o 360 \f(CWcrossroad status\fP reports on each running 361 service\&. Per service, the state of each back end is 362 reported\&. 363 .IP o 364 \f(CWcrossroads tell\fP \fIservice backend state\fP is a 365 command line way of telling crossroads that a given back 366 end, of a given service, is in a given state\&. Normally 367 crossroads maintains state information itself, but by 368 using \f(CWcrossroads tell\fP, a back end can be e\&.g\&. taken 369 \&'off line\&' for servicing\&. 370 .IP o 371 \f(CWcrossroads configtest\fP tells you whether the 372 configuration is syntactially correct\&. 373 .IP o 374 \f(CWcrossroads services\fP reports on the configured 375 services\&. In contrast to \f(CWcrossroads status\fP, this 376 option only shows what\&'s configured -- not what\&'s up and 377 running\&. Therefore, \f(CWcrossroads services\fP doesn\&'t 378 report on back end states\&. 379 .IP o 380 \f(CWcrossroads sampleconf\fP shows a sample configuration on 381 screen\&. A good way of quicky viewing the configuration 382 file syntax, or of getting a start for your own 383 configuration \f(CW/etc/crossroads\&.conf\fP\&. 384 385 .PP 386 387 .SH "3\&.2: Logging-related options" 388 389 .PP 390 Two \&'flags\&' of Crossroads are specifically logging-related\&. This 391 section elaborates on these flags\&. 392 .PP 393 First, there\&'s flag \f(CW-a\fP\&. When present, the start and end of 394 activity is logged using statements like 395 .PP 396 \fIYYYY-MM-DD HH/MM/SS starting http from 61\&.45\&.32\&.189 to 10\&.1\&.1\&.1\fP 397 398 .PP 399 Similarly, there are \&'ending\&' statements\&. Using this flag and 400 scanning your logs for these statements may be helpful in quickly 401 determining your system load\&. 402 .PP 403 Second, there\&'s flag \f(CW-l\fP\&. This flag selects the \&'facility\&' of 404 logging and defaults to \f(CWLOG_DAEMON\fP\&. You can supply a number 405 between 0 and 7 to flag \f(CW-l\fP to select \f(CWLOG_LOCAL0\fP to 406 \f(CWLOG_LOCAL7\fP\&. This would separate the Crossroads-related logging 407 from other streams\&. Here\&'s a very short guide; please read your Unix 408 manpages of \f(CWsyslogd\fP for more information\&. 409 .PP 410 .IP o 411 First edit \f(CW/etc/syslog\&.conf\fP and add a line: 412 .IP 413 .nf 414 local7\&.* /var/log/crossroads\&.log 415 .fi 416 417 .IP 418 That instructs \f(CWsyslogd\fP to send \f(CWLOG_LOCAL7\fP requests to the 419 logfile \f(CW/var/log/crossroads\&.log\fP\&. 420 .IP 421 .IP o 422 Next, restart \f(CWsyslogd\fP\&. On most Unices that\&'s done by 423 issuing \f(CWkillall -1 syslogd\fP\&. (As a side-note, I tried this once 424 on an Bull/AIX system, and the box just shut down\&. The \f(CWkillall\fP 425 command killed every process\&.\&.\&.) 426 .IP 427 .IP o 428 Now start \f(CWcrossroads\fP with the flag \f(CW-l7\fP\&. 429 .IP 430 .IP o 431 Finally, monitor \f(CW/var/log/crossroads\&.log\fP for Crossroads\&' 432 messages\&. 433 .PP 434 435 .SH "3\&.3: Reloading Configurations" 436 437 .PP 438 Crossroads doesn\&'t support the reloading of a configuration while 439 running (such as other programs, e\&.g\&. Apache do)\&. There are various 440 technical reasons for this\&. 441 .PP 442 However, external lists of allowed or denied IP addresses can be 443 reloaded by sending a signal -1 (\f(CWSIGHUP\fP) to Crossroads\&. See 444 section ?? for the details\&. 445 .PP 446 447 .SH "4: The configuration" 448 The configuration that crossroads uses is normally stored in the file 449 \f(CW/etc/crossroads\&.conf\fP\&. This location can be overruled using the 450 command line flag \f(CW-c\fP\&. 451 .PP 452 This section explains the syntax of the configuration file, and what 453 all settings do\&. 454 .PP 455 456 .SH "4\&.1: General language elements" 457 458 .PP 459 This section describes the general elements of the crossroads 460 configuration language\&. 461 .PP 462 463 .SH "4\&.1\&.1: Empty lines and comments" 464 465 .PP 466 Empty lines are of course allowed in the 467 configuration\&. Crossroads recognizes three formats of comment: 468 .PP 469 .IP o 470 C-style, between \f(CW/*\fP and \f(CW*/\fP, 471 .IP o 472 C++-style, starting with \f(CW//\fP and ending with the end 473 of the text line; 474 .IP o 475 Shell-style, starting with \f(CW#\fP and ending with the end 476 of the text line\&. 477 .PP 478 Simply choose your favorite editor and use the comment that \&'looks 479 best\&'\&.\e (I favor C or C++ comment\&. My favorite editor \fIemacs\fP 480 can be put in \f(CWcmode\fP and nicely highlight what\&'s comment and what\&'s 481 not\&. And as a bonus it will auto-indent the configuration!) 482 .PP 483 484 .SH "4\&.1\&.2: Keywords, numbers, identifiers, generic strings" 485 486 .PP 487 In a configuration file, statements are identified by \fIkeywords\fP, 488 such as \f(CWservice\fP, \f(CWverbosity\fP\&. These are reserved words\&. 489 .PP 490 Many keywords require an \fIidentifier\fP as the argument\&. E\&.g, a 491 service has a unique name, which must start with a letter or 492 underscore, followed by zero or more letters, underscores, or 493 digits\&. Therefore, in the statement \f(CWservice myservice\fP, the keyword is 494 \f(CWservice\fP and the identifier is \f(CWmyservice\fP\&. 495 .PP 496 Other keywords require a numeric argument\&. Crossroads knows only 497 non-negative integer numbers, as in \f(CWport 8000\fP\&. Here, \f(CWport\fP is 498 the keyword and \f(CW8000\fP is the number\&. 499 .PP 500 Yet other keywords require \&'generic strings\&', such as hostname 501 specifications or system commands\&. Such generic strings contain any 502 characters (including white space) up to the terminating statement 503 character \f(CW;\fP\&. If a string must contain a semicolon, then it must 504 be enclosed in single or double quotes: 505 .PP 506 .IP o 507 \f(CWThis is a string;\fP is a string that starts at \f(CWT\fP 508 and ends with \f(CWg\fP 509 .IP o 510 \f(CW"This is a string";\fP is the same, the double quotes 511 are not necessary 512 .IP o 513 \f(CW"This is ; a string";\fP has double quotes to protect 514 the inner ; 515 .PP 516 Finally, an argument can be a \&'boolean\&' value\&. Crossroads knows 517 \f(CWtrue\fP, \f(CWfalse\fP, \f(CWyes\fP, \f(CWno\fP, \f(CWon\fP, \f(CWoff\fP\&. The keywords 518 \f(CWtrue\fP, \f(CWyes\fP and \f(CWon\fP all mean the same and can be used 519 interchangeably; as can the keywords \f(CWfalse\fP, \f(CWno\fP and \f(CWoff\fP\&. 520 .PP 521 522 .SH "4\&.2: Service definitions" 523 524 .PP 525 Service definitions are blocks in the configuration file that 526 state what is for each service\&. A service definition starts with 527 \f(CWservice\fP, followed by a unique identifier, and by statements in 528 \f(CW{\fP and \f(CW}\fP\&. For example: 529 .PP 530 .nf 531 // Definition of service \&'www\&': 532 service www { 533 \&.\&.\&. 534 \&.\&.\&. // statements that define the 535 \&.\&.\&. // service named \&'www\&' 536 \&.\&.\&. 537 } 538 .fi 539 540 .PP 541 The configuration file can contain many service blocks, as long as the 542 identifying names differ\&. The following list shows possible 543 statements\&. Each statement must end with a semicolon, except for the 544 \f(CWbackend\fP statement, which has is own block (more on this later)\&. 545 .PP 546 547 .SH "4\&.2\&.1: type - Defining the service type" 548 .IP "Description:" 549 The \f(CWtype\fP statement defines how crossroads handles the stated 550 service\&. There are currently two types: \f(CWany\fP and 551 \f(CWhttp\fP\&. The type \f(CWany\fP means that crossroads doesn\&'t 552 interpret the contents of a TCP stream, but only distributes streams 553 over back ends\&. The type \f(CWhttp\fP means that crossroads has to 554 analyze what\&'s in the messages, does magical HTTP header tricks, and 555 so on -- all to ensure that multiple connections are treated as one 556 session, or that the back end is notified of the client\&'s IP 557 address\&. 558 .IP 559 Unless you really need such special features, use the type \f(CWany\fP (the 560 default), even for HTTP protocols\&. 561 .IP "Syntax:" 562 \f(CWtype\fP \fIspecifier\fP, where \fIspecifier\fP is \f(CWany\fP or 563 \f(CWhttp\fP 564 .IP "Default:" 565 \f(CWany\fP 566 567 .PP 568 569 .SH "4\&.2\&.2: port - Specifying the listen port" 570 .IP "Description:" 571 The \f(CWport\fP statement defines to which TCP port a service 572 \&'listens\&'\&. E\&.g\&. \f(CWport 8000\fP says that this service will accept 573 connections on port 8000\&. 574 .IP "Syntax:" 575 \f(CWport\fP \fInumber\fP 576 .IP "Default:" 577 There is no default\&. This is a required setting\&. 578 579 .PP 580 581 .SH "4\&.2\&.3: bindto - Binding to a specific IP address" 582 .IP "Description:" 583 The \f(CWbindto\fP statement is used in situations where crossroads 584 should only listen to the stated port at a given IP address\&. E\&.g\&., 585 \f(CWbindto 127\&.0\&.0\&.1\fP causes crossroads to \&'bind\&' the service only to 586 the local IP address\&. Network connections from other hosts won\&'t be 587 serviced\&. By default, crossroads binds a service to all presently 588 active IP addresses at the invoking host\&. 589 .IP "Syntax:" 590 \f(CWbindto\fP \fIaddress\fP, where \fIaddress\fP is a numeric IP 591 address, such as 127\&.0\&.0\&.1, or the keyword \f(CWany\fP\&. 592 .IP "Default:" 593 \f(CWany\fP 594 595 .PP 596 597 .SH "4\&.2\&.4: verbosity - Controlling debug output" 598 .IP "Description:" 599 Verbosity statements come in two forms: \f(CWverbosity on\fP or 600 \f(CWverbosity off\fP\&. When \&'on\&', log messages to \f(CW/var/log/messages\fP 601 are generated that show what\&'s going on\&.\e (Actually, the 602 messages go to \f(CWsyslog(3)\fP, using facility \f(CWLOG_DAEMON\fP and 603 priority \f(CWLOG_INFO\fP\&. In most (Linux) cases this will mean: output to 604 \f(CW/var/log/messages\fP\&. On Mac OSX the messages go to 605 \f(CW/var/log/system\&.log\fP\&.) The keyword \f(CWverbose\fP is an alias for 606 \f(CWverbosity\fP\&. 607 .IP "Syntax:" 608 \f(CWverbosity\fP \fIsetting\fP or \f(CWverbose\fP \fIsetting\fP, where 609 \fIsetting\fP is \f(CWtrue\fP, \f(CWyes\fP or \f(CWon\fP to turn 610 verbosity on; or \f(CWfalse\fP, \f(CWno\fP, \f(CWoff\fP to turn it off\&. 611 .IP "Default:" 612 \f(CWoff\fP 613 614 .PP 615 616 .SH "4\&.2\&.5: dispatchmode - How are back ends selected" 617 .IP "Description:" 618 The dispatch mode controls how crossroads selects a back end from 619 a list of active back ends\&. The below text shows the bare 620 syntax\&. See section ?? for a textual explanation\&. 621 .IP 622 The settings can be: 623 .IP 624 .IP o 625 \f(CWdispatchmode roundrobin\fP: Simply the \&'next in line\&' is 626 chosen\&. E\&.g, when 3 back ends are active, then the usage 627 series is 1, 2, 3, 1, 2, 3, and so on\&. 628 .IP 629 Roundrobin dispatching is the default method, when no 630 \f(CWdispatchmode\fP statement occurs\&. 631 .IP 632 .IP o 633 \f(CWdispatchmode random\fP: Random selection\&. Probably only 634 for stress testing, though when used with weights (see below) 635 it is a good distributor of new connections too\&. 636 .IP 637 .IP o 638 \f(CWdispatchmode bysize [ over\fP \fIconnections\fP \f(CW]\fP: 639 The next back end is the one 640 that has transferred the least number of bytes\&. This 641 selection mechanism assumes that the more bytes, the heavier 642 the load\&. 643 .IP 644 The modifier \f(CWover\fP \fIconnections\fP is optional\&. (The square 645 brackets shown above are not part of the statement but 646 indicate optionality\&.) When given, 647 the load is computed as an average of the last stated number of 648 connections\&. When this modifier is absent, then the load is 649 computed over all connections since startup\&. 650 .IP 651 .IP o 652 \f(CWdispatchmode byduration [ over\fP \fIconnections\fP \f(CW]\fP: 653 The next back end is the one 654 that served connections for the shortest time\&. This mechanism 655 assumes that the longer the connection, the heavier the load\&. 656 .IP 657 .IP o 658 \f(CWdispatchmode byconnections\fP: The next back end is the one 659 with the least active connections\&. This mechanism assumes that 660 each connection to a back end represents load\&. It is usable 661 for e\&.g\&. database connections\&. 662 .IP 663 .IP o 664 \f(CWdispatchmode byorder\fP: The first back end is selected 665 every time, unless it\&'s unavailable\&. In that case the second 666 is taken, and so on\&. 667 .IP 668 .IP o 669 \f(CWdispatchmode externalhandler\fP \fIprogram arguments\fP: 670 This is a special mode, where an external program is delegated 671 the responsibility to say which back end should be used 672 next\&. In this case, Crossroads will call the external program, 673 and this will of course be slower than one of the \&'built-in\&' 674 dispatch modes\&. However, this is the ultimate escape when 675 custom-made dispatch modes are needed\&. 676 .IP 677 The dispatch mode that uses an \f(CWexternalhandler\fP is 678 discussed separately in section ??\&. 679 .IP 680 The selection algorithm is only used when clients are serviced that 681 aren\&'t part of a sticky HTTP session\&. This is the case during: 682 .IP 683 .IP o 684 all client requests of a service type \f(CWany\fP; 685 .IP o 686 new sessions of a service type \f(CWhttp\fP\&. 687 .IP 688 When type \f(CWhttp\fP is in effect and a session is underway, then the 689 previously used back end is always selected -- regardless of 690 dispatching mode\&. 691 .IP 692 Your \&'right\&' dispatch mode will depend on the type of service\&. Given 693 the fact that crossroads doesn\&'t know (and doesn\&'t care) how to 694 estimate load from a network traffic stream, you have to choose an 695 appropriate dispatch mode to optimize load balancing\&. In most cases, 696 \f(CWroundrobin\fP or \f(CWbyconnections\fP will do the job just fine\&. 697 .IP "Syntax:" 698 \f(CWdispatchmode\fP \fImode\fP (see above for the modes), optionally 699 followed by \f(CWover\fP \fInumber\fP, or when the \fImode\fP is 700 \f(CWexternalhandler\fP, followed by \fIprogram\fP\&. 701 .IP "Default:" 702 \f(CWroundrobin\fP 703 704 .PP 705 706 .SH "4\&.2\&.6: revivinginterval - Back end wakeup calls" 707 .IP "Description:" 708 A reviving interval definition is needed when crossroads 709 determines that a back end is temporarily unavailable\&. This will 710 happen when: 711 .IP 712 .IP o 713 The back end cannot be reached (network connection 714 fails); 715 .IP o 716 The network connection to the back end suddenly dies\&. 717 .IP 718 An example of the definition is \f(CWrevivinginterval 10\fP\&. When this 719 reviving interval is given, crossroads will check each 10 seconds 720 whether unavailable back ends have woken up yet\&. A back end is 721 considered awake when a network connection to that back end can 722 succesfully be established\&. 723 .IP "Syntax:" 724 \f(CWrevivinginterval\fP \fInumber\fP, where the number is the interval 725 in seconds\&. 726 .IP "Default:" 727 0 (no wakeup calls) 728 729 .PP 730 731 .SH "4\&.2\&.7: maxconnections - Limiting concurrent clients at service level" 732 .IP "Description:" 733 The maximum number of connections is specified using 734 \f(CWmaxconnections\fP\&. There is one argument; the number of concurrent 735 established connections that may be active within one service\&. 736 .IP 737 \&'Throttling\&' the number of connections is a way of preventing Denial of 738 Service (DOS) attacks\&. Without a limit, numerous network connections 739 may spawn so many server instances, that the service ultimately breaks 740 down and becomes unavailable\&. 741 .IP "Syntax:" 742 \f(CWmaxconnections\fP \fInumber\fP, where the number specifies the 743 maximum of concurrent connections to the service\&. 744 .IP "Default:" 745 0, meaning that all connections will be accepted\&. 746 747 .PP 748 749 .SH "4\&.2\&.8: backlog - The TCP Back Log size" 750 .IP "Description:" 751 The TCP back log size is a number that controls how many 752 \&'waiting\&' network connections may be queued, before a client simply 753 cannot connect\&. The syntax is e\&.g\&. \f(CWbacklog 5\fP to cause crossroads 754 to have 5 waiting connections for 1 active connection\&. 755 The backlog queue shouldn\&'t be too 756 high, or clients will experience timeouts before they can actually 757 connect\&. The queue shouldn\&'t be too small either, because clients 758 would be simply rejected\&. Your mileage may vary\&. 759 .IP "Syntax:" 760 \f(CWbacklog\fP \fInumber\fP 761 .IP "Default:" 762 0, which takes the operating system\&'s default 763 value for socket back log size\&. 764 765 .PP 766 767 .SH "4\&.2\&.9: shmkey - Shared Memory Access" 768 .IP "Description:" 769 Different Crossroads 770 invocations must \&'know\&' of each others activity\&. E\&.g, \f(CWcrossroad 771 status\fP must be able to get to the actual state information of all 772 running services\&. This is internally implemented through shared 773 memory, which is reserved using a key\&. 774 .IP 775 Normally crossroads will supply a shared memory key, based on the 776 service port and bitwise or-ed with a magic number\&. In situations 777 where this conflicts with existing keys (of other programs, having 778 their own keys), you may supply a chosen value\&. 779 .IP 780 The actual key value doesn\&'t matter much, as long as it\&'s unique 781 and as long as each invocation of crossroads uses it\&. 782 .IP "Syntax:" 783 \f(CWshmkey\fP \fInumber\fP 784 .IP "Default:" 785 0, which means that crossroads will \&'guess\&' its 786 own key, based on TCP port and a magic number\&. 787 788 .PP 789 790 .SH "4\&.2\&.10: allow* and deny* - Allowing or denying connections" 791 .IP "Description:" 792 Crossroads can allow or deny 793 connections based on the IP address of a client\&. There are four 794 directives that are relevant: \f(CWallowfrom\fP, \f(CWallowfile\fP, 795 \f(CWdenyfrom\fP and \f(CWdenyfile\fP\&. When using \f(CWallowfrom\fP and 796 \f(CWdenyfrom\fP then the IP addresses to allow or deny connections are 797 stated in \f(CW/etc/crossroads\&.conf\fP\&. 798 .IP 799 When \f(CWallow*\fP directives are used, then all connections are denied 800 unless they match the stated allowed IP\&'s\&. When \f(CWdeny*\fP directives 801 are used, then all connections are allowed unless they match the 802 stated disallowed IP\&'s\&. When denying and allowing is both used, 803 then the Crossroads checks the deny list first\&. 804 .IP 805 The statements \f(CWallowfrom\fP and \f(CWdenyfrom\fP are followed by a 806 list of filter specifications\&. The statements \f(CWallowfile\fP and 807 \f(CWdenyfile\fP are followed by a filename; Crossroads will read 808 filter specifications from those external files\&. In both cases, 809 Crossroads obtains filter specifications and places them in its 810 lists of allowed or denied IP addresses\&. The difference between 811 specifying filters in \f(CW/etc/crossroads\&.conf\fP or in external 812 files, is that Crossroads will reload the external files when it 813 receives signal 1 (\f(CWSIGHUP\fP), as in \f(CWkillall -1 crossroads\fP\&. 814 .IP 815 The filter specifications must obey the following syntax: it 816 consists of up to 817 four numbers ranging from 0 to 255 and separated by a decimal 818 sign\&. Optionally a slash follows, with a bitmask which is also a 819 decimal number\&. 820 .IP 821 This is probably best explained by a few examples: 822 .IP 823 .IP o 824 \f(CWallowfrom 10/8;\fP will allow connections from 825 \f(CW10\&.*\&.*\&.*\fP (a full Class A network)\&. The mask \f(CW/8\fP means 826 that the first 8 bits of the number (ie\&., only the \f(CW10\fP) are 827 significant\&. On the last 3 positions of the IP address, all 828 numbers are allowed\&. Given this directive, client connections 829 from e\&.g\&. 10\&.1\&.1\&.1 and 10\&.2\&.3\&.4 will be allowed\&. 830 .IP 831 .IP o 832 \f(CWallowfrom 10\&.3/16;\fP will allow all IP addresses that 833 start with \f(CW10\&.3\fP\&. 834 .IP 835 .IP o 836 \f(CWallowfrom 10\&.3\&.1/16;\fP is the same as above\&. The third 837 byte of the IP address is superfluous because the netmask 838 specifies that only the first 16 bits (2 numbers) are taken 839 into account\&. 840 .IP 841 .IP o 842 \f(CWallowfrom 10\&.3\&.1\&.15;\fP allows traffic from only the 843 specified IP address\&. There is no bitmask; all four numbers 844 are relevant\&. 845 .IP 846 .IP o 847 \f(CWallowfrom 10\&.3\&.1\&.15 10\&.2/16;\fP allows traffic from one 848 IP address \f(CW10\&.3\&.1\&.15\fP or from a complete Class B network 849 \f(CW10\&.2\&.*\&.*\fP 850 .IP 851 .IP o 852 \f(CWallowfile /tmp/myfile\&.txt;\fP in combination with a file 853 \f(CW/tmp/myfile\&.txt\fP, with the contents \f(CW10\&.3\&.1\&.15 10\&.2/16\fP, 854 is the same as above\&. 855 .IP "Syntax:" 856 .IP o 857 \f(CWallowfrom\fP \fIfilter-specificication(s)\fP 858 .IP o 859 \f(CWdenyfrom\fP \fIfilter-specificication(s)\fP 860 .IP o 861 \f(CWallowfile\fP \fIfilename\fP 862 .IP o 863 \f(CWdenyfile\fP \fIfilename\fP 864 .IP "Default:" 865 In absence of these statements, all client IP\&'s are accepted\&. 866 867 .PP 868 869 .SH "4\&.2\&.11: useraccount - Limiting the effective ID of external processes" 870 .IP "Description:" 871 Using the directive \f(CWuseraccount\fP, the effective user and group 872 ID can be restricted\&. This comes into effect when Crossroads runs 873 external commands, such as: 874 .IP o 875 Hooks for \f(CWonstart\fP, \f(CWonend\fP or \f(CWonfail\fP; 876 .IP o 877 External dispatchers, when \f(CWdispatchmode 878 externalhandler\fP is in effect\&. 879 Once a user name for external commands is specified, Crossroads 880 assumes the associated user ID and group ID before running those 881 commands\&. 882 .IP "Syntax:" 883 \f(CWuseraccount\fP \fIusername\fP 884 .IP "Default:" 885 None; when unspecified, external commands are run with the 886 ID that was in effect when Crossroads was started\&. 887 888 .PP 889 890 .SH "4\&.3: Backend definitions" 891 892 .PP 893 Inside the service definitions as are described in the previous 894 section, \fIbackend definitions\fP must also occur\&. Backend definitions 895 are started by the keyword \f(CWbackend\fP, followed by an identifier 896 (the back end name) , and statements inside \f(CW{\fP and \f(CW}\fP: 897 .PP 898 .nf 899 service myservice { 900 \&.\&.\&. 901 \&.\&.\&. // statements that define the 902 \&.\&.\&. // service named \&'myservice\&' 903 \&.\&.\&. 904 905 backend mybackend { 906 \&.\&.\&. 907 \&.\&.\&. // statements that define the 908 \&.\&.\&. // backend named \&'mybackend\&' 909 \&.\&.\&. 910 } 911 } 912 .fi 913 914 .PP 915 Each service definition must have at least one backend 916 definition\&. There may be more (and probably will, if you want 917 balancing and fail over) as long as the backend names differ\&. 918 The statements in the backend definition blocks are described in the 919 following sections\&. 920 .PP 921 Some directives (\f(CWstickycookie\fP etc\&.) only have effect when 922 Crossroads treats the network traffic as a stream of HTTP messages; 923 i\&.e\&., when the service is declared with \f(CWtype http\fP\&. Incase of 924 \f(CWtype any\fP, the HTTP-specific directives have no effect\&. 925 .PP 926 927 .SH "4\&.3\&.1: server - Specifying the back end address" 928 .IP "Description:" 929 Each back end must be identified by the network name 930 (server name) where it is located\&. For example: \f(CWserver 931 10\&.1\&.1\&.23\fP, or \f(CWserver web\&.mydomain\&.org\fP\&. A TCP port specifier 932 can follow the server name, as in \f(CWserver web\&.mydomain\&.org:80\fP\&. 933 .IP "Syntax:" 934 .IP o 935 \f(CWserver\fP \fIservername\fP, where \fIservername\fP is a 936 network name or IP address; 937 .IP o 938 \f(CWserver\fP \fIservername:port\fP 939 .IP "Default:" 940 There is no default\&. This is a required setting\&. 941 942 .PP 943 944 .SH "4\&.3\&.2: verbosity - Controlling verbosity at the back end level" 945 .IP "Description:" 946 Similar to \f(CWservice\fP specifications, a 947 \f(CWbackend\fP can have its own verbosity (\f(CWon\fP or \f(CWoff\fP)\&. When 948 \f(CWon\fP, traffic to and fro this back end is reported\&. 949 .IP "Syntax:" 950 .IP o 951 \f(CWverbosity\fP \fIsetting\fP, or 952 .IP o 953 \f(CWverbose\fP \fIsetting\fP, where \fIsetting\fP is \f(CWtrue\fP, 954 \f(CWyes\fP or \f(CWon\fP, or \f(CWfalse\fP, \f(CWno\fP, \f(CWoff\fP to turn it 955 off\&. 956 .IP "Default:" 957 \f(CWoff\fP 958 959 .PP 960 961 .SH "4\&.3\&.3: weight - When a back end is more equal than others" 962 .IP "Description:" 963 To influence how backends are selected, a backend can specify its 964 \&'weight\&' in the process\&. The higher the weight, the less likely a 965 back end will be chosen\&. The default is 1\&. 966 .IP 967 The weighing mechanism only applies to the dispatch modes 968 \f(CWrandom\fP, \f(CWbyconnections\fP, \f(CWbysize\fP and \f(CWbyduration\fP\&. 969 The weight is in fact a penalty factor\&. E\&.g\&., if backend A has 970 \f(CWweight 2\fP and backend B has \f(CWweight 1\fP, then backend B will 971 be selected all the time, until its usage parameter is twice as 972 large as the parameter of A\&. Think of it as a \&'sluggishness\&' 973 statement\&. 974 .IP "Syntax:" 975 \f(CWweight\fP \fInumber\fP; the higher the number, the more \&'sluggish\&' 976 a back end is 977 .IP "Default:" 978 1; all back ends have equal weight\&. 979 980 .PP 981 982 .SH "4\&.3\&.4: decay - Levelling out activity of a back end" 983 .IP "Description:" 984 To make sure that a \&'spike\&' of activity doesn\&'t 985 influence the perceived load of a back end forever, you may 986 specify a certain decay\&. E\&.g, the statement \f(CWdecay 10\fP makes 987 sure that the load that crossroads computes for this back end (be 988 it in seconds or in bytes) is decreased by 10% each time that 989 \fBan other\fP back end is hit\&. Decays are not applied to the count 990 of concurrent connections\&. 991 .IP 992 This means that when a given back end is hit, then its usage data 993 of the transferred bytes and the connection duration are updated 994 using the actual number of bytes and actual duration\&. However, 995 when a different back end is hit, then the usage data are 996 decreased by the specified decay\&. 997 .IP "Syntax:" 998 \f(CWdecay\fP \fInumber\fP, where \fInumber\fP is a percentage that 999 decreases the back end usage data when other back ends are 1000 hit\&. 1001 .IP "Default:" 1002 0, meaning that no decay is applied to usage statistics\&. 1003 1004 .PP 1005 1006 .SH "4\&.3\&.5: onstart, onend, onfail - Action Hooks" 1007 .IP "Description:" 1008 The three directives \f(CWonstart\fP, \f(CWonend\fP and \f(CWonfail\fP can be 1009 specified to start system commands (external programs) when a 1010 connection to a back end starts, fails or ends: 1011 .IP o 1012 \f(CWonstart\fP commands will be run when Crossroads 1013 successfully connects to a back end, and starts servicing; 1014 .IP o 1015 \f(CWonend\fP commands will be run when a (previously 1016 established) connection stops; 1017 .IP o 1018 \f(CWonfail\fP commands will be run when Crossroads tries to 1019 contact a back end to serve a client, but the back end can\&'t 1020 be reached\&. 1021 .IP 1022 The format is always \f(CWon\fP\fItype\fP \fIcommand\fP\&. The \fIcommand\fP 1023 is an external program, optionally followed by arguments\&. The 1024 command is expanded according to the following table: 1025 .IP 1026 .IP o 1027 \f(CW%a\fP is the availability of the current back end, when 1028 a current back end is established; 1029 .IP o 1030 \f(CW%1a\fP is the availability of the first back end (0 when 1031 unavailable, 1 if available); \f(CW%2a\fP is the availability of 1032 the second back end, and so on; 1033 .IP o 1034 \f(CW%b\fP is the name of the current back end, when one is 1035 established; 1036 .IP o 1037 \f(CW%1b\fP is the name of the first back end, \f(CW%2b\fP of the 1038 second back end, and so on; 1039 .IP o 1040 \f(CW%e\fP is the count of seconds since start of epoch 1041 (January 1st 1970 GMT); 1042 .IP o 1043 \f(CW%r\fP is the IP address of the client that requests a 1044 connection and for whom the external dispatcher should compute 1045 a back end; 1046 .IP o 1047 \f(CW%s\fP is the name of the current service that the client 1048 connected to; 1049 .IP o 1050 \f(CW%t\fP is the current local time in ASCII format, in 1051 \fIYYYY-MM-DD/hhh:mm:ss\fP; 1052 .IP o 1053 \f(CW%T\fP is the current GMT time in ASCIII format; 1054 .IP o 1055 \f(CW%v\fP is the Crossroads version; 1056 .IP o 1057 Any other chararacter following a \f(CW%\fP sign is taken 1058 literally; e\&.g\&. \f(CW%z\fP is just a z\&. 1059 .IP 1060 .IP "Syntax:" 1061 .IP o 1062 \f(CWonstart\fP \fIcommandline\fP 1063 .IP o 1064 \f(CWonend\fP \fIcommandline\fP 1065 .IP o 1066 \f(CWonfail\fP \fIcommandline\fP 1067 .IP o 1068 \f(CWonsuccess\fP \fIcommandline\fP 1069 .IP "Default:" 1070 There is no default\&. Normally no external programs are run upon 1071 connection, success or failure of a back end\&. 1072 1073 .PP 1074 1075 .SH "4\&.3\&.6: trafficlog and throughputlog - Debugging and Performance Aids" 1076 .IP "Description:" 1077 Two directives are available 1078 to log network traffic to files\&. They are \f(CWtrafficlog\fP and 1079 \f(CWthroughputlog\fP\&. 1080 .IP 1081 The \f(CWtrafficlog\fP statement causes all traffic to be logged in 1082 hexadecimal format\&. Each line is prefixed by \f(CWB\fP or \f(CWC\fP, 1083 depending on whether the information was received from the back 1084 end or from the client\&. 1085 .IP 1086 The \f(CWthroughputlog\fP statement writes shorthand transmissions to 1087 its log, accompanied by timings\&. 1088 .IP "Syntax:" 1089 .IP o 1090 \f(CWtrafficlog\fP \fIfilename\fP 1091 .IP o 1092 \f(CWthroughputlog\fP \fIfilename\fP 1093 .IP "Default:" 1094 none 1095 1096 .PP 1097 1098 .SH "4\&.3\&.7: stickycookie - Back end selection with an HTTP cookie" 1099 .IP "Description:" 1100 The directive \f(CWstickycookie\fP \fIvalue\fP 1101 causes Crossroads to unpack clients\&' requests, to check for 1102 \fIvalue\fP in the cookies\&. When found, the message is routed to the 1103 back end having the appropriate \f(CWstickycookie\fP directive\&. 1104 .IP 1105 E\&.g\&., consider the following configuration: 1106 .IP 1107 .nf 1108 service \&.\&.\&. { 1109 \&.\&.\&. 1110 backend one { 1111 \&.\&.\&. 1112 stickycookie "BalancerID=first"; 1113 } 1114 backend two { 1115 \&.\&.\&. 1116 stickycookie "BalancerID=second"; 1117 } 1118 } 1119 .fi 1120 1121 .IP 1122 When clients\&' messages contain cookies named \f(CWBalancerID\fP with 1123 the value \f(CWfirst\fP, then such messages are routed to backend 1124 \f(CWone\fP\&. When the value is \f(CWsecond\fP then they are routed to the 1125 backend \f(CWtwo\fP\&. 1126 .IP 1127 There are basically to provide such cookies to a browser\&. First, a 1128 back end can insert such a cookie into the HTTP response\&. E\&.g\&., 1129 the webserver of back end \f(CWone\fP might insert a cookie named 1130 \f(CWBalancerID\fP, having value \f(CWfirst\fP\&. 1131 Second, Crossroads can insert such cookies using a carefully 1132 crafted directive \f(CWaddclientheader\fP\&. 1133 .IP "Syntax:" 1134 \f(CWstickycookie\fP \fIcookievalue\fP 1135 .IP "Default:" 1136 There is no default\&. 1137 1138 .PP 1139 1140 .SH "4\&.3\&.8: HTTP Header Modification Directives" 1141 .IP "Description:" 1142 Crossroads understands the following 1143 header modification directives: \f(CWaddclientheader\fP, 1144 \f(CWappendclientheader\fP, \f(CWsetclientheader\fP, \f(CWaddserverheader\fP, 1145 \f(CWappendserverheader\fP, \f(CWsetserverheader\fP\&. 1146 .IP 1147 The directive names always consist of 1148 \fIAction\fP\fIDestination\fP\f(CWheader\fP, where: 1149 .IP 1150 .IP o 1151 The action is \f(CWadd\fP, \f(CWappend\fP or \f(CWinsert\fP\&. 1152 .IP 1153 .IP o 1154 Action \f(CWadd\fP adds a header, even when headers with 1155 the same name already are present in an HTTP 1156 message\&. Adding headers is useful for e\&.g\&. \f(CWSet-Cookie\fP 1157 headers; a message may contain several of such headers\&. 1158 .IP 1159 .IP o 1160 Action \f(CWappend\fP adds a header if it isn\&'t present 1161 yet in an HTTP message\&. If such a header is already 1162 present, then the value is appended to the pre-existing 1163 header\&. This is useful for e\&.g\&. \f(CWVia\fP headers\&. Imagine 1164 an HTTP message with a header \f(CWVia: someproxy\fP\&. Then the 1165 directive \f(CWappendclientheader "Via: crossroads"\fP will 1166 rewrite the header to \f(CWVia: someproxy; crossroads\fP\&. 1167 .IP 1168 .IP o 1169 Action \f(CWset\fP overwrites headers with the same 1170 name; or adds a new header if no pre-existing is found\&. 1171 This is useful for e\&.g\&. \f(CWHost\fP headers\&. 1172 .IP 1173 .IP o 1174 The destination is one of \f(CWclient\fP or \f(CWserver\fP\&. When 1175 the destination is \f(CWserver\fP, then Crossroads will apply such 1176 directives to HTTP messages that originate from the browser 1177 and are being forwarded to back ends\&. When the destination is 1178 \f(CWclient\fP, then Crossroads will apply such directives to 1179 backend responses that are shuttled to the browser\&. 1180 .IP 1181 The format of the directives is e\&.g\&. \f(CWaddclientheader 1182 "X-Processed-By: Crossroads"\fP\&. The directives expect one 1183 argument; a string, consisting of a header name, a colon, and a 1184 header value\&. As usual, the directive must end with a semicolon\&. 1185 .IP 1186 The header value may contain one of the following formatting 1187 directives: 1188 .IP 1189 .IP o 1190 \f(CW%a\fP is the availability of the current back end, when 1191 a current back end is established; 1192 .IP o 1193 \f(CW%1a\fP is the availability of the first back end (0 when 1194 unavailable, 1 if available); \f(CW%2a\fP is the availability of 1195 the second back end, and so on; 1196 .IP o 1197 \f(CW%b\fP is the name of the current back end, when one is 1198 established; 1199 .IP o 1200 \f(CW%1b\fP is the name of the first back end, \f(CW%2b\fP of the 1201 second back end, and so on; 1202 .IP o 1203 \f(CW%e\fP is the count of seconds since start of epoch 1204 (January 1st 1970 GMT); 1205 .IP o 1206 \f(CW%r\fP is the IP address of the client that requests a 1207 connection and for whom the external dispatcher should compute 1208 a back end; 1209 .IP o 1210 \f(CW%s\fP is the name of the current service that the client 1211 connected to; 1212 .IP o 1213 \f(CW%t\fP is the current local time in ASCII format, in 1214 \fIYYYY-MM-DD/hhh:mm:ss\fP; 1215 .IP o 1216 \f(CW%T\fP is the current GMT time in ASCIII format; 1217 .IP o 1218 \f(CW%v\fP is the Crossroads version; 1219 .IP o 1220 Any other chararacter following a \f(CW%\fP sign is taken 1221 literally; e\&.g\&. \f(CW%z\fP is just a z\&. 1222 .IP 1223 The following examples show common uses of header modifications\&. 1224 .IP 1225 .IP "Enforcing session stickiness:" 1226 By combining 1227 \f(CWstickycookie\fP and \f(CWaddclientheader\fP, HTTP session 1228 stickiness is enforced\&. Consider the following configuration: 1229 .IP 1230 .nf 1231 service \&.\&.\&. { 1232 \&.\&.\&. 1233 backend one { 1234 \&.\&.\&. 1235 addclientheader "Set-Cookie: BalancerID=first; path=/"; 1236 stickycookie "BalancerID=first"; 1237 } 1238 backend two { 1239 \&.\&.\&. 1240 addclientheader "Set-Cookie: BalancerID=second; path=/"; 1241 stickycookie "BalancerID=second"; 1242 } 1243 } 1244 .fi 1245 1246 .IP 1247 The first request of an HTTP session is balanced to either 1248 backend \f(CWone\fP or \f(CWtwo\fP\&. The server response is enriched 1249 using \f(CWaddclientheader\fP with an appropriate cookie\&. A 1250 subsequent request from the same browser now has that cookie 1251 in place; and is therefore sent to the same back end where the 1252 its predecessors went\&. 1253 .IP 1254 .IP "Hiding the server software version:" 1255 Many servers 1256 (e\&.g\&. Apache) advertize their version, as in \f(CWServer: Apache 1257 1\&.27\fP\&. This potentially provides information to attackers\&. The 1258 following configuration hides such information: 1259 .IP 1260 .nf 1261 service \&.\&.\&. { 1262 \&.\&.\&. 1263 backend one { 1264 \&.\&.\&. 1265 setclientheader "Server: WWW-Server"; 1266 } 1267 } 1268 .fi 1269 1270 .IP 1271 .IP "Informing the server of the clients\&' IP address:" 1272 Since 1273 Crossroads sits \&'in the middle\&' between a client and a back 1274 end, the back end perceives Crossroads as its client\&. The 1275 following sends the true clients\&' IP address to the server, in 1276 a header \f(CWX-Real-IP\fP: 1277 .IP 1278 .nf 1279 service \&.\&.\&. { 1280 \&.\&.\&. 1281 backend one { 1282 \&.\&.\&. 1283 setserverheader "X-Real-IP: %r"; 1284 } 1285 } 1286 .fi 1287 1288 .IP 1289 .IP "Keep-Alive Downgrading:" 1290 The directives 1291 \f(CWsetclientheader\fP and \f(CWsetserverheader\fP also play a key 1292 role in downgrading Keep-Alive connections to 1293 \&'single-shot\&'\&. E\&.g\&., the following configuration makes sure 1294 that no Keep-Alive connections occur\&. 1295 .IP 1296 .nf 1297 service \&.\&.\&. { 1298 \&.\&.\&. 1299 backend one { 1300 \&.\&.\&. 1301 setserverheader "Connection: close"; 1302 setclientheader "Connection: close"; 1303 } 1304 } 1305 .fi 1306 .IP "Syntax:" 1307 .IP o 1308 \f(CWaddclientheader\fP \fIHeadername: headervalue\fP to add a 1309 header in the traffic towards the client, even when another 1310 header \fIHeadername\fP exists; 1311 .IP o 1312 \f(CWappendclientheader\fP \fIHeadername: headervalue\fP to 1313 append \fIheadervalue\fP to an existing header \fIHeadername\fP 1314 in the traffic towards the client, 1315 or to add the whole header alltogether; 1316 .IP o 1317 \f(CWsetclientheader\fP \fIHeadername: headervalue\fP to 1318 overwrite an existing header in the traffic towards the 1319 client, or to add such a header; 1320 .IP o 1321 \f(CWaddserverheader\fP \fIHeadername: headervalue\fP to add a 1322 header in the traffic towards the server, even when another 1323 header \fIHeadername\fP exists; 1324 .IP o 1325 \f(CWappendserverheader\fP \fIHeadername: headervalue\fP to 1326 append \fIheadervalue\fP to an existing header \fIHeadername\fP 1327 in the traffic towards the server, 1328 or to add the whole header alltogether; 1329 .IP o 1330 \f(CWsetserverheader\fP \fIHeadername: headervalue\fP to 1331 overwrite an existing header in the traffic towards the 1332 server, or to add such a header\&. 1333 .IP "Default:" 1334 There is no default\&. 1335 1336 .PP 1337 1338 .SH "5: Tips, Tricks and Remarks" 1339 1340 The following sections elaborate on the directives as described in 1341 section ?? to illustrate how crossroads works and to help you 1342 achieve the "optimal" balancing configuration\&. 1343 .PP 1344 1345 .SH "5\&.1: How back ends are selected in load balancing" 1346 1347 .PP 1348 In order to tune your load balancing, you\&'ll need to understand how 1349 crossroads computes usage, how weighing works, and so on\&. In this 1350 section we\&'ll focus on the dispatching modes \f(CWbysize\fP, \f(CWbyduration\fP 1351 and \f(CWbyconnections\fP only\&. The other dispatching types are 1352 self-explanatory\&. 1353 .PP 1354 1355 .SH "5\&.1\&.1: Bysize, byduration or byconnections?" 1356 1357 .PP 1358 As stated before, crossroads doesn\&'t know \&'what a service does\&' and 1359 how to judge whether a given back end is very busy or not\&. You 1360 must therefore give the right hints: 1361 .PP 1362 .IP o 1363 In general, a service which is CPU bound, will be more 1364 busy when it takes longer to process a request\&. The dispatch 1365 mode \f(CWbyduration\fP is appropriate here\&. 1366 .IP 1367 .IP o 1368 In contrast, a service which is filesystem bound, will be 1369 more busy when more data are transferred\&. The dispatch mode 1370 \f(CWbysize\fP is apppropriate\&. 1371 .IP 1372 .IP o 1373 The dispatch mode \f(CWbyduration\fP can also be used when 1374 network latency is an issue\&. E\&.g\&., if your balancer has back 1375 ends that are geograpically distributed, then \f(CWbyduration\fP 1376 would be a good way to select best available back ends\&. 1377 .IP 1378 .IP o 1379 Furthermore it is noteworthy that \f(CWdispatchmode 1380 byduration\fP is not usable for interactive processes such as 1381 SSH logins\&. Idle time of a 1382 login adds to the duration, while causing (almost) no 1383 load\&. Mode \f(CWbyduration\fP should only be used for automated 1384 processes that don\&'t wait for user interaction (e\&.g\&., SOAP 1385 calls and other HTTP requests)\&. 1386 .IP 1387 .IP o 1388 As a last remark, the dispatching mode \f(CWbyconnections\fP can 1389 be used if you don\&'t have other clues for load 1390 estimations\&. 1391 .IP 1392 E\&.g\&., consider a database connection\&. What\&'s 1393 heavier on the back end, time-consuming connections, or connections 1394 where loads of bytes are transferred? Well, that depends\&. A 1395 tough \f(CWselect\fP query that joins multiple tables can be very 1396 heavy on the back end, though the response set can be quite 1397 small - and hence the number of 1398 transferred bytes\&. That would suggest 1399 dispatching by duration\&. However, \f(CWbyduration\fP 1400 balancing doesn\&'t respresent the true world, when interactive 1401 connections can occur where users have an idle TCP connection to 1402 the database: 1403 this consumes time, but no bytes (see the SSH login example 1404 above)\&. In this case, the dispatch mode \f(CWbyconnections\fP may be 1405 your best bet\&. 1406 .IP 1407 1408 .SH "5\&.1\&.2: Averaging size and duration" 1409 1410 .PP 1411 The configuration statement \f(CWdispatchmode bysize\fP or \f(CWbyduration\fP 1412 allows an optional modifier \f(CWover\fP \fInumber\fP, where the stated 1413 number represents a connection count\&. When this modifier is present, then 1414 crossroads will use a moving average over the last \fIn\fP connections to 1415 compute duration and size figures\&. 1416 .PP 1417 In the real world you\&'ll always want this modifier\&. E\&.g\&., consider two 1418 back ends that are running for years now, and one of them is suddenly 1419 overloaded and very busy (it experiences a \&'spike\&' in activity)\&. 1420 When the \f(CWover\fP modifier is absent, then 1421 the sudden load will hardly show up in the usage figures -- it will 1422 flatten out due to the large usage figures already stored in the years 1423 of service\&. 1424 .PP 1425 In contrast, when e\&.g\&. \f(CWover 3\fP is in effect, then a sudden load 1426 does show up -- because it highly contributes to the average of three 1427 connections\&. 1428 .PP 1429 1430 .SH "5\&.1\&.3: Specifying decays" 1431 1432 .PP 1433 Decays are also only relevant when crossroads computes the \&'next best 1434 back end\&' by size (bytes) or duration (seconds)\&. E\&.g\&., imagine two 1435 back ends A and B, both averaged over say 3 connections\&. 1436 .PP 1437 Now when back end A is suddenly hit by a spike, 1438 its average would go up accordingly\&. But the back end would never 1439 again be used, unless B also received a similar spike, because A\&'s 1440 \&'usage data\&' over its last three connections would forever be larger than 1441 B\&'s data\&. 1442 .PP 1443 For that reason, you should in real situations probably always 1444 specify a decay, so that the backend selection algorithm recovers from 1445 spikes\&. Note that the usage data of the back end where a decay is 1446 specified, decay when \fBother\fP back ends are hit\&. The decay parameter 1447 is like specifying how fast your body regenerates when someone else 1448 does the work\&. 1449 .PP 1450 The below configuration illustrates this: 1451 .PP 1452 .nf 1453 /* Definition of the service */ 1454 service soap { 1455 /* Local TCP port */ 1456 port 8080; 1457 1458 /* We\&'ll select back ends by the processing 1459 * duration 1460 */ 1461 dispatchmode byduration over 3; 1462 1463 /* First back end: */ 1464 backend A { 1465 /* Back end IP address and port */ 1466 server 10\&.1\&.1\&.1:8080; 1467 1468 /* When this back end is NOT hit because 1469 * the other one was less busy, then the 1470 * usage parameters decay 10% per connection 1471 */ 1472 decay 10; 1473 } 1474 1475 /* Second back end: */ 1476 backend B { 1477 server 10\&.1\&.1\&.2:8080; 1478 decay 10; 1479 } 1480 } 1481 .fi 1482 1483 .PP 1484 1485 .SH "5\&.1\&.4: Adjusting the weights" 1486 1487 .PP 1488 The back end modifier \f(CWweight\fP is useful in situations where your 1489 back ends differ in respect to performance\&. E\&.g,\&. your back ends may 1490 be geographically distributed, and you know that a given back end is 1491 difficult to reach and often experiences network lag\&. 1492 .PP 1493 Or you may have 1494 one primary back end, a system with a fast CPU and enough memory, and a 1495 small fall-back back end, with a slow CPU and short on memory\&. In that 1496 case you know in advance that the second back end should be used only 1497 rarely\&. Most requests should go to the big server, up to a certain load\&. 1498 .PP 1499 In such cases you will know in advance that the best performing back ends 1500 should be selected the most often\&. Here\&'s where the \f(CWweight\fP 1501 statement comes in: you can simply increase the weight of the back 1502 ends with the least performance, so that they are selected less 1503 frequently\&. 1504 .PP 1505 E\&.g\&., consider the following configuration: 1506 .PP 1507 .nf 1508 service soap { 1509 port 8080; 1510 dispatchmode byduration over 3; 1511 backend A { 1512 server 10\&.1\&.1\&.1:8080; 1513 decay 20; 1514 } 1515 backend B { 1516 server 10\&.1\&.1\&.2:8080; 1517 weight 2; 1518 decay 10; 1519 } 1520 backend C { 1521 server 10\&.1\&.1\&.3:8080; 1522 weight 4; 1523 decay 5; 1524 } 1525 } 1526 .fi 1527 1528 .PP 1529 This will cause crossroads to select back ends by the processing time, 1530 averaging over the last three connections\&. However, backend B will kick 1531 in only when its usage is half of the usage of A (back end B is 1532 probably only half as fast as A)\&. Backend C will kick in only when its 1533 usage is a quarter of the usage of A, which is half of the usage of B 1534 (back end C is probably very weak, and just a fall-back system incase 1535 both A and B crash)\&. Note also that A\&'s usage data decay much faster 1536 than B\&'s and C\&'s: we\&'re assuming that this big server recovers quicker 1537 than its smaller siblings\&. 1538 .PP 1539 1540 .SH "5\&.1\&.5: Throttling the number of concurrent connections" 1541 1542 .PP 1543 If you suspect that your service may occasionally receive \&'spikes\&' of 1544 activity\e (which you should always assume), then it might be a 1545 good idea to protect your service by specifying a maximum number of 1546 concurrent connections\&. This protection can be specified on two levels: 1547 .PP 1548 .IP "On the service level" 1549 a statement like \f(CWmaxconnections 1550 100;\fP states that the service as a whole will never 1551 service more than 100 concurrent connections\&. This means that 1552 all your back ends and the crossroads balancer itself 1553 will be protected from being overloaded\&. 1554 .IP "On the back end level" 1555 a statement like \f(CWmaxconnections 10;\fP 1556 states that this particular back end will never have more 1557 than 10 concurrent connections; regardless of the overall 1558 setting on the service level\&. This means that this 1559 particular back end will be protected from being 1560 overloaded (regardless of what other back ends may 1561 experience)\&. 1562 .PP 1563 The \f(CWmaxconnections\fP statement, combined with a back end selection 1564 algorithm, allows very fine granularity\&. The \f(CWmaxconnections\fP statement 1565 on the back end level is like a hand brake: even when you specify a 1566 back end algorithm that would protect a given back end from being used 1567 too much, a situation may occur where that back end is about to be 1568 hit\&. A \f(CWmaxconnections\fP statement on the level of that back may then 1569 protect it\&. 1570 .PP 1571 1572 .SH "5\&.2: Using an external program to dispatch" 1573 1574 .PP 1575 As mentioned before, Crossroads supports several built-in dispatch 1576 modes\&. However, you are always free to hook-in your own dispatch mode 1577 that determines the next back end using your own specific 1578 algorithm\&. This section explains how to do it\&. 1579 .PP 1580 1581 .SH "5\&.2\&.1: Configuring the external handler" 1582 1583 .PP 1584 First, the \f(CWdispatchmode\fP statement needs to inform Crossroads that 1585 an external program will do the job\&. The syntax is: \f(CWdispatchmode 1586 externalhandler\fP \fIprogram arguments\fP\&. The \fIprogram\fP must point to 1587 an executable program that will be started by Crossroads\&. The 1588 specifier \fIarguments\fP can be anything you want; those will be the 1589 arguments to Crossroads\&. You can however use the following special 1590 format specifiers: 1591 .PP 1592 .IP o 1593 \f(CW%a\fP is the availability of the current back end, when 1594 a current back end is established; 1595 .IP o 1596 \f(CW%1a\fP is the availability of the first back end (0 when 1597 unavailable, 1 if available); \f(CW%2a\fP is the availability of 1598 the second back end, and so on; 1599 .IP o 1600 \f(CW%b\fP is the name of the current back end, when one is 1601 established; 1602 .IP o 1603 \f(CW%1b\fP is the name of the first back end, \f(CW%2b\fP of the 1604 second back end, and so on; 1605 .IP o 1606 \f(CW%e\fP is the count of seconds since start of epoch 1607 (January 1st 1970 GMT); 1608 .IP o 1609 \f(CW%r\fP is the IP address of the client that requests a 1610 connection and for whom the external dispatcher should compute 1611 a back end; 1612 .IP o 1613 \f(CW%s\fP is the name of the current service that the client 1614 connected to; 1615 .IP o 1616 \f(CW%t\fP is the current local time in ASCII format, in 1617 \fIYYYY-MM-DD/hhh:mm:ss\fP; 1618 .IP o 1619 \f(CW%T\fP is the current GMT time in ASCIII format; 1620 .IP o 1621 \f(CW%v\fP is the Crossroads version; 1622 .IP o 1623 Any other chararacter following a \f(CW%\fP sign is taken 1624 literally; e\&.g\&. \f(CW%z\fP is just a z\&. 1625 .PP 1626 Note that the format specifiers such as \f(CW%b\fP don\&'t make sense in the 1627 phase in which an external handler is called, since there is no 1628 current back end yet (the job of the handler is to supply one)\&. 1629 .PP 1630 1631 .SH "5\&.2\&.2: Writing the external handler" 1632 1633 .PP 1634 The external handler is activated using the arguments that are 1635 specified in \f(CW/etc/crossroads\&.conf\fP\&. The external handler can do 1636 whatever it wants, but ultimately, it must write a back end name on 1637 its \fIstdout\fP\&. Crossroads reads this, and if the back end is 1638 available, uses that back end for the connection\&. 1639 .PP 1640 1641 .SH "5\&.2\&.3: Examples of external handlers" 1642 1643 .PP 1644 This section shows some examples of Crossroads configurations 1645 vs\&. external handlers\&. The sample handlers that are shown here, are 1646 also included in the Crossroads distribution, under the directory 1647 \f(CWetc/\fP\&. Also note that the examples shown here are just 1648 quick-and-dirty Perl scripts, meant to illustrate only\&. Your 1649 applications may need other external handlers, but you can use the 1650 shown scripts as a starting point\&. 1651 .PP 1652 .SH "Round-robin dispatching" 1653 1654 .PP 1655 This example is trivial in the sense that round-robin dispatching is 1656 already built into Crossroads, so 1657 that using an external handler for this purpose only slows down 1658 Crossroads\&. However, it\&'s a good starting example\&. 1659 .PP 1660 The Crossroads configuration is shown below: 1661 .PP 1662 .nf 1663 service test { 1664 port 8001; 1665 verbosity on; 1666 revivinginterval 5; 1667 1668 dispatchmode externalhandler 1669 /usr/local/src/crossroads/etc/dispatcher-roundrobin 1670 %1b %1a %2b %2a; 1671 1672 backend testone { 1673 server localhost:3128; 1674 verbosity on; 1675 } 1676 backend testtwo { 1677 server locallhost:3128; 1678 verbosity on; 1679 } 1680 } 1681 .fi 1682 1683 .PP 1684 The relevant \f(CWdispatchmode\fP statement invokes the external program 1685 \f(CWdispatcher-roundrobin\fP with four arguments: the name of the first 1686 back end (\f(CWtestone\fP), its availability (0 or 1), the name of the 1687 second back end (\f(CWtesttwo\fP) and its availability (0 or 1)\&. 1688 .PP 1689 The external handler, which is also included in the Crossroads 1690 distribution, is shown below\&. It is a Perl script\&. 1691 .PP 1692 .nf 1693 #!/usr/bin/perl 1694 1695 use strict; 1696 1697 # Example of a round-robin external dispatcher\&. This is totally 1698 # superfluous, Crossroads has this on-board; if you use the external 1699 # program for determining round-robin dispatching, then you\&'ll only 1700 # slow things down\&. This script is just meant as an example\&. 1701 1702 # Globals / configuration 1703 # ----------------------- 1704 my $log = \&'/tmp/exthandler\&.log\&'; # Debug log, set to /dev/null to suppress 1705 my $statefile = \&'/tmp/rr\&.last\&'; # Where we keep the last used 1706 1707 # Logging 1708 # ------- 1709 sub msg { 1710 return if ($log eq \&'/dev/null\&' or $log eq \&'\&'); 1711 open (my $of, ">>$log") or return; 1712 print $of (scalar(localtime()), \&' \&', @_); 1713 } 1714 1715 # Read the last used back end 1716 # --------------------------- 1717 sub readlast() { 1718 my $ret; 1719 1720 if (open (my $if, $statefile)) { 1721 $ret = <$if>; 1722 chomp ($ret); 1723 close ($if); 1724 msg ("Last used back end: $ret\en"); 1725 return ($ret); 1726 } 1727 msg ("No last-used back end (yet)\en"); 1728 return (undef); 1729 } 1730 1731 # Write back the last used back end, reply to Crossroads and stop 1732 # --------------------------------------------------------------- 1733 sub reply ($) { 1734 my $last = shift; 1735 1736 if (open (my $of, ">$statefile")) { 1737 print $of ("$last\en"); 1738 } 1739 print ("$last\en"); 1740 exit (0); 1741 } 1742 1743 # Main starts here 1744 # ---------------- 1745 1746 # Collect the cmdline arguments\&. We expect pairs of backend-name / 1747 # backend-availablility, and we\&'ll store only the available ones\&. 1748 msg ("Dispatch request received\en"); 1749 my @backend; 1750 for (my $i = 0; $i <= $#ARGV; $i += 2) { 1751 push (@backend, $ARGV[$i]) if ($ARGV[$i + 1]); 1752 } 1753 msg ("Available back ends: @backend\en"); 1754 1755 # Let\&'s see what the last one is\&. If none found, then we return the 1756 # first available back end\&. Otherwise we need to go thru the list of 1757 # back ends, and return the next one in line\&. 1758 my $last = readlast(); 1759 if ($last eq \&'\&') { 1760 msg ("Returning first available back end $backend[0]\en"); 1761 reply ($backend[0]); 1762 } 1763 1764 # There **was** a last back end\&. Try to match it in the list, 1765 # then return the next-in-line\&. 1766 for (my $i = 0; $i < $#backend; $i++) { 1767 if ($last eq $backend[$i]) { 1768 msg ("Returning next back end ", $backend[$i + 1], "\en"); 1769 reply ($backend[$i + 1]); 1770 } 1771 } 1772 1773 # No luck\&.\&. run back to the first one\&. 1774 msg ("Returning first back end $backend[0]\en"); 1775 reply ($backend[0]); 1776 .fi 1777 1778 .PP 1779 The working of the script is basically as follows: 1780 .PP 1781 .IP o 1782 The argument list is scanned\&. Back ends that are 1783 available are collected in an array \f(CW@backend\fP\&. 1784 .IP 1785 .IP o 1786 The script queries a state file \f(CW/tmp/rr\&.last\fP\&. If a 1787 back end name occurs there, then the next back end is looked 1788 up in \f(CW@backend\fP and returned to Crossroads\&. If no last back 1789 is unknown or can\&'t be matched, then the first available back 1790 end (first element of \f(CW@backend\fP) is returned to Crossroads\&. 1791 .IP 1792 .IP o 1793 Informing Crossroads is done via the subroutine 1794 \f(CWreply()\fP\&. This code writes the selected back end to file 1795 \f(CW/tmp/rr\&.last\fP (for future usage) and prints the back end 1796 name to \fIstdout\fP\&. 1797 .IP 1798 .IP o 1799 The script logs its actions to a file 1800 \f(CW/tmp/exthandler\&.log\fP\&. This log file can be inspected for 1801 the script\&'s actions\&. 1802 .PP 1803 .SH "Dispatching by the client IP address" 1804 1805 .PP 1806 The following example shows a useful real-life situation\&. The 1807 situation is as follows: 1808 .PP 1809 .IP o 1810 Crossroads is used as a single-address point to forward 1811 Remote Desktop requests to a farm of Windows systems, where 1812 users can work via remote access; 1813 .IP 1814 .IP o 1815 However, users may stop their session, and when they 1816 re-connect, they expect to be sent to the Windows system that 1817 they had worked on previously; 1818 .IP 1819 .IP o 1820 Client PC\&'s have their distinct IP addresses, which 1821 distinguishes them\&. 1822 .IP 1823 .IP o 1824 Of four windows systems, two are large servers, and two 1825 are small ones\&. We\&'ll want to assign large servers to clients 1826 when we have a choice\&. 1827 .PP 1828 The requirements resemble session stickiness in HTTP, except that the remote 1829 desktop protocol doesn\&'t support stickiness\&. This situation is a 1830 perfect example of how an external handler can help: 1831 .PP 1832 .IP o 1833 A suitable dispatch mode isn\&'t yet available in 1834 Crossroads, but can be easily coded in an external handler; 1835 .IP 1836 .IP o 1837 The potential delay due to the calling of an external 1838 handler won\&'t even be noticed\&. This is a network service where 1839 the connection time isn\&'t critical; we\&'d expect only a few 1840 (albeit lengthy) TCP connections\&. 1841 .PP 1842 The approach to the solution of this problem uses several external 1843 program hooks: 1844 .PP 1845 .IP o 1846 An external dispatcher handler will be responsible for 1847 suggesting a back end, given a client IP and given the current 1848 timestamp\&. This handler will consult an internal 1849 administration to see whether the stated IP address should 1850 re-use a back end, or to determine which back end is free for usage\&. 1851 .IP o 1852 An external hook \f(CWonstart\fP will be responsible for 1853 updating the internal administration; i\&.e\&., to flag a back end 1854 as \&'occupied\&'\&. 1855 .IP o 1856 The external hooks \f(CWonfailure\fP and \f(CWonend\fP will be 1857 responsible for flagging a back end as \&'free\&' again; i\&.e\&., for 1858 erasing any previous information that states that the back end 1859 was occupied\&. 1860 .PP 1861 The Crossroads configuration is shown below\&. Only four Windows back 1862 ends are shown\&. Each back end is configured on a 1863 given IP address, port 3389, and is limited to one concurrent connection 1864 (otherwise a new user might \&'steal\&' a running desktop session)\&. 1865 .PP 1866 .nf 1867 service rdp { 1868 port 3389; 1869 revivinginterval 5; 1870 1871 /* rdp-helper dispatch IP STAMP \&.\&.\&. will suggest a back end to use, 1872 * arguments are for all back ends: name, availability, weight */ 1873 dispatchmode externalhandler 1874 /usr/local/src/crossroads/etc/rdp-helper dispatch %r %e 1875 %1b %1a %1w 1876 %2b %2a %2w 1877 %3b %3a %3w 1878 %4b %4a %4w; 1879 1880 backend win1 { 1881 server 10\&.1\&.1\&.1:3389; 1882 maxconnections 1; 1883 /* rdp-helper start IP STAMP BACKEND will log the actual start 1884 * of a connection; 1885 * rdp-helper end IP will log the ending of a connection */ 1886 onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b; 1887 onend /usr/local/src/crossroads/etc/rdp-helper end %r; 1888 onfail /usr/local/src/crossroads/etc/rdp-helper end %r; 1889 } 1890 backend win2 { 1891 server 10\&.1\&.1\&.2:3389; 1892 maxconnections 1; 1893 onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b; 1894 onend /usr/local/src/crossroads/etc/rdp-helper end %r; 1895 onfail /usr/local/src/crossroads/etc/rdp-helper end %r; 1896 } 1897 backend win3 { 1898 server 10\&.1\&.1\&.3:3389; 1899 maxconnections 1; 1900 weight 2; 1901 onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b; 1902 onend /usr/local/src/crossroads/etc/rdp-helper end %r; 1903 onfail /usr/local/src/crossroads/etc/rdp-helper end %r; 1904 } 1905 backend win4 { 1906 server 10\&.1\&.1\&.4:3389; 1907 maxconnections 1; 1908 weight 3; 1909 onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b; 1910 onend /usr/local/src/crossroads/etc/rdp-helper end %r; 1911 onfail /usr/local/src/crossroads/etc/rdp-helper end %r; 1912 } 1913 } 1914 .fi 1915 1916 .PP 1917 Depending on the dispatcher stage, the exernal handler \f(CWrdp-helper\fP 1918 is invoked in different ways: 1919 .PP 1920 .IP "During dispatching" 1921 the helper is called to suggest a back 1922 end\&. The arguments are an action indicator \f(CWdispatch\fP, the 1923 client\&'s IP address, the timestamp, and four triplets that 1924 represent back ends: per back end its name, its availability, 1925 and its weight\&. The purpose of the helper is to tell 1926 Crossroads which back end to use\&. 1927 .IP 1928 .IP "During connection start" 1929 the helper will be invoked to 1930 inform it of the start of a connection, given a client IP 1931 address\&. 1932 .IP 1933 .IP "When a connection terminates" 1934 the helper will be invoked 1935 to inform it that the connection has ended\&. 1936 .PP 1937 Here\&'s the external handler as Perl script\&. It uses the module 1938 \f(CWGDBM_File\fP which most likely will not be part of standard Perl 1939 distributions, but can be added using CPAN\&. (Alternatively, any other 1940 database module can be used\&.) 1941 .PP 1942 .nf 1943 #!/usr/bin/perl 1944 1945 use strict; 1946 use GDBM_File; 1947 1948 # Global variables and configuration 1949 # ---------------------------------- 1950 my $log = \&'/tmp/exthandler\&.log\&'; # Debug log, set to /dev/null to suppress 1951 my $cdb = \&'/tmp/client\&.db\&'; # GDBM database of clients 1952 my %db; # \&.\&. and memory representation of it 1953 my $timeout = 24*60*60; # Timeout of a connection in secs 1954 1955 # Logging 1956 # ------- 1957 sub msg { 1958 return if ($log eq \&'/dev/null\&' or $log eq \&'\&'); 1959 open (my $of, ">>$log") or return; 1960 print $of (scalar(localtime()), \&' \&', @_); 1961 close ($of); 1962 } 1963 1964 # Reply a back end to the caller and stop processing\&. 1965 # --------------------------------------------------- 1966 sub reply ($) { 1967 my $b = shift; 1968 msg ("Suggesting $b to Crossroads\&.\en"); 1969 print ("$b\en"); 1970 exit (0); 1971 } 1972 1973 # Is a value in an array 1974 # ---------------------- 1975 sub inarray { 1976 my $val = shift; 1977 for my $other (@_) { 1978 return (1) if ($other eq $val); 1979 } 1980 return (0); 1981 } 1982 1983 # A connection is starting 1984 # ------------------------ 1985 sub start { 1986 my ($ip, $stamp, $backend) = @_; 1987 msg ("Logging START of connection for IP $ip on stamp $stamp, ", 1988 "back end $backend\en"); 1989 $db{$ip} = "$backend:$stamp"; 1990 } 1991 1992 # A connection has ended 1993 # ---------------------- 1994 sub end { 1995 my $ip = shift; 1996 msg ("Logging END of connection for IP $ip\en"); 1997 $db{$ip} = undef; 1998 } 1999 2000 # Request to determine a back end 2001 # ------------------------------- 2002 sub dispatch { 2003 my $ip = shift; 2004 my $stamp = shift; 2005 2006 msg ("Request to dispatch IP $ip on stamp $stamp\en"); 2007 2008 # Read the next arguments\&. They are triplets of 2009 # backend-name / availability / weight\&. Store if the back end is 2010 # available\&. 2011 my (@backends, @weights); 2012 for (my $i = 0; $i < $#_; $i += 3) { 2013 if ($_[$i + 1] != 0) { 2014 push (@backends, $_[$i]); 2015 push (@weights, $_[$i + 2]); 2016 msg ("Candidate back end: $_[$i] with weight ", $_[$i + 2], "\en"); 2017 } 2018 } 2019 2020 # See if this is a reconnect by a previously seen client IP\&. We\&'ll 2021 # treat this as a reconnect if the timeout wasn\&'t yet exceeded\&. 2022 if ($db{$ip} ne \&'\&') { 2023 my ($last_backend, $last_stamp) = split (/:/, $db{$ip}); 2024 msg ("IP $ip had last connected on $last_stamp to $last_backend\en"); 2025 if ($stamp < $last_stamp + $timeout) { 2026 msg ("Timeout not yet exceeded, this may be a reconnect\en"); 2027 # We\&'ll allow a reconnect only if the stated last_backend is 2028 # free (sanity check)\&. 2029 if (inarray ($last_backend, @backends)) { 2030 msg ("Last back end $last_backend is available, ", 2031 "letting through\en"); 2032 reply ($last_backend); 2033 } else { 2034 msg ("Last used back end isn\&'t free, suggesting a new one\en"); 2035 } 2036 } else { 2037 msg ("Timeout exceeded, suggesting a new back end\en"); 2038 } 2039 } else { 2040 msg ("Np preveious connection data, suggesting a new back end\en"); 2041 } 2042 2043 my $bestweight = -1; 2044 my $bestbackend; 2045 for (my $i = 0; $i <= $#weights; $i++) { 2046 if ($bestweight == -1 or $bestweight > $weights[$i]) { 2047 $bestweight = $weights[$i]; 2048 $bestbackend = $backends[$i]; 2049 } 2050 } 2051 2052 msg ("Best back end: $bestbackend (given weight $bestweight)\en"); 2053 reply ($bestbackend); 2054 } 2055 2056 # Main starts here 2057 # ---------------- 2058 msg ("Start of run, attaching GDBM database \&'$cdb\&'\en"); 2059 tie (%db, \&'GDBM_File\&', $cdb, &GDBM_WRCREAT, 0600); 2060 2061 # The first argument must be an action \&'dispatch\&', \&'start\&' or \&'end\&'\&. 2062 # Depending on the action, we do stuff\&. 2063 my $action = shift (@ARGV); 2064 if ($action eq \&'dispatch\&') { 2065 dispatch (@ARGV); 2066 } elsif ($action eq \&'start\&') { 2067 start (@ARGV); 2068 } elsif ($action eq \&'end\&') { 2069 end (@ARGV); 2070 } else { 2071 print STDERR ("Usage: rdp-helper {dispatch|start|end} args\en"); 2072 exit (1); 2073 } 2074 .fi 2075 2076 .PP 2077 2078 .SH "5\&.3: HTTP Session Stickiness" 2079 2080 .PP 2081 This section focuses on HTTP session stickiness\&. This term refers to 2082 the ability of a balancer to route a conversation between browser and 2083 a backend farm always to the same back end\&. In other words: once a 2084 back end is selected by the balancer, it will remain the back end of 2085 choice, even for subsequent connections\&. 2086 .PP 2087 2088 .SH "5\&.3\&.1: Don\&'t use stickiness!" 2089 2090 .PP 2091 The rule of thumb as far as the balancer is concerned, is: \fBDo not 2092 use HTTP session stickiness unless you really have to\&.\fP Enabling 2093 session stickiness hampers failover, balancing and performance: 2094 .PP 2095 .IP o 2096 Failover is hampered because during the session, 2097 the balancer has to assign new connections to the same back 2098 end that was selected at the start of a session\&. If the back 2099 end suddenly goes \&'down\&', then the session will most likely 2100 crash\&. (Actually, when a back end becomes unreachable in the 2101 middle of a session, Crossroads will assign a new back end to 2102 that session\&. This will most likely result in a malfunction 2103 of the underlying application\&.) 2104 .IP o 2105 Balancing is hampered because at the start of the session, 2106 the balancer has selected the next-best back end\&. But during 2107 the session, that back end may well become overloaded\&. The 2108 balancer however must continue to send the requests there\&. 2109 .IP o 2110 Performance is hampered because crossroads needs to \&'unpack\&' 2111 messages as they are passed to and fro\&. That\&'s because 2112 crossroads needs to check the HTTP headers in the messages 2113 for persistence cookies\&. 2114 .PP 2115 There is a number of measures that you can take to avoid using session 2116 stickiness\&. E\&.g\&., session data can be \&'shared\&' between web back 2117 ends\&. PHP offers functionality to store session data in a database, so 2118 that all PHP applications have access to these data\&. Application 2119 servers such as Websphere can be configured to replicate session data 2120 between nodes\&. 2121 .PP 2122 2123 .SH "5\&.3\&.2: But if you must\&.\&." 2124 2125 .PP 2126 However, if you \fBmust\fP use session stickiness, then proceed as 2127 follows: 2128 .PP 2129 .IP o 2130 At the level of a \f(CWservice\fP description, set the type to 2131 \f(CWhttp\fP\&. 2132 .IP o 2133 At the level of each back end description, configure the 2134 \f(CWstickycookie\fP and a \f(CWaddclientheader\fP directives\&. 2135 .PP 2136 Once crossroads sees that, it will examine each HTTP message that it 2137 shuttles between client and back end: 2138 .PP 2139 .IP o 2140 If there is no persistence cookie in the HTTP headers of a 2141 client\&'s request, then the message must be the first one and 2142 a new session should be established\&. 2143 Crossroads selects an appropriate back 2144 end, sends the message to that back end, catches the reply, 2145 and inserts a \f(CWSet-Cookie\fP directive\&. 2146 .IP o 2147 If there is a persistence cookie in the HTTP headers of a 2148 client\&'s request, then the request is part of an already 2149 established session\&. Crossroads analyzes the cookie and 2150 forwards the request to the appropriate back end\&. 2151 .PP 2152 Below is a short example of a configuration\&. 2153 .PP 2154 .nf 2155 service www { 2156 port 80; 2157 type http; 2158 revivinginterval 15; 2159 dispatchmode byconnections; 2160 2161 backend one { 2162 server 10\&.1\&.1\&.100:80; 2163 stickycookie XRID=100; 2164 addclientheader "Set-Cookie: XRID=100; Path=/"; 2165 } 2166 2167 backend two { 2168 server 10\&.1\&.1\&.101:80; 2169 stickycookie XRID=101; 2170 addclientheader "Set-Cookie: XRID=101; Path=/"; 2171 } 2172 } 2173 .fi 2174 2175 .PP 2176 Note how the cookie names and values in the directives 2177 \f(CWstickycookie\fP and \f(CWaddclientheader\fP match\&. That is obviously a 2178 prerequisite for stickiness\&. 2179 .PP 2180 2181 .SH "5\&.4: Passing the client\&'s IP address" 2182 2183 .PP 2184 Since Crossroads just shuttles bytes to and fro, meta-information of 2185 network connections is lost\&. As far as the back ends are concerned, 2186 their connections originate at the Crossroads junction\&. 2187 For example, standard Apache access logs will show the IP address of 2188 Crossroads\&. 2189 .PP 2190 In order to compensate for this, Crossroads can insert a special 2191 header in HTTP connections, to inform the back end of the original 2192 client\&'s IP address\&. In order to enable this, the Crossroads 2193 configuration must state the following: 2194 .PP 2195 .IP o 2196 The service type must be \f(CWhttp\fP, and not \f(CWany\fP; 2197 .IP o 2198 In the back end definition, the following statement must 2199 occur: 2200 .br 2201 \f(CWaddserverheader "X-Real-IP: %r";\fP 2202 .br 2203 You are of course free to choose the header name; the here 2204 used \f(CWX-Real-IP\fP is a common name for this purpose\&. 2205 .PP 2206 After this, HTTP traffic that arrives at the back ends has a new 2207 header: \f(CWX-Real-IP\fP, holding the client\&'s IP address\&. 2208 \fBNote that\fP once the type is set to \f(CWhttp\fP, Crossroads\&' 2209 performance will be hampered -- all passing messages will have to be 2210 unpacked and analyzed\&. 2211 .PP 2212 2213 .SH "5\&.4\&.1: Sample Crossroads configuration" 2214 2215 .PP 2216 The below sample configuration shows two HTTP back ends that receive 2217 the client\&'s IP address: 2218 .PP 2219 .nf 2220 2221 service www { 2222 port 80; 2223 type http; 2224 revivinginterval 5; 2225 dispatchmode roundrobin; 2226 2227 backend one { 2228 server 10\&.1\&.1\&.100:80; 2229 addserverheader "X-Real-IP: %r"; 2230 } 2231 2232 backend two { 2233 server 10\&.1\&.1\&.200:80; 2234 addserverheader "X-Real-IP: %r"; 2235 } 2236 } 2237 .fi 2238 2239 .PP 2240 2241 .SH "5\&.4\&.2: Sample Apache configuration" 2242 2243 .PP 2244 The method by which each back end analyzes the header \f(CWX-Real-IP\fP 2245 will obviously be different per server implementations\&. However, a 2246 common method with the Apache webserver is to log the client\&'s IP 2247 address into the access log\&. 2248 .PP 2249 Often this is accomplished using the log format \f(CWcustom\fP, defined as 2250 follows: 2251 .PP 2252 .nf 2253 LogFormat "%h %l %u %t %D \e"%r\e" %>s %b" common 2254 CustomLog logs/access_log common 2255 .fi 2256 2257 .PP 2258 The first line defines the format \f(CWcommon\fP, with the remote host 2259 specified by \f(CW%h\fP\&. The second line sends access information to a log 2260 file \f(CWlogs/access_log\fP, using the previously defined format 2261 \f(CWcommon\fP\&. 2262 .PP 2263 Furtunately, Apache\&'s \f(CWLogFormat\fP allows one to log contents of 2264 headers\&. By replacing the \f(CW%h\fP with \f(CW%{X-Real-IP}i\fP, the desired 2265 information is sent to the log\&. Therefore, normally you can simply 2266 redefine the \f(CWcommon\fP format to 2267 .PP 2268 .nf 2269 LogFormat "%{X-Real-IP}i %l %u %t %D \e"%r\e" %>s %b" common 2270 .fi 2271 2272 .PP 2273 2274 .SH "5\&.5: Debugging network traffic" 2275 2276 .PP 2277 Incase the traffic between 2278 client and backend 2279 must be debugged, the statement \f(CWtrafficlog\fP \fIfilename\fP can 2280 be issued\&. This causes the traffic to be dumped in hexadecimal 2281 format to the stated filename\&. 2282 .PP 2283 Traffic sent by the client is prefixed by a \fBC\fP, traffic sent by 2284 the back end is prefixed by a \fBB\fP\&. Below is a sample traffic 2285 dump of a browser trying to get a HTML page\&. The server replies 2286 that the page was not modified\&. 2287 .PP 2288 .nf 2289 C 0000 47 45 54 20 68 74 74 70 3a 2f 2f 77 77 77 2e 63 GET http://www\&.c 2290 C 0010 73 2e 68 65 6c 73 69 6e 6b 69 2e 66 69 2f 6c 69 s\&.helsinki\&.fi/li 2291 C 0020 6e 75 78 2f 6c 69 6e 75 78 2d 6b 65 72 6e 65 6c nux/linux-kernel 2292 C 0030 2f 32 30 30 31 2d 34 37 2f 30 34 31 37 2e 68 74 /2001-47/0417\&.ht 2293 C 0040 6d 6c 20 48 54 54 50 2f 31 2e 31 0d 0a 43 6f 6e ml HTTP/1\&.1\&.\&.Con 2294 C 0050 6e 65 63 74 69 6f 6e 3a 20 63 6c 6f 73 65 0d 0a nection: close\&.\&. 2295 \&. 2296 \&. etcetera 2297 \&. 2298 B 0000 48 54 54 50 2f 31 2e 30 20 33 30 34 20 4e 6f 74 HTTP/1\&.0 304 Not 2299 B 0010 20 4d 6f 64 69 66 69 65 64 0d 0a 44 61 74 65 3a Modified\&.\&.Date: 2300 B 0020 20 54 75 65 2c 20 31 32 20 4a 75 6c 20 32 30 30 Tue, 12 Jul 200 2301 B 0030 35 20 30 39 3a 34 39 3a 34 37 20 47 4d 54 0d 0a 5 09:49:47 GMT\&.\&. 2302 B 0040 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 65 Content-Type: te 2303 B 0050 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 65 74 xt/html; charset 2304 \&. 2305 \&. etcetera 2306 \&. 2307 .fi 2308 2309 .PP 2310 Turning on traffic dumps will \fIsignificantly\fP 2311 slow down crossroads\&. 2312 .PP 2313 Besides \f(CWtrafficlog\fP, there is also a directive 2314 \f(CWthroughputlog\fP\&. This directive also takes one argument, a 2315 filename\&. The file is appended, and the following information is 2316 logged: 2317 .PP 2318 .IP o 2319 The process ID of the crossroads image that serves the 2320 TCP connection; 2321 .IP o 2322 The time of the request, in seconds and microseconds 2323 since start of the run; 2324 .IP o 2325 A \fBC\fP when the request originated at the client, or 2326 \fBB\fP when the request originated at the back end; 2327 .IP o 2328 The first 100 bytes of the request\&. 2329 .PP 2330 As an example, consider the following (the lines are shortened for 2331 brevity and prefixed by line numbers for clarity): 2332 .PP 2333 .nf 2334 2335 1 0000594 0\&.000001 C GET http://public\&.e-tunity\&.com/index\&.html\&.\&.\&. 2336 2 0000594 0\&.173713 B HTTP/1\&.0 200 OK\&.\&.Date: Fri, 18 Nov 2005 0\&.\&.\&. 2337 3 0000594 0\&.278125 B width="100" bgcolor="#e0e0e0" valign="to\&.\&.\&. 2338 4 0000595 0\&.000001 C GET http://public\&.e-tunity\&.com/css/style/\&.\&.\&. 2339 5 0000594 0\&.944339 B /a></td>\&.\&. </tr>\&.</table>\&.</td><td class\&.\&.\&. 2340 6 0000594 0\&.946356 B smallboxdownl">Download</td>\&.\&. <td class\&.\&.\&. 2341 7 0000594 0\&.961102 B td><td class="smallboxodd" valign="top"><\&.\&.\&. 2342 8 0000595 0\&.698215 B HTTP/1\&.0 304 Not Modified\&.\&.Date: Fri, 18 \&.\&.\&. 2343 .fi 2344 2345 .PP 2346 This tells us that: 2347 .PP 2348 .IP o 2349 Line 1: PID 594 served a request that originated at 2350 the client\&. The corresponding time is (almost) 0 seconds, 2351 so this is really the start of the run\&. 2352 .IP o 2353 Line 2: A back end replied 0\&.17 seconds later, and 2354 0\&.28 seconds later, it was still replying (this is the 2355 third line, again a \fBB\fP-type transmission)\&. 2356 .IP o 2357 Line 4: PID 595 served a request that originated 2358 at the client\&. Again, the corresponding time is (almost) 2359 0 seconds, since this is the first conversation part of 2360 this connection\&. 2361 .IP o 2362 Lines 5 to 7: This is the continuation of line 2\&. Line 7 2363 is the last line of the \fBB\fP series (not visible from 2364 the example, but trust me, it is), so that we may 2365 conclude that it took the back end 0\&.96 seconds to serve 2366 the file \f(CWindex\&.html\fP requested in line 1\&. 2367 .IP o 2368 Line 8: This is the answer to the client\&'s request of 2369 line 4 (you can tell by the process ID number)\&. 2370 So the back end took 0\&.68 seconds to confirm that 2371 the stylesheet requested in line 4 wasn\&'t modified\&. 2372 .PP 2373 It is also worth while remembering that the start time of a \fBC\fP 2374 request is the time that crossroads sees the activity\&. Any latency 2375 between the true client and crossroads is obviously not 2376 included\&. This is illustrated by the below simple ASCII art: 2377 .PP 2378 .nf 2379 2380 client ---->---->---->--->*crossroads ====>====>====> 2381 \e 2382 back end 2383 / 2384 client ----<----<----<---< crossroads ====<====<====< 2385 2386 .fi 2387 2388 .PP 2389 This simple picture shows a typical HTTP request that originates 2390 at a client, travels to crossroads, and is relayed via the back 2391 end\&. The \fBC\fP entry in a throughput log is the time when 2392 crossroads sees the request, indicated by an asterisk\&. The \fBB\fP 2393 entries are the times that it takes the back end to answer, 2394 indicated by \f(CW===\fP style lines\&. Therefore, the true roundtrip 2395 time will be longer than the number of seconds that are logged in 2396 the throughput log: the latency between client and crossroads 2397 isn\&'t included in that measurement\&. 2398 .PP 2399 Summarizing, the throughput times of a client-back end connection 2400 can be analyzed using the directive \f(CWthroughputlog\fP\&. In a 2401 real-world analysis, you\&'d probably want to write up a script to 2402 analyze the output and to compute round trip times\&. Such scripts 2403 are not (yet) included in Crossroads\&. 2404 .PP 2405 2406 .SH "5\&.6: Limiting Access to Crossroads by Client IP Address" 2407 2408 .PP 2409 2410 .SH "5\&.6\&.1: General Examples" 2411 2412 .PP 2413 The directives \f(CWallowfrom\fP, \f(CWdenyfrom\fP, \f(CWallowfile\fP and 2414 \f(CWdenyfile\fP can be used to instruct Crossroads to specifically allow 2415 access by using a "whitelist" of IP addresses, or to specifically deny 2416 access by using a "blacklist"\&. E\&.g\&., the following configuration 2417 allows access to service \f(CWwebproxy\fP only to \fIlocalhost\fP: 2418 .PP 2419 .nf 2420 service webproxy { 2421 port 8000; 2422 allowfrom 127\&.0\&.0\&.1; 2423 backend one { 2424 \&. 2425 \&. Back end definitions occur here 2426 \&. 2427 } 2428 \&. 2429 \&. Other back ends or other service directives 2430 \&. may occur here 2431 \&. 2432 } 2433 .fi 2434 2435 .PP 2436 In this example there is a "whitelist" having only one entry: IP 2437 address 127\&.0\&.0\&.1, or \fIlocalhost\fP\&. (Incidentally, the same behaviour 2438 could be accomplished by stating \fIbindto 127\&.0\&.0\&.1\fP, in which case 2439 Crossroads would only listen to the local network device\&.) 2440 .PP 2441 In the same vein, the directive \f(CWallowfrom 127\&.0\&.0\&.1 192\&.168\&.1/24\fP 2442 would allow access to \fIlocalhost\fP and to all IP addresses that start 2443 with 192\&.168\&.1\&. The specifier \f(CW192\&.168\&.1/24\fP states that there are 2444 three network bytes (192, 168 and 1), and 24 bits (or 3 bytes) are 2445 relevant; so that the fourth network byte doesn\&'t matter\&. 2446 .PP 2447 2448 .SH "5\&.6\&.2: Using External Files" 2449 2450 .PP 2451 The directives \f(CWallowfile\fP and \f(CWdenyfile\fP allow you to specify IP 2452 addresses in external files\&. The Crossroads configuration states 2453 e\&.g\&. \f(CWallowfile /tmp/allow\&.txt\fP, and the IP addresses are then in 2454 \f(CW/tmp/allow\&.txt\fP\&. The format of \f(CW/tmp/allow\&.txt\fP is as follows: 2455 .PP 2456 .IP o 2457 The specifications follow again \fIp\&.q\&.r\&.s/mask\fP, where 2458 p, q, r and s are network bytes which can be left out on the 2459 right hand side when the mask allows it; 2460 .IP 2461 .IP o 2462 The specifications must be separated by white space 2463 (spaces, tabs or newlines)\&. 2464 .PP 2465 E\&.g\&., the following is a valid example of an external specification 2466 file: 2467 .PP 2468 .nf 2469 127\&.0\&.0\&.1 2470 192\&.168\&.1/24 2471 10/8 2472 .fi 2473 2474 .PP 2475 When external files are in effect, then the signal \f(CWSIGHUP\fP (1) 2476 causes Crossroads to reload the external file\&. E\&.g\&., while Crossroads 2477 is running, you may edit \f(CW/tmp/allow\&.txt\fP, and then issue \f(CWkillall 2478 -1 crossroads\fP\&. The new contents of \f(CW/tmp/allow\&.txt\fP will be 2479 reloaded\&. 2480 .PP 2481 2482 .SH "5\&.6\&.3: Mixing Directives" 2483 2484 .PP 2485 Crossroads allows to mix all directives in one service 2486 description\&. However, some mixes are less meaningful than others\&. It\&'s 2487 up to you to take this into account\&. 2488 .PP 2489 The following rules apply: 2490 .PP 2491 .IP o 2492 Blacklisting and whitelisting can be used together\&. When 2493 combined, the blacklist will always be interpreted 2494 first\&. E\&.g\&., consider the following directives: 2495 .IP 2496 .nf 2497 allowfrom 192\&.168\&.1/24 2498 denyfrom 192\&.168\&.1\&.100 2499 .fi 2500 2501 .IP 2502 Given the fact that the deny list is checked first, client 2503 192\&.168\&.1\&.100 won\&'t be able to access Crossroads\&. Then the 2504 allow list will be checked, stating that all clients whose IP 2505 address starts with 192\&.168\&.1 may connect\&. The effect will be 2506 that e\&.g\&., client 192\&.168\&.1\&.1 may connect, 192\&.168\&.1\&.2 may 2507 connect too, 192\&.168\&.1\&.100 will be blocked, and 10\&.1\&.1\&.1 will 2508 be blocked as well\&. 2509 .IP 2510 Now consider the following directives: 2511 .IP 2512 .nf 2513 allowfrom 192\&.168\&.1\&.100 127\&.0\&.0\&.1 2514 denyfrom 192\&.168\&.1/24 2515 .fi 2516 2517 .IP 2518 This will first of all deny access to all IP addresses that 2519 start with 192\&.168\&.1\&. So the rule that allows 192\&.168\&.1\&.100 2520 won\&'t ever be effective\&. The net result will be that access 2521 will be granted to 127\&.0\&.0\&.1, and IP addresses that don\&'t 2522 match 192\&.168\&.1/24\&. 2523 .IP 2524 .IP o 2525 Blacklisting or whitelisting can be left out\&. 2526 A list is considered empty when no appropriate directives 2527 occur in \f(CW/etc/crossroads\&.conf\fP, or when the directive 2528 points to an empty or non-existent external file\&. 2529 .IP 2530 .IP o 2531 Using \f(CW*from\fP and \f(CW*file\fP statements is allowed, but 2532 doesn\&'t make sense\&. E\&.g\&., the following configuration sample 2533 is such a case: 2534 .IP 2535 .nf 2536 allowfrom 127\&.0\&.0\&.1 192\&.168\&.1/24 2537 allowfile /tmp/allow\&.txt 2538 .fi 2539 2540 .IP 2541 There is a technical reason for this\&. Once Crossroads 2542 processes the \f(CWallowfile\fP directive, then the whole 2543 whitelist is cleared (thereby removing the entries 127\&.0\&.0\&.1 2544 and 192\&.168\&.1/24), and new entries are reloaded from the 2545 file\&. The net result is that the \f(CWallowfrom\fP specification 2546 is overruled\&. 2547 .IP 2548 Crossroads doesn\&'t check for such configurations, which are 2549 syntactially correct, but make no semantic sense\&. 2550 .PP 2551 2552 .SH "5\&.7: Configuration examples" 2553 2554 .PP 2555 As a general hint, use \f(CWcrossroads sampleconf\fP to view the most 2556 up-to-date examples of configurations\&. The description below shows a 2557 few examples too\&. 2558 .PP 2559 2560 .SH "5\&.7\&.1: A load balancer for three webserver back ends" 2561 2562 .PP 2563 The following configuration example binds crossroads to port 80 of the 2564 current server, and distributes the load over three back ends\&. This 2565 configuration shows most of the possible settings\&. 2566 .PP 2567 .nf 2568 service www { 2569 /* We don\&'t need session stickyness\&. */ 2570 type any; 2571 2572 /* Port on which we\&'ll listen in this service: required\&. */ 2573 port 8000; 2574 2575 /* What IP address should this service listen? Default is \&'any\&'\&. 2576 * Alternatively you can state an explicit IP address, such as 2577 * 127\&.0\&.0\&.1; that would bind the service only to \&'localhost\&'\&. */ 2578 bindto any; 2579 2580 /* Verbose reporting or not\&. Default is off\&. */ 2581 verbosity on; 2582 2583 /* Dispatching mode, or: How to select a back end for an incoming 2584 * request\&. Possible values: 2585 * roundrobin: just the next back end in line 2586 * random: like roundrobin, but at random to make things more 2587 * confusing\&. Probably only good for testing\&. 2588 * bysize: The backend that transferred the least nr of bytes 2589 * is the next in line\&. As a modifier you can say e\&.g\&. 2590 * bysize over 10, meaning that the 10 last connections will 2591 * be used to compute the transfer size, instead of all 2592 * transfers\&. 2593 * byduration: The backend that was active for the shortest time 2594 * is the next in line\&. As a modifier you can say e\&.g\&. 2595 * byduration of 10 to compute over the last 10 connections\&. 2596 * byconnections: The back end with the least active connections 2597 * is the next ine line\&. 2598 * byorder: The first available back end is always taken\&. 2599 */ 2600 dispatchmode byduration over 5; 2601 2602 /* Interval at which we\&'ll check whether a temporarily unavailable 2603 * backend has woken up\&. 2604 */ 2605 revivinginterval 5; 2606 2607 /* TCP backlog of connections\&. Default is 0 (no backlog, one 2608 * connection may be active)\&. 2609 */ 2610 backlog 5; 2611 2612 /* For status reporting: a shared memory key\&. Default is the same 2613 * as the port number, OR-ed by a magic number\&. 2614 */ 2615 shmkey 8000; 2616 2617 /* This controls when crossroads should consider a connection as 2618 * finished even when the TCP sockets weren\&'t closed\&. This is to 2619 * avoid hanging connections that don\&'t do anything\&. NOTE THAT when 2620 * crossroads cuts off a connection due to timeout exceed, this is 2621 * not marked as a failure, but as a success\&. Default is 0: no timeout\&. 2622 */ 2623 connectiontimeout 300; 2624 2625 /* The max number of allowed client connections\&. When present, connections 2626 * won\&'t be accepted if the max is about to be exceeded\&. When 2627 * absent, all connections will be accepted, which might be misused 2628 * for a DOS attack\&. 2629 */ 2630 maxconnections 300; 2631 2632 /* Now let\&'s define a couple of back ends\&. Number 1: */ 2633 backend www_backend_1 { 2634 /* The server and its port, the minimum configuration\&. */ 2635 server httpserver1; 2636 port 9010; 2637 /* The \&'decay\&' of usage data of this back end\&. Only relevant 2638 * when the whole service has \&'dispatchmode bysize\&' or 2639 * \&'byduration\&'\&. The number is a percentage by which the usage 2640 * parameter is decreased upon each connection of an other back 2641 * end\&. 2642 */ 2643 decay 10; 2644 2645 /* To see what\&'s happening in /var/log/messages: */ 2646 verbosity on; 2647 } 2648 2649 /* The second one: */ 2650 backend www_backend_2 { 2651 /* Server and port */ 2652 server httpserver2; 2653 port 9011; 2654 2655 /* Verbosity of reporting when this back end is active */ 2656 verbosity on; 2657 2658 /* Decay */ 2659 decay 10; 2660 2661 /* This back end is twice as weak as the first one */ 2662 weight 2; 2663 2664 /* Event triggers for system commands upon succesful activation 2665 * and upon failure\&. 2666 */ 2667 onsuccess echo \&'success on backend 2\&' | mail root; 2668 onfailure echo \&'failure on backend 2\&' | mail root; 2669 } 2670 2671 /* And yet another one\&.\&. this time we will dump the traffic 2672 * to a trace file\&. Furthermore we don\&'t want more than 10 concurrent 2673 * connections here\&. Note that there\&'s also a total maxconnections for the 2674 * whole service\&. 2675 */ 2676 backend www_backend_3 { 2677 server httpserver3; 2678 verbosity on; 2679 port 9000; 2680 verbosity on; 2681 decay 10; 2682 trafficlog /tmp/backend\&.3\&.log; 2683 maxconnections 10; 2684 } 2685 } 2686 .fi 2687 2688 .PP 2689 2690 .SH "5\&.7\&.2: An HTTP forwarder when travelling" 2691 2692 .PP 2693 As another example, here\&'s my \f(CWcrossroads\&.conf\fP that I use on my 2694 Unix laptop\&. The problem that I face is that I need many HTTP proxy 2695 configurations (at home, at customers\&' sites and so on) but I\&'m too 2696 lazy to reconfigure browsers all the time\&. 2697 .PP 2698 Here\&'s how it used to be before crossroads: 2699 .PP 2700 .IP o 2701 At home, I would surf through a squid proxy on my local 2702 machine\&. The browser proxy setting is then 2703 \f(CWhttp://localhost:3128\fP\&. 2704 .IP 2705 .IP o 2706 Sometimes I start up an SSH tunnel to our offices\&. The 2707 tunnel has a local port 3129, and connects to a squid proxy on 2708 our e-tunity server\&. Hence, the browser proxy is then 2709 \f(CWhttp://localhost:3129\fP\&. 2710 .IP 2711 .IP o 2712 At a customer\&'s location I need the proxy 2713 \f(CWhttp://10\&.120\&.34\&.113:8080\fP, because they have configured it 2714 so\&. 2715 .IP 2716 .IP o 2717 And in yet other instances, I use a HTTP diagnostic tool 2718 Charles 2719 that sits between browser and website and shows me 2720 what\&'s happening\&. I run charles on my own machine and it 2721 listens to port 8888, behaving like a proxy\&. The browser 2722 configuration for the proxy is then 2723 \f(CWhttp://localhost:8888\fP\&. 2724 .PP 2725 Here\&'s how it works with a crossroads configuration: 2726 .PP 2727 .IP o 2728 I have configured my browsers to use 2729 \f(CWhttp://localhost:8080\fP as the proxy\&. For all situations\&. 2730 .IP 2731 .IP o 2732 I use the following crossroads configuration, and let 2733 crossroads figure out which proxy backend works, and which 2734 doesn\&'t\&. Note two particularities: 2735 .IP 2736 .IP o 2737 The statement \f(CWdispatchmode byorder\fP\&. This 2738 makes sure that once crossroads determines which 2739 backend works, it will stick to it\&. This usage of 2740 crossroads doesn\&'t need to balance over more than one 2741 back end\&. 2742 .IP 2743 .IP o 2744 The statement \f(CWbindto 127\&.0\&.0\&.1\fP makes sure 2745 that requests from other interfaces than loopback 2746 won\&'t get serviced\&. 2747 .IP 2748 .nf 2749 service HttpProxy { 2750 port 8080; 2751 bindto 127\&.0\&.0\&.1; 2752 verbosity on; 2753 dispatchmode byorder; 2754 revivinginterval 15; 2755 2756 backend Charles { 2757 server localhost:8888; 2758 verbosity on; 2759 } 2760 2761 backend CustomerProxy { 2762 server 10\&.120\&.34\&.113:8080; 2763 verbosity on; 2764 } 2765 2766 backend SshTunnel { 2767 server localhost:3129; 2768 } 2769 2770 backend LocalSquid { 2771 server localhost:3128; 2772 } 2773 } 2774 .fi 2775 2776 .PP 2777 As a final note, the commandline argument \f(CWtell\fP can be used to 2778 influence crossroad\&'s own detection mechanism of back end availability 2779 detection\&. E\&.g\&., if in the above example the back ends \f(CWSshTunnel\fP 2780 and \f(CWLocalSquid\fP are both active, then \f(CWcrossroads tell httpproxy 2781 sshtunnel down\fP will \&'take down\&' the back end \f(CWSshTunnel\fP -- and 2782 will automatically cause crossroads to switch to \f(CWLocalSquid\fP\&. 2783 .PP 2784 2785 .SH "5\&.7\&.3: SSH login with enforced idle logout" 2786 2787 .PP 2788 The following example shows how crossroads \&'throttles\&' SSH 2789 logins\&. Connections are accepted on port 2790 22 (the normal SSH port) and forwarded to the actual SSH daemon 2791 which is running on port 2222\&. 2792 .PP 2793 Note the usage of the 2794 \f(CWconnectiontimeout\fP directive\&. This makes sure that users are logged 2795 out after 10 minutes of inactivity\&. Note also the \f(CWmaxconnections\fP 2796 setting, this makes sure that no more than 10 concurrent logins occur\&. 2797 .PP 2798 .nf 2799 service Ssh { 2800 port 22; 2801 backlog 5; 2802 maxconnections 10; 2803 connectiontimeout 600; 2804 backend TrueSshDaemon { 2805 server localhost:2222; 2806 } 2807 } 2808 .fi 2809 2810 .PP 2811 2812 .SH "6: Benchmarking" 2813 This section shows how crossroads affects the 2814 transmitting of HTML data when used as an intermediate \&'station\&' 2815 through which all data travels\&. 2816 .PP 2817 2818 .SH "6\&.1: Benchmark 1: Accessing a proxy via crossroads or directly" 2819 2820 .PP 2821 The benchmark was run on a system where the following was varied: 2822 .PP 2823 .IP 1\&. 2824 A website was recursively spidered through a local squid 2825 proxy\&. The spidering was repeated 10 times, the total was recorded\&. 2826 .IP 2827 .IP 2\&. 2828 Crossroads was placed in front of the squid proxy, and 2829 the website was again recursively spidered\&. Again, the 2830 spidering was repeated 10 times and the total was recorded\&. 2831 .PP 2832 The crossroads configuration of the second alternative is shown below: 2833 .PP 2834 .nf 2835 service HttpProxy { 2836 port 8080; 2837 verbosity on; 2838 backend LocalSquid { 2839 server 127\&.0\&.0\&.1; 2840 port 3128; 2841 verbosity on; 2842 } 2843 } 2844 .fi 2845 2846 .PP 2847 2848 .SH "6\&.1\&.1: Results" 2849 2850 .PP 2851 The results of this test are that crossroads causes a negligible 2852 delay, if it is statistically relevant at all\&. Without crossroads, the 2853 timing results are: 2854 .PP 2855 .nf 2856 real 0m8\&.146s 2857 user 0m0\&.130s 2858 sys 0m0\&.253s 2859 .fi 2860 2861 .PP 2862 When using crossroads as a middle station, the results are: 2863 .PP 2864 .nf 2865 real 0m9\&.481s 2866 user 0m0\&.141s 2867 sys 0m0\&.230s 2868 .fi 2869 2870 .PP 2871 2872 .SH "6\&.1\&.2: Discussion" 2873 2874 .PP 2875 The above shown results are quite favorable to crossroads\&. However, 2876 one should know that situations will exist where crossroads leans 2877 towards the \&'worst case\&' scenario, causing up to 50% 2878 delay\&. 2879 .PP 2880 E\&.g\&., imagine a test where a \f(CWwget\fP command retrieves a 2881 HTML document from an Apache server on \f(CWlocalhost\fP\&. Now we have 2882 (almost) no overhead due to network throttling, hostname lookups and 2883 so on\&. When this test would be run either with or without crossroads 2884 in between, then theoretically, crossroads would cause a much larger 2885 delay, because it has to read from the server, and then write the same 2886 information to \f(CWwget\fP\&. Each read/write occurs twice when crossroads 2887 sits in between\&. 2888 .PP 2889 This worst case scenario will however (fortunately) occur only very 2890 seldom in the real world: 2891 .PP 2892 .IP o 2893 Normally network issues, such as the above mentioned host 2894 name lookups or throughput restrictions, will add 2895 significantly to the duration of a request\&. The \&'twice as 2896 many\&' read/writes caused by crossroads are then relatively 2897 irrelevant\&. 2898 .IP 2899 .IP o 2900 Normally a significant amount of time will be spent in a 2901 back end, due to processing (e\&.g\&., when calling a servlet on a 2902 back end)\&. Again, this processing time will weigh much heavier 2903 than the multiple read/writes\&. 2904 .PP 2905 2906 .SH "6\&.2: Benchmark 2: Crossroads versus Linux Virtual Server (LVS)" 2907 2908 .PP 2909 LVS is a kernel-based balancer that acts like a masquerading 2910 firewall: TCP packets that arrive at the balancer are sent to one of 2911 the configured back ends\&. LVS has the advantage over crossroads that 2912 there is no stop-and-go in the transmission; in contrast, crossroads 2913 needs to send data via an internal buffer\&. Crossroads has the 2914 advantage that it offers instantaneous failover because it tries to 2915 contact the back end for upon each new TCP connection; in contrast, 2916 LVS isn\&'t aware of downtime of back ends (unless one implements an 2917 external heartbeat)\&. Also, crossroads offers more complex balancing 2918 than LVS\&. 2919 .PP 2920 2921 .SH "6\&.2\&.1: Environment" 2922 2923 .PP 2924 On the balancer, LVS was run on port 80, its forwarding set up for two 2925 equally weighted back ends, using \f(CWipvsadm\fP: 2926 .PP 2927 .nf 2928 ipvsadm -a -t 192\&.168\&.1\&.250:http -r 10\&.1\&.1\&.100:http -m -w 1 2929 ipvsadm -a -t 192\&.168\&.1\&.250:http -r 10\&.1\&.1\&.101:http -m -w 1 2930 .fi 2931 2932 .PP 2933 Crossroads was run on port 81\&. The configuration file is shown below: 2934 .PP 2935 .nf 2936 service http { 2937 port 81; 2938 dispatchmode roundrobin; 2939 revivinginterval 5; 2940 backend one { 2941 server 10\&.1\&.1\&.100; 2942 port 80; 2943 } 2944 backend two { 2945 server 10\&.1\&.1\&.101; 2946 port 80; 2947 } 2948 } 2949 .fi 2950 2951 .PP 2952 2953 .SH "6\&.2\&.2: Tests and results" 2954 2955 .PP 2956 In the first test, ports 80 and 81 on the balancer were \&'bombed\&' with 2957 50 concurrent clients, each requesting a small page 50 times\&. The 2958 following timings where measured: 2959 .PP 2960 .IP o 2961 How long it takes to establish a connection; 2962 .IP o 2963 How long it takes to retrieve the page\&. 2964 .PP 2965 The results of this test were: 2966 .PP 2967 .IP o 2968 On average, each client took 0\&.12 seconds to connect 2969 to LVS, and each page was retrieved in 0\&.14 seconds; 2970 .IP o 2971 On average, each client took 0\&.11 seconds to connect to 2972 crossroads, and each page was retrieved in 0\&.13 seconds\&. 2973 .PP 2974 In this setup there seems to be no difference between the performance 2975 of LVS and crossroads! 2976 .PP 2977 In a second test, the size of the retrieved page was varied from 2\&.000 2978 to 2\&.000\&.000 bytes\&. This test was taken to see whether crossroads would 2979 show performance degradation when transferring larger amounts of data\&. 2980 .PP 2981 For each page size, 30 concurrent clients were started, that retrieved 2982 the page 50 times\&. Again, the connect times and processing times where 2983 recorded\&. 2984 .PP 2985 The results of the total time (connect time + retrieval time) 2986 are shown in the below table: 2987 .PP 2988 .TS 2989 tab(~); 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 --- 3003 rrr 3004 rrr 3005 rrr 3006 rrr 3007 rrr 3008 --- 3009 c. 3010 \fBBytes\fP~\fBLVS timing\fP~\fBCrossroads timing\fP 3011 2000~0\&.130741688~0\&.12739582 3012 20000~0\&.490916224~0\&.50376901 3013 200000~3\&.799440328~4\&.33125273 3014 2000000~45\&.25090855~45\&.9600728 3015 .TE 3016 3017 .PP 3018 Again, the results show that crossroads performs just as effectively 3019 as LVS, even with large data chunks! 3020 .PP 3021 3022 .SH "7: Compiling and Installing" 3023 3024 3025 .SH "7\&.1: Prerequisites" 3026 3027 .PP 3028 The creation of crossroads requires: 3029 .PP 3030 .IP o 3031 Standard Unix tools, such as \f(CWsed\fP, \f(CWawk\fP, \f(CWPerl\fP 3032 (5\&.00 or better); 3033 .IP 3034 .IP o 3035 A POSIX-compliant C compiler; 3036 .IP 3037 .IP o 3038 Support for SYSV IPC, networking and so on\&. 3039 3040 .PP 3041 Basically a Linux or Apple MacOSX box will do nicely\&. To compile and install 3042 crossroads, follow these steps\&. 3043 .PP 3044 3045 .SH "7\&.2: Compiling and installing" 3046 3047 .PP 3048 .IP o 3049 Obtain the source distribution\&. It can be found on 3050 http://crossroads\&.e-tunity\&.com\&. The distribution comes as an 3051 archive \f(CWcrossroads-\fP\fItype\fP\f(CW\&.tar\&.gz\fP, where \fItype\fP is 3052 \f(CWstable\fP or \f(CWdevel\fP\&. 3053 .IP 3054 .IP o 3055 Unpack the archive in a sources directory using \f(CWtar 3056 xzf crossroads-\fP\fIX\&.YY\fP\f(CW\&.tar\&.gz\fP\&. The contents spill into a 3057 subdirectory \f(CWcrossroads-\fP\fIX\&.YY/\fP\&. 3058 .IP 3059 .IP o 3060 Change-dir into the directory\&. 3061 .IP 3062 .IP o 3063 Next, edit \f(CWetc/Makefile\&.def\fP and verify that all 3064 compilation settings are to your likings\&. The settings are 3065 explained in the file\&. \fBNote that\fP the default distribution 3066 of \f(CWMakefile\&.def\fP is suited for Linux or Apple MacOSX 3067 systems\&. On other Unices, or on non-Unix systems, you must 3068 particularly pay attention to \f(CWSET_PROC_TITLE_BY\&.\&.\&.\fP\&. When 3069 in doubt, comment out all \f(CWSET_PROC_TITLE\&.\&.\&.\fP 3070 settings\&. Crossroads will work nevertheless, but it won\&'t show 3071 nice titles in \f(CWps\fP listings\&. Also there\&'s a macro 3072 \f(CWEXTRA_LIBS\fP to add linkage flags (an example for a Solaris 3073 build is included)\&. 3074 .IP 3075 .IP o 3076 Now crossroads is ready for compilation\&. Do a \f(CWmake 3077 local\fP followed by \f(CWmake install\fP\&. The latter step may have 3078 to be done by the user \f(CWroot\fP if the \f(CWBINDIR\fP setting of 3079 \f(CWetc/Makefile\&.def\fP points to a root-owned directory\&. 3080 .IP 3081 .IP o 3082 The documentation doesn\&'t install in this process\&. If you 3083 want to install the documentation, then proceed as follows: 3084 .IP 3085 .IP o 3086 Optionally, \f(CWcp doc/crossroads\&.html\fP 3087 \fIhtmldirectory/\fP; where \fIhtmldirectory\fP is the destination 3088 directory for your HTML manuals; 3089 .IP 3090 .IP o 3091 Optionally, \f(CWcp doc/crossroads\&.pdf\fP 3092 \fIpdfdirectory/\fP; where \fIpdfdirectory\fP is the 3093 destination directory for your PDF manuals; 3094 .IP 3095 .IP o 3096 Optionally, \f(CWcp doc/crossroads\&.man\fP 3097 \fImanualdirectory\fP\f(CW/crossroads\&.1\fP, where 3098 \fImanualdirectory\fP is e\&.g\&. \f(CW/usr/man/man1\fP, 3099 \f(CW/usr/share/man1\fP, \f(CW/usr/local/man/man1\fP, 3100 \f(CW/usr/local/share/man1\fP\&. Any possibility is valid, as 3101 long as \fImanualdirectory\fP is one of the directories 3102 where manual pages are stored; 3103 .IP 3104 .IP o 3105 If your manual page system supports compressed 3106 manual pages, then you can save some space with 3107 \f(CWgzip\fP \fImanualdirectory\fP\f(CW/crossroads\&.1\fP\&. 3108 .IP 3109 3110 .SH "7\&.3: Configuring crossroads" 3111 3112 .PP 3113 Now that the binary is available on your system, you need to create a 3114 suitable \f(CW/etc/crossroads\&.conf\fP\&. Use this manual or the output of 3115 \f(CWcrossroads samplconf\fP to get started\&. 3116 .PP 3117 Once you have the configuration ready, start crossroads with 3118 \f(CWcrossroads start\fP\&. Test the availability of your services and back 3119 ends\&. Monitor how crossroads is doing with: 3120 .PP 3121 .IP o 3122 In one terminal, run the script: 3123 .nf 3124 while [ 1 ] ; do 3125 tput clear 3126 crossroads status 3127 sleep 3 3128 done 3129 .fi 3130 3131 .IP 3132 \fBNote\fP that depending on your system you might need 3133 \f(CWsleep 3s\fP, i\&.e\&., with an \f(CWs\fP appended\&. 3134 .IP 3135 .IP o 3136 In another terminal, run: 3137 .nf 3138 while [ 1 ] ; do 3139 tput clear 3140 ps ax | grep crossroads | grep -v grep 3141 sleep 3 3142 done 3143 .fi 3144 3145 .IP 3146 \fBNote\fP that depending on your system you might need 3147 \f(CWps -ef\fP instead of \f(CWps ax\fP\&. 3148 .IP 3149 .IP o 3150 In yet another terminal, run \f(CWtail -f 3151 /var/log/messages\fP (supply the appropriate system log file if 3152 \f(CW/var/log/messages\fP doesn\&'t work for you)\&. 3153 .PP 3154 Now thoroughly test the availability of your back ends through 3155 crossroads\&. The status display will show an updated view of which back 3156 ends are selected and how busy they are\&. The process list will show 3157 which crossroads daemons are running\&. Finally, the tailing of 3158 \f(CW/var/log/messages\fP shows what\&'s going on -- especially if you have 3159 \f(CWverbosity true\fP statements in the configuration\&. 3160 .PP 3161 3162 .SH "7\&.4: A boot script" 3163 3164 .PP 3165 Finally, you may want to create a boot-time startup script\&. The exact 3166 procedure depends on the used Unix flavor\&. 3167 .PP 3168 3169 .SH "7\&.4\&.1: SysV Style Startup" 3170 3171 .PP 3172 On SysV style systems, there\&'s a startup script directory 3173 \f(CW/etc/init\&.d\fP where bootscripts for all utilities are located\&. 3174 You may have the \f(CWchkconfig\fP utility to automate the task of 3175 inserting scripts into the boot sequence, but 3176 otherwise the steps will resemble the following\&. 3177 .PP 3178 .IP o 3179 Create a script \f(CWcrossroads\fP in \f(CW/etc/init\&.d\fP similar to the 3180 following: 3181 .IP 3182 .nf 3183 #!/bin/sh 3184 /usr/local/bin/crossroads -v $@ 3185 .fi 3186 3187 .IP 3188 The stated directory \f(CW/usr/local/bin\fP must correspond with 3189 the installation path\&. The flag \f(CW-v\fP causes the startup to 3190 be more \&'verbose\&'\&. However, once daemonized, the verbosity is 3191 controlled by the appropriate statements in the configuration\&. 3192 .IP 3193 .IP o 3194 Determine your \&'runlevel\&': usually 3 when your system is 3195 running in text-mode only, or 5 when you are using a graphical 3196 interface\&. If your runlevel is 3, then: 3197 .IP 3198 .nf 3199 root> cd /etc/rc\&.d/rc3\&.d 3200 root> ln -s /etc/init\&.d/crossroads S99crossroads 3201 root> ln -s /etc/init\&.d/crossroads K99crossroads 3202 .fi 3203 3204 .IP 3205 This creates startup (\f(CWS*\fP) and stop (\f(CWK*\fP) links that 3206 will be run when the system enters or leaves a given runlevel\&. 3207 .IP 3208 If your runlevel is 5, then the right \f(CWcd\fP command is to 3209 \f(CW/etc/rc\&.d/rc5\&.d\fP\&. Alternatively, you can create the 3210 symlinks in both runlevel directories\&. 3211 .PP 3212 3213 .SH "7\&.4\&.2: BSD Style Startup" 3214 3215 .PP 3216 On BSD style systems, daemons are booted directly from \f(CW/etc/rc\fP and 3217 related scripts\&. Incase you have a file \f(CW/etc/rc\&.local\fP, edit it, 3218 and add the statement: 3219 .PP 3220 .nf 3221 /usr/local/bin/crossroads start 3222 .fi 3223 3224 .PP 3225 If your BSD system lacks \f(CW/etc/rc\&.local\fP, then you may need to start 3226 Crossroads from \f(CW/etc/rc\fP\&. Your mileage may vary\&. 3227 .PP