lemonldap-ng/doc/pages/documentation/current/performances.html
2017-02-07 16:35:26 +00:00

377 lines
22 KiB
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<title>documentation:2.0:performances</title>
<meta name="generator" content="DokuWiki"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="keywords" content="documentation,2.0,performances"/>
<link rel="search" type="application/opensearchdescription+xml" href="lib/exe/opensearch.html" title="LemonLDAP::NG"/>
<link rel="start" href="performances.html"/>
<link rel="contents" href="performances.html" title="Sitemap"/>
<link rel="stylesheet" type="text/css" href="lib/exe/css.php.t.bootstrap3.css"/>
<!-- //if:usedebianlibs
<link rel="stylesheet" type="text/css" href="/javascript/bootstrap/css/bootstrap.min.css" />
//elsif:useexternallibs
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"></script>
//elsif:cssminified
<link rel="stylesheet" type="text/css" href="/static/bwr/bootstrap/dist/css/bootstrap.min.css" />
//else -->
<link rel="stylesheet" type="text/css" href="/static/bwr/bootstrap/dist/css/bootstrap.css" />
<!-- //endif -->
<script type="text/javascript">/*<![CDATA[*/var NS='documentation:2.0';var JSINFO = {"id":"documentation:2.0:performances","namespace":"documentation:2.0"};
/*!]]>*/</script>
<script type="text/javascript" charset="utf-8" src="lib/exe/js.php.t.bootstrap3.js"></script>
<!-- //if:usedebianlibs
<script type="text/javascript" src="/javascript/jquery/jquery.min.js"></script>
//elsif:useexternallibs
<script type="text/javascript" src="http://code.jquery.com/jquery-2.2.0.min.js"></script>
//elsif:jsminified
<script type="text/javascript" src="/static/bwr/jquery/dist/jquery.min.js"></script>
//else -->
<script type="text/javascript" src="/static/bwr/jquery/dist/jquery.js"></script>
<!-- //endif -->
<!-- //if:usedebianlibs
<script type="text/javascript" src="/javascript/jquery-ui/jquery-ui.min.js"></script>
//elsif:useexternallibs
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
//elsif:jsminified
<script type="text/javascript" src="/lib/scripts/jquery-ui.min.js"></script>
//else -->
<script type="text/javascript" src="/lib/scripts/jquery-ui.js"></script>
<!-- //endif -->
</head>
<body>
<div class="dokuwiki export container">
<!-- TOC START -->
<div id="dw__toc">
<h3 class="toggle">Table of Contents</h3>
<div>
<ul class="toc">
<li class="level1"><div class="li"><a href="#global_performance">Global performance</a></div></li>
<li class="level1"><div class="li"><a href="#handler_performance">Handler performance</a></div>
<ul class="toc">
<li class="level2"><div class="li"><a href="#macros_and_groups">Macros and groups</a></div></li>
<li class="level2"><div class="li"><a href="#local_macros">Local macros</a></div></li>
</ul>
</li>
<li class="level1"><div class="li"><a href="#portal_performances">Portal performances</a></div>
<ul class="toc">
<li class="level2"><div class="li"><a href="#general_performances">General performances</a></div></li>
<li class="level2"><div class="li"><a href="#configuration_access">Configuration access</a></div></li>
<li class="level2"><div class="li"><a href="#starting_performances">Starting performances</a></div></li>
<li class="level2"><div class="li"><a href="#apachesession_performances">Apache::Session performances</a></div>
<ul class="toc">
<li class="level3"><div class="li"><a href="#replace_mysql_by_apachesessionflex">Replace MySQL by Apache::Session::Flex</a></div></li>
<li class="level3"><div class="li"><a href="#use_apachesessionbrowseable">Use Apache::Session::Browseable</a></div></li>
</ul>
</li>
<li class="level2"><div class="li"><a href="#ldap_performances">LDAP performances</a></div></li>
</ul>
</li>
<li class="level1"><div class="li"><a href="#manager_performances">Manager performances</a></div>
<ul class="toc">
<li class="level2"><div class="li"><a href="#disable_unused_modules">Disable unused modules</a></div></li>
<li class="level2"><div class="li"><a href="#use_static_html_files">Use static HTML files</a></div></li>
</ul></li>
</ul>
</div>
</div>
<!-- TOC END -->
<h1 class="sectionedit1" id="performances">Performances</h1>
<div class="level1">
<p>
LemonLDAP::NG is designed to be very performant. In particular, it use Apache2 threads capabilities so to optimize performances, prefer using <a href="http://httpd.apache.org/docs/2.2/misc/perf-tuning.html#compiletime" class="urlextern" title="http://httpd.apache.org/docs/2.2/misc/perf-tuning.html#compiletime" rel="nofollow">mpm-worker</a>.
</p>
</div>
<!-- EDIT1 SECTION "Performances" [1-254] -->
<h2 class="sectionedit2" id="global_performance">Global performance</h2>
<div class="level2">
<p>
On Linux, by default, there is no <abbr title="Domain Name System">DNS</abbr> cache and LemonLDAP::NG portal request <abbr title="Domain Name System">DNS</abbr> at every connexions on LDAP or DB. Under heavy loads, that can generated hundred of <abbr title="Domain Name System">DNS</abbr> queries and many errors on LDAP connexions (timed out) from IO::Socket.
</p>
<p>
To bypass this, you can:
</p>
<ul>
<li class="level1"><div class="li"> Use <abbr title="Internet Protocol">IP</abbr> in configuration to avoid <abbr title="Domain Name System">DNS</abbr> resolution</div>
</li>
<li class="level1"><div class="li"> Install a <abbr title="Domain Name System">DNS</abbr> cache like nscd, netmask or bind</div>
</li>
</ul>
</div>
<!-- EDIT2 SECTION "Global performance" [255-658] -->
<h2 class="sectionedit3" id="handler_performance">Handler performance</h2>
<div class="level2">
<p>
Handlers check rights and calculate headers for each HTTP hit. So to improve performances, avoid too complex rules by using the macro or the groups or local macros.
</p>
</div>
<!-- EDIT3 SECTION "Handler performance" [659-856] -->
<h3 class="sectionedit4" id="macros_and_groups">Macros and groups</h3>
<div class="level3">
<p>
Macros and groups are calculated during authentication process by the portal:
</p>
<ul>
<li class="level1"><div class="li"> macros are used to extend (or rewrite) <a href="exportedvars.html" class="wikilink1" title="documentation:2.0:exportedvars">exported variables</a>. A macro is stored as attributes: it can contain boolean results or any string</div>
</li>
<li class="level1"><div class="li"> groups are stored as space-separated strings in the special attribute “groups”: it contains the names of groups whose rules were returned true for the current user</div>
</li>
<li class="level1"><div class="li"> You can also get groups in <code>$hGroups</code> which is a Hash Reference of this form:</div>
</li>
</ul>
<pre class="code perl"><span class="re0">$hGroups</span> <span class="sy0">=</span> <span class="br0">&#123;</span>
<span class="st_h">'group3'</span> <span class="sy0">=&gt;</span> <span class="br0">&#123;</span>
<span class="st_h">'description'</span> <span class="sy0">=&gt;</span> <span class="br0">&#91;</span>
<span class="st_h">'Service 3'</span><span class="sy0">,</span>
<span class="st_h">'Service 3 TEST'</span>
<span class="br0">&#93;</span><span class="sy0">,</span>
<span class="st_h">'cn'</span> <span class="sy0">=&gt;</span> <span class="br0">&#91;</span>
<span class="st_h">'group3'</span>
<span class="br0">&#93;</span><span class="sy0">,</span>
<span class="st_h">'name'</span> <span class="sy0">=&gt;</span> <span class="st_h">'group3'</span>
<span class="br0">&#125;</span><span class="sy0">,</span>
<span class="st_h">'admin'</span> <span class="sy0">=&gt;</span> <span class="br0">&#123;</span>
<span class="st_h">'name'</span> <span class="sy0">=&gt;</span> <span class="st_h">'admin'</span>
<span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>
<p>
Example for macros:
</p>
<pre class="code perl"><span class="co1"># boolean macro</span>
isAdmin <span class="sy0">-&gt;</span> <span class="re0">$uid</span> <span class="kw1">eq</span> <span class="st_h">'foo'</span> <span class="kw1">or</span> <span class="re0">$uid</span> <span class="kw1">eq</span> <span class="st_h">'bar'</span>
<span class="co1"># other macro </span>
displayName <span class="sy0">-&gt;</span> <span class="re0">$givenName</span><span class="sy0">.</span><span class="st0">&quot; &quot;</span><span class="sy0">.</span><span class="re0">$surName</span>
&nbsp;
<span class="co1"># Use a boolean macro in a rule</span>
<span class="sy0">^/</span>admin <span class="sy0">-&gt;</span> <span class="re0">$isAdmin</span>
<span class="co1"># Use a string macro in a HTTP header</span>
Display<span class="sy0">-</span>Name <span class="sy0">-&gt;</span> <span class="re0">$displayName</span></pre>
<p>
Example for groups:
</p>
<pre class="code perl"><span class="co1"># group</span>
admin <span class="sy0">-&gt;</span> <span class="re0">$uid</span> <span class="kw1">eq</span> <span class="st_h">'foo'</span> <span class="kw1">or</span> <span class="re0">$uid</span> <span class="kw1">eq</span> <span class="st_h">'bar'</span>
&nbsp;
<span class="co1"># Use a group in a rule</span>
<span class="sy0">^/</span>admin <span class="sy0">-&gt;</span> <span class="re0">$groups</span> <span class="sy0">=~</span> <span class="co2">/\badmin\b/</span>
&nbsp;
<span class="co1"># Or with hGroups</span>
<span class="sy0">^/</span>admin <span class="sy0">-&gt;</span> <a href="http://perldoc.perl.org/functions/defined.html"><span class="kw3">defined</span></a> <span class="re0">$hGroups</span><span class="sy0">-&gt;</span><span class="br0">&#123;</span><span class="st_h">'admin'</span><span class="br0">&#125;</span></pre>
<div class="noteclassic">Groups are computed after macros, so a group rule may involve a macro value.
</div><div class="noteimportant">Macros and groups are computed in alphanumeric order, that is, in the order they are displayed in the manager. For example, macro “macro1” will be computed before macro “macro2”: so, expression of macro2 may involve value of macro1. As same for groups: a group rule may involve another, previously computed group.
</div>
</div>
<!-- EDIT4 SECTION "Macros and groups" [857-2819] -->
<h3 class="sectionedit5" id="local_macros">Local macros</h3>
<div class="level3">
<p>
Macros and groups are stored in session database. Local macros is a special feature of handler that permit one to have macros useable localy only. Those macros are calculated only at the first usage and stored in the local session cache (only for this server) and only if the user access to the related applications. This avoid to have to many datas stored.
</p>
<pre class="code perl"><span class="co1"># rule</span>
admin <span class="sy0">-&gt;</span> <span class="re0">$admin</span> <span class="sy0">||=</span> <span class="br0">&#40;</span><span class="re0">$uid</span> <span class="kw1">eq</span> <span class="st_h">'foo'</span> <span class="kw1">or</span> <span class="re0">$uid</span> <span class="kw1">eq</span> <span class="st_h">'bar'</span><span class="br0">&#41;</span>
<span class="co1"># header</span>
Display<span class="sy0">-</span>Name <span class="sy0">-&gt;</span> <span class="re0">$displayName</span> <span class="sy0">||=</span> <span class="re0">$givenName</span><span class="sy0">.</span><span class="st0">&quot; &quot;</span><span class="sy0">.</span><span class="re0">$surName</span></pre>
<div class="notetip">Note that this feature is interesting only for the Lemonldap::NG systems protecting a high number of applications
</div>
</div>
<!-- EDIT5 SECTION "Local macros" [2820-3481] -->
<h2 class="sectionedit6" id="portal_performances">Portal performances</h2>
<div class="level2">
</div>
<!-- EDIT6 SECTION "Portal performances" [3482-3514] -->
<h3 class="sectionedit7" id="general_performances">General performances</h3>
<div class="level3">
<p>
The portal is the biggest component of Lemonldap::NG. It is recommended to use ModPerl::Registry instead of using cgi-script as described in Apache configuration file example (portal-apache2.conf):
</p>
<pre class="code apache">&lt;<span class="kw3">Files</span> *.pl&gt;
<span class="kw1">SetHandler</span> perl-<span class="kw1">script</span>
PerlResponseHandler ModPerl::Registry
&lt;/<span class="kw3">Files</span>&gt;</pre>
<p>
You can also use a FastCGI server using index.fcgi given in portal examples.
</p>
<div class="notetip">In production environment for network performance, prefer using minified versions of javascript and css libs: use <code>make install <strong>PROD=yes</strong></code>. This is done by default in RPM/DEB packages.
</div>
</div>
<!-- EDIT7 SECTION "General performances" [3515-4145] -->
<h3 class="sectionedit8" id="configuration_access">Configuration access</h3>
<div class="level3">
<p>
If you set <code>useLocalConf</code> to 1 in lemonldap-ng.ini (section [Portal]), the portal will use only a cached configuration. To refresh it, you have to set an handler on the same server to use the refresh mechanism or to restart the server after each configuration change.
</p>
</div>
<!-- EDIT8 SECTION "Configuration access" [4146-4448] -->
<h3 class="sectionedit9" id="starting_performances">Starting performances</h3>
<div class="level3">
<p>
To make the portal start faster when the server is relaunched, add those lines in Apache configuration file (as described in portal-apache2.conf):
</p>
<pre class="code apache">&lt;Perl&gt;
<span class="kw1">require</span> Lemonldap::NG::Portal::SharedConf;
Lemonldap::NG::Portal::SharedConf-&gt;compile(
qw(delete <span class="kw1">header</span> cache read_from_client cookie <span class="kw1">redirect</span> unescapeHTML));
<span class="co1"># Uncomment this line if you use Lemonldap::NG menu</span>
<span class="kw1">require</span> Lemonldap::NG::Portal::Menu;
<span class="co1"># Uncomment this line if you use portal SOAP capabilities</span>
<span class="kw1">require</span> SOAP::Lite;
&lt;/Perl&gt;</pre>
</div>
<!-- EDIT9 SECTION "Starting performances" [4449-5024] -->
<h3 class="sectionedit10" id="apachesession_performances">Apache::Session performances</h3>
<div class="level3">
<p>
Lemonldap::NG handlers use a local cache to store sessions (for 10 minutes). So Apache::Session module is not a problem for handlers. It can be a brake for the portal:
</p>
<ol>
<li class="level1"><div class="li"> When you use the multiple sessions restriction parameters, sessions are parsed for each authentication unless you use an <a href="https://metacpan.org/module/Apache::Session::Browseable" class="urlextern" title="https://metacpan.org/module/Apache::Session::Browseable" rel="nofollow">Apache::Session::Browseable</a> module.</div>
</li>
<li class="level1"><div class="li"> Since MySQL does not have always transaction feature, Apache::Session::MySQL has been designed to use MySQL locks. Since MySQL performances are very bad using this, if you want to store sessions in a MySQL database, prefer one of the following</div>
</li>
</ol>
</div>
<h4 id="replace_mysql_by_apachesessionflex">Replace MySQL by Apache::Session::Flex</h4>
<div class="level4">
<p>
In “Apache::Session module” field, set “<a href="https://metacpan.org/module/Apache::Session::Flex" class="urlextern" title="https://metacpan.org/module/Apache::Session::Flex" rel="nofollow">Apache::Session::Flex</a>” and use the following parameters:
</p>
<pre class="code">Store -&gt; MySQL
Lock -&gt; Null
Generate -&gt; MD5
Serialize -&gt; Storable
DataSource -&gt; dbi:mysql:sessions;host=...
UserName -&gt; ...
Password -&gt; ...</pre>
<div class="notetip">Since version 1.90 of Apache::Session, you can use Apache::Session::MySQL::NoLock instead
</div>
</div>
<h4 id="use_apachesessionbrowseable">Use Apache::Session::Browseable</h4>
<div class="level4">
<p>
<a href="https://metacpan.org/module/Apache::Session::Browseable" class="urlextern" title="https://metacpan.org/module/Apache::Session::Browseable" rel="nofollow">Apache::Session::Browseable</a> is a wrapper for other Apache::Session modules that add the capability to manage indexes. To use it (with MySQL for example), choose “Apache::Session::Browseable::MySQL” as “Apache::Session module” and use the following parameters:
</p>
<pre class="code">DataSource -&gt; dbi:mysql:sessions;host=...
UserName -&gt; user
Password -&gt; password
Index -&gt; ipAddr uid</pre>
<p>
Note that Apache::Session::Browseable::MySQL doesn&#039;t use MySQL locks.
</p>
<div class="notetip">A <a href="https://metacpan.org/module/Apache::Session::Browseable::Redis" class="urlextern" title="https://metacpan.org/module/Apache::Session::Browseable::Redis" rel="nofollow">Apache::Session::Browseable::Redis</a> has been created, it is the faster (except for session explorer, defeated by Apache::Session::Browseable::<a href="https://metacpan.org/module/Apache::Session::Browseable" class="urlextern" title="https://metacpan.org/module/Apache::Session::Browseable" rel="nofollow">DBI</a>/<a href="https://metacpan.org/module/Apache::Session::Browseable::LDAP" class="urlextern" title="https://metacpan.org/module/Apache::Session::Browseable::LDAP" rel="nofollow">LDAP</a> &gt;= 1.0)
</div><div class="noteimportant">Some Apache::Session module are not fully usable by Lemonldap::NG such as Apache::Session::Memcached since this modules do not offer capability to browse sessions. They does not allow one to use sessions explorer neither manage one-off sessions.
</div>
</div>
<!-- EDIT10 SECTION "Apache::Session performances" [5025-7381] -->
<h3 class="sectionedit11" id="ldap_performances">LDAP performances</h3>
<div class="level3">
<p>
LDAP server can be a brake when you use LDAP groups recovery. You can avoid this by setting “memberOf” fields in your LDAP scheme:
</p>
<pre class="code ldif"><span class="re0">dn</span>:<span class="re1"> uid=foo,dmdName=people,dc=example,dc=com</span>
...
<span class="re0">memberOf</span>:<span class="re1"> cn=admin,dmdName=groups,dc=example,dc=com</span>
<span class="re0">memberOf</span>:<span class="re1"> cn=su,dmdName=groups,dc=example,dc=com</span></pre>
<p>
So instead of using LDAP groups recovery, you just have to store “memberOf” field in your exported variables. With OpenLDAP, you can use the <a href="http://www.openldap.org/doc/admin24/overlays.html#Reverse%20Group%20Membership%20Maintenance" class="urlextern" title="http://www.openldap.org/doc/admin24/overlays.html#Reverse%20Group%20Membership%20Maintenance" rel="nofollow">memberof overlay</a> to do it automatically.
</p>
<div class="noteimportant">Don&#039;t forget to create an index on the field used to find users (uid by default)
</div><div class="notetip">To avoid having group dn stored in sessions datas, you can use a macro to rewrite memberOf:<ul>
<li class="level1"><div class="li"> Exported variables</div>
</li>
</ul>
<pre class="code">ldapgroups -&gt; memberOf</pre>
<p>
For now, ldapgroups contains “cn=admin,dmdName=groups,dc=example,dc=com cn=su,dmdName=groups,dc=example,dc=com”
</p>
<ul>
<li class="level1"><div class="li"> A little macro:</div>
</li>
</ul>
<pre class="code perl">ldapgroups <span class="sy0">-&gt;</span> <a href="http://perldoc.perl.org/functions/join.html"><span class="kw3">join</span></a><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span><span class="sy0">,</span><span class="br0">&#40;</span><span class="re0">$ldapgroups</span> <span class="sy0">=~</span> <span class="co2">/cn=(.*?),/g</span><span class="br0">&#41;</span><span class="br0">&#41;</span></pre>
<p>
Now ldapgroups contains “admin su”
</p>
</div>
</div>
<!-- EDIT11 SECTION "LDAP performances" [7382-8511] -->
<h2 class="sectionedit12" id="manager_performances">Manager performances</h2>
<div class="level2">
</div>
<!-- EDIT12 SECTION "Manager performances" [8512-8545] -->
<h3 class="sectionedit13" id="disable_unused_modules">Disable unused modules</h3>
<div class="level3">
<p>
In lemonldap-ng.ini, set only modules that you will use. By default, configuration, sessions explorer and notifications explorer are enabled. Example:
</p>
<pre class="code ini"><span class="re0"><span class="br0">&#91;</span>manager<span class="br0">&#93;</span></span>
<span class="re1">enabledModules</span> <span class="sy0">=</span><span class="re2"> conf, sessions</span></pre>
</div>
<!-- EDIT13 SECTION "Disable unused modules" [8546-8792] -->
<h3 class="sectionedit14" id="use_static_html_files">Use static HTML files</h3>
<div class="level3">
<p>
Once Manager is installed, browse enabled modules (configuration, sessions, notifications) and save the web pages respectively under <code>manager.html</code>, <code>sessions.html</code> and <code>notifications.html</code> in the <code>DocumentRoot</code> directory. Then replace this in Manager file of Apache configuration:
</p>
<pre class="code apache"><span class="kw1">RewriteRule</span> <span class="st0">&quot;^/$&quot;</span> <span class="st0">&quot;/psgi/manager-server.fcgi&quot;</span> [PT]
<span class="co1"># DirectoryIndex manager.html</span>
<span class="co1"># RewriteCond &quot;%{REQUEST_FILENAME}&quot; &quot;!\.html$&quot;</span>
<span class="kw1">RewriteCond</span> <span class="st0">&quot;%{REQUEST_FILENAME}&quot;</span> <span class="st0">&quot;!^/(?:static|doc|fr-doc|lib).*&quot;</span>
<span class="kw1">RewriteRule</span> <span class="st0">&quot;^/(.+)$&quot;</span> <span class="st0">&quot;/psgi/manager-server.fcgi/$1&quot;</span> [PT]</pre>
<p>
by:
</p>
<pre class="code apache"><span class="co1"># RewriteRule &quot;^/$&quot; &quot;/psgi/manager-server.fcgi&quot; [PT]</span>
<span class="kw1">DirectoryIndex</span> manager.html
<span class="kw1">RewriteCond</span> <span class="st0">&quot;%{REQUEST_FILENAME}&quot;</span> <span class="st0">&quot;!<span class="es0">\.</span>html$&quot;</span>
<span class="kw1">RewriteCond</span> <span class="st0">&quot;%{REQUEST_FILENAME}&quot;</span> <span class="st0">&quot;!^/(?:static|doc|fr-doc|lib).*&quot;</span>
<span class="kw1">RewriteRule</span> <span class="st0">&quot;^/(.+)$&quot;</span> <span class="st0">&quot;/psgi/manager-server.fcgi/$1&quot;</span> [PT]</pre>
<p>
So manager <abbr title="HyperText Markup Language">HTML</abbr> templates will be no more generated by Perl but directly given by the web server.
</p>
</div>
<!-- EDIT14 SECTION "Use static HTML files" [8793-] --></div>
</body>
</html>