lemonldap-ng/doc/pages/documentation/current/performances.html
2019-09-23 22:41:16 +02:00

545 lines
36 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="index,follow"/>
<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="/static/bwr/jquery-ui/jquery-ui.min.js"></script>
//else -->
<script type="text/javascript" src="/static/bwr/jquery-ui/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="#built-in">Built-in</a></div>
<ul class="toc">
<li class="level2"><div class="li"><a href="#cache_system">Cache system</a></div></li>
</ul>
</li>
<li class="level1"><div class="li"><a href="#global_performance">Global performance</a></div>
<ul class="toc">
<li class="level2"><div class="li"><a href="#cron_optimization_or_systemd_timers">Cron optimization (or systemd timers)</a></div></li>
</ul>
</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="#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>
<li class="level3"><div class="li"><a href="#performance_test">Performance test</a></div></li>
</ul>
</li>
<li class="level2"><div class="li"><a href="#ldap_performances">LDAP performances</a></div></li>
<li class="level2"><div class="li"><a href="#nginx_performances">NGINX 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 for high performance, both in throughput and response time. Indeed, it can use Apache2 threads capabilities <strong>but</strong> since Apache version 2.4, mpm_worker seems to break mod_perl. So to increase performances, prefer using Nginx.
</p>
</div>
<!-- EDIT1 SECTION "Performances" [1-282] -->
<h2 class="sectionedit2" id="built-in">Built-in</h2>
<div class="level2">
</div>
<!-- EDIT2 SECTION "Built-in" [283-303] -->
<h3 class="sectionedit3" id="cache_system">Cache system</h3>
<div class="level3">
<p>
LLNG uses different cache systems to avoid querying to many the databases:
</p>
<div class="table sectionedit4"><table class="inline table table-bordered table-striped">
<thead>
<tr class="row0 roweven">
<th class="col0 leftalign"> </th><th class="col1 centeralign" colspan="2"> Lifetime in memory </th><th class="col3 centeralign" colspan="2"> Lifetime in Local-Cache (file) </th><th class="col5 centeralign"> DB </th>
</tr>
<tr class="row1 rowodd">
<th class="col0 leftalign"> </th><th class="col1 centeralign"> Parameter </th><th class="col2 centeralign"> Default </th><th class="col3 centeralign"> Parameter </th><th class="col4 centeralign"> Default </th><th class="col5 leftalign"> </th>
</tr>
</thead>
<tr class="row2 roweven">
<th class="col0 centeralign"> Configuration </th><td class="col1 centeralign"> <code>checkTime</code> </td><td class="col2 centeralign"> 10 minutes </td><td class="col3 leftalign"> </td><td class="col4 centeralign"> Until &quot;reload&quot; order </td><td class="col5 centeralign"></td>
</tr>
<tr class="row3 rowodd">
<th class="col0 centeralign"> Session </th><td class="col1 centeralign"> <code>handlerInternalCache</code> </td><td class="col2 centeralign"> 15 seconds </td><td class="col3 centeralign"> <code>default_expires_in</code>(*) </td><td class="col4 centeralign"> 10 minutes </td><td class="col5 centeralign"></td>
</tr>
</table></div>
<!-- EDIT4 TABLE [404-879] -->
<p>
<em>(*): Manager &gt;&gt; General parameters &gt;&gt; Sessions &gt;&gt; Sessions storage &gt;&gt; Cache module options</em>
</p>
<div class="noteclassic">Configuration and sessions are first looked up in-memory, then in the cache file, and then in their backing store. This means that after a configuration reload <em>(using Manager)</em>, you have to wait for <code>checkTime</code> before you can see your changes.
</div>
</div>
<!-- EDIT3 SECTION "Cache system" [304-1241] -->
<h2 class="sectionedit5" id="global_performance">Global performance</h2>
<div class="level2">
<p>
By default, Linux does not use <abbr title="Domain Name System">DNS</abbr> cache and LemonLDAP::NG portal request <abbr title="Domain Name System">DNS</abbr> for each 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, dnsmasq or unbound</div>
</li>
</ul>
</div>
<!-- EDIT5 SECTION "Global performance" [1242-1645] -->
<h3 class="sectionedit6" id="cron_optimization_or_systemd_timers">Cron optimization (or systemd timers)</h3>
<div class="level3">
<p>
LLNG installs its cron files without knowing how many servers are installed. You should optimize this to launch:
</p>
<ul>
<li class="level1"><div class="li"> purgeCentralCache: only 1 time every 10 minutes for the whole system (or more)</div>
</li>
<li class="level1"><div class="li"> purgeLocalCache: ~ 1 time per hour on each server</div>
</li>
</ul>
</div>
<!-- EDIT6 SECTION "Cron optimization (or systemd timers)" [1646-1945] -->
<h2 class="sectionedit7" id="handler_performance">Handler performance</h2>
<div class="level2">
<p>
For Nginx, you can use another auth server instead of llng-fastcgi-server. See: <a href="psgi.html" class="wikilink1" title="documentation:2.0:psgi">Advanced PSGI usage</a>.
</p>
<p>
To increase handler performance, you can disable &quot;Sessions activity timeout&quot; to prevent it from writing to the session database.
</p>
<p>
Handlers check rights and calculate headers for each HTTP hit. So to improve performances, avoid too complex rules by using macros, groups or local macros.
</p>
</div>
<!-- EDIT7 SECTION "Handler performance" [1946-2376] -->
<h3 class="sectionedit8" 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"> macros can also be used to import environment variables <em>(these variables are in CGI format)</em>. Example: <code>$ENV{HTTP_COOKIE}</code></div>
</li>
<li class="level1"><div class="li"> groups are stored as space-separated strings in the special attribute &quot;groups&quot;: 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 &quot;macro1&quot; will be computed before macro &quot;macro2&quot;: so, expression of macro2 may involve value of macro1. As same for groups: a group rule may involve another, previously computed group.
</div>
</div>
<!-- EDIT8 SECTION "Macros and groups" [2377-4471] -->
<h3 class="sectionedit9" 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>
<!-- EDIT9 SECTION "Local macros" [4472-5133] -->
<h2 class="sectionedit10" id="portal_performances">Portal performances</h2>
<div class="level2">
</div>
<!-- EDIT10 SECTION "Portal performances" [5134-5166] -->
<h3 class="sectionedit11" id="general_performances">General performances</h3>
<div class="level3">
<p>
The portal is the biggest component of Lemonldap::NG. Since version 2.0, portal runs under FastCGI and has been rewritten using plugins, so performance is increased in comparison to earlier versions. You just have to disable unused plugins:
</p>
<ul>
<li class="level1"><div class="li"> disable unused issuer modules</div>
</li>
<li class="level1"><div class="li"> disable notifications if not used</div>
</li>
<li class="level1"><div class="li"> ...</div>
</li>
</ul>
<p>
By default it uses local storage to store its tokens. If you have more than 1 portal and if your load-balancer doesn&#039;t keep state, you have to disable this to use the global session storage <em>(General parameters » portal Parameters » Advanced Parameters » Forms)</em>. Note that this will decrease performances.
</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>
<!-- EDIT11 SECTION "General performances" [5167-6044] -->
<h3 class="sectionedit12" 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. But it can be a bottleneck 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 class="notetip">Since 1.9.6, LLNG portal and handler check if session is valid at each access, so purgeCentralCache cron no longer needs to be launched every 10 minutes: one or two times per day is enough.
</div>
</div>
<h4 id="replace_mysql_by_apachesessionflex">Replace MySQL by Apache::Session::Flex</h4>
<div class="level4">
<p>
In &quot;Apache::Session module&quot; field, set &quot;<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>&quot; 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. Prefer versions ≥ 1.2.5 for better performances in DB cleaning. To use it (with PostgreSQL for example), choose &quot;Apache::Session::Browseable::Postgres&quot; as &quot;Apache::Session module&quot; and use the following parameters:
</p>
<pre class="code">DataSource -&gt; dbi:Pg:database=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>
<p>
Look at <a href="browseablesessionbackend.html" class="wikilink1" title="documentation:2.0:browseablesessionbackend">Browseable session backend</a> to known which index to choose.
</p>
<div class="noteimportant">Some Apache::Session module are not fully usable by Lemonldap::NG such as Apache::Session::Memcached since these modules do not offer capability to browse sessions. They does not allow one to use sessions explorer neither manage one-off sessions.
</div>
</div>
<h4 id="performance_test">Performance test</h4>
<div class="level4">
<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 fastest (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>])
</div>
<p>
This test isn&#039;t an &quot;only-backend&quot; test but embedded some LLNG methods, so real differences between engines are mitigate here.
</p>
<div class="table sectionedit13"><table class="inline table table-bordered table-striped">
<thead>
<tr class="row0 roweven">
<th class="col0 centeralign" colspan="2"> Backend </th><th class="col2 centeralign" colspan="3"> Portal and handlers </th><th class="col5 centeralign" colspan="3"> Session explorer and one-off sessions </th>
</tr>
<tr class="row1 rowodd">
<th class="col0 centeralign"> Name </th><th class="col1 centeralign"> Configuration </th><th class="col2 centeralign"> Insert 1000 </th><th class="col3 centeralign"> Search 1 </th><th class="col4 centeralign"> Purge 500 </th><th class="col5 centeralign"> Parse all </th><th class="col6 centeralign"> Search by substring </th><th class="col7 centeralign"> Search by UID </th>
</tr>
</thead>
<tr class="row2 roweven">
<td class="col0 leftalign"> Apache::Session::<strong>Browseable::LDAP</strong> </td><td class="col1 leftalign"> mdb </td><td class="col2 centeralign"> 159.66 </td><td class="col3 centeralign"> 0.0120 </td><td class="col4 centeralign"> 49.22 </td><td class="col5 centeralign"> 0.1110 </td><td class="col6 centeralign"> 0.0076 </td><td class="col7 centeralign"> 0.0050 </td>
</tr>
<tr class="row3 rowodd">
<td class="col0 leftalign"> Apache::Session::<strong>MySQL</strong> </td><td class="col1"> No lock </td><td class="col2 centeralign"> 87.20 </td><td class="col3 centeralign"> <strong>0.0039</strong> </td><td class="col4 centeralign"> 23.14 </td><td class="col5 centeralign"> 0.0281 </td><td class="col6 centeralign"> 0.0252 </td><td class="col7 centeralign"> 0.0235 </td>
</tr>
<tr class="row4 roweven">
<td class="col0"> Apache::Session::<strong>Browseable::MySQL</strong> </td><td class="col1 leftalign"> </td><td class="col2 centeralign"> 91.79 </td><td class="col3 centeralign"> <strong>0.0039</strong> </td><td class="col4 centeralign"> <strong>0.139</strong> <em>(1)</em> </td><td class="col5 centeralign"> 0.0272 </td><td class="col6 centeralign"> <strong>0.0036</strong> </td><td class="col7 centeralign"> <strong>0.0026</strong> </td>
</tr>
<tr class="row5 rowodd">
<td class="col0"> Apache::Session::<strong>Browseable::MySQLJSON</strong> </td><td class="col1 leftalign"> </td><td class="col2 centeralign"> 86.06 </td><td class="col3 centeralign"> 0.0145 </td><td class="col4 centeralign"> <strong> 0.151</strong> <em>(2)</em> </td><td class="col5 centeralign"> <strong>0.0104</strong> </td><td class="col6 centeralign"> 0.0137 </td><td class="col7 centeralign"> 0.0038 </td>
</tr>
<tr class="row6 roweven">
<td class="col0 leftalign"> Apache::Session::<strong>Postgres</strong> </td><td class="col1 leftalign"> </td><td class="col2 centeralign"> 18.31 </td><td class="col3 centeralign"> 0.0095 </td><td class="col4 centeralign"> 13.40 </td><td class="col5 centeralign"> 0.0323 </td><td class="col6 centeralign"> 0.0277 </td><td class="col7 centeralign"> 0.0264 </td>
</tr>
<tr class="row7 rowodd">
<td class="col0"> Apache::Session::<strong>Postgres</strong> </td><td class="col1"> Unlogged table </td><td class="col2 centeralign"> 9.16 </td><td class="col3 centeralign"> 0.0095 </td><td class="col4 centeralign"> 7.91 </td><td class="col5 centeralign"> 0.0318 </td><td class="col6 centeralign"> 0.0270 </td><td class="col7 centeralign"> 0.0254 </td>
</tr>
<tr class="row8 roweven">
<td class="col0 leftalign"> Apache::Session::<strong>Browseable::Postgres</strong> </td><td class="col1"> Unlogged table with indexes </td><td class="col2 centeralign"> 9.24 </td><td class="col3 centeralign"> 0.0094 </td><td class="col4 centeralign"> <strong>0.103</strong> <em>(1)</em> </td><td class="col5 centeralign"> 0.0301 </td><td class="col6 centeralign"> <strong>0.0036</strong> </td><td class="col7 centeralign"> <strong>0.0028</strong> </td>
</tr>
<tr class="row9 rowodd">
<td class="col0 leftalign"> Apache::Session::<strong>Browseable::PgJSON</strong> </td><td class="col1"> Unlogged table, json field </td><td class="col2 centeralign"> 9.25 </td><td class="col3 centeralign"> 0.0091 </td><td class="col4 centeralign"> <strong>0.108</strong> <em>(1)</em> </td><td class="col5 centeralign"> 0.0247 </td><td class="col6 centeralign"> <strong>0.0035</strong> </td><td class="col7 centeralign"> <strong>0.0029</strong> </td>
</tr>
<tr class="row10 roweven">
<td class="col0 leftalign"> Apache::Session::<strong>Browseable::PgJSON</strong> </td><td class="col1"> Unlogged table, jsonb field </td><td class="col2 centeralign"> 9.25 </td><td class="col3 centeralign"> 0.0091 </td><td class="col4 centeralign"> <strong>0.105</strong> <em>(1)</em> </td><td class="col5 centeralign"> <strong>0.0126</strong> </td><td class="col6 centeralign"> <strong>0.0034</strong> </td><td class="col7 centeralign"> <strong>0.0029</strong> </td>
</tr>
<tr class="row11 rowodd">
<td class="col0 leftalign"> Apache::Session::<strong>Browseable::PgHstore</strong> </td><td class="col1"> Unlogged table, hstore field </td><td class="col2 centeralign"> 9.62 </td><td class="col3 centeralign"> 0.0111 </td><td class="col4 centeralign"> <strong>0.105</strong> <em>(1)</em> </td><td class="col5 centeralign"> <strong>0.0125</strong> </td><td class="col6 centeralign"> <strong>0.0033</strong> </td><td class="col7 centeralign"> <strong>0.0029</strong> </td>
</tr>
<tr class="row12 roweven">
<td class="col0 leftalign"> Apache::Session::<strong>Redis</strong> </td><td class="col1 leftalign"> </td><td class="col2 centeralign"> <strong>2.13</strong> </td><td class="col3 centeralign"> <strong>0.0033</strong> </td><td class="col4 centeralign"> 1.158 </td><td class="col5 centeralign"> 0.0623 </td><td class="col6 centeralign"> 0.0570 </td><td class="col7 centeralign"> 0.0550 </td>
</tr>
<tr class="row13 rowodd">
<td class="col0 leftalign"> Apache::Session::<strong>Browseable::Redis</strong> </td><td class="col1 leftalign"> </td><td class="col2 centeralign"> <strong>2.36</strong> </td><td class="col3 centeralign"> <strong>0.0033</strong> </td><td class="col4 centeralign"> 1.154 </td><td class="col5 centeralign"> 0.0643 </td><td class="col6 centeralign"> 0.1048 </td><td class="col7 centeralign"> <strong>0.0024</strong> </td>
</tr>
<tr class="row14 roweven">
<td class="col0 centeralign" colspan="8"> <em>The source of this test is available in sources: e2e-tests/sbperf.pl</em> </td>
</tr>
</table></div>
<!-- EDIT13 TABLE [8945-10848] --><ul>
<li class="level1"><div class="li"> <em><strong>(1) :</strong> &quot;purge&quot; test is done with Apache::Session::Browseable-1.2.5 and LLG-2.0. Earlier results are not so good.</em></div>
</li>
<li class="level1"><div class="li"> <em><strong>(2) :</strong> &quot;purge&quot; test is done with Apache::Session::Browseable-1.2.6 and LLG-2.0.</em></div>
</li>
</ul>
<p>
Analysis:
</p>
<ul>
<li class="level1"><div class="li"> LDAP servers are &quot;write-once-read-many&quot;, so write performances are very bad. Don&#039;t use this on heavy load if &quot;Session activity timeout&quot; is enabled <em>(if set, handler &quot;write&quot; sessions)</em></div>
</li>
<li class="level1"><div class="li"> MySQL/MariaDB is better to read than to write. Prefer PostgreSQL if you use &quot;Session activity timeout&quot;</div>
</li>
<li class="level1"><div class="li"> Logged tables decrease a lot insert performances with PostgreSQL, so use unlogged tables for sessions except for persistent sessions</div>
</li>
<li class="level1"><div class="li"> Redis is the best for main usage</div>
</li>
<li class="level1"><div class="li"> Browseable::Postgres/PgHstore/PgJSON are the best SQL solutions on average</div>
</li>
</ul>
</div>
<!-- EDIT12 SECTION "Apache::Session performances" [6045-11626] -->
<h3 class="sectionedit14" id="ldap_performances">LDAP performances</h3>
<div class="level3">
<p>
LDAP server can slow you down when you use LDAP groups retrieval. You can avoid this by setting &quot;memberOf&quot; 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 retrieval, you just have to store &quot;memberOf&quot; 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 &quot;cn=admin,dmdName=groups,dc=example,dc=com cn=su,dmdName=groups,dc=example,dc=com&quot;
</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 &quot;admin su&quot;
</p>
</div>
</div>
<!-- EDIT14 SECTION "LDAP performances" [11627-12761] -->
<h3 class="sectionedit15" id="nginx_performances">NGINX performances</h3>
<div class="level3">
<p>
To increase launch by web browser, for example to load js, css, or fonts, Gzip compression can be activated.
</p>
<p>
Edit file /etc/nginx/mime.types
Check those lines or add :
</p>
<pre class="code perl">application<span class="sy0">/</span>vnd<span class="sy0">.</span>ms<span class="sy0">-</span>fontobject eot<span class="sy0">;</span>
application<span class="sy0">/</span>x<span class="sy0">-</span>font<span class="sy0">-</span>ttf ttf<span class="sy0">;</span>
application<span class="sy0">/</span>font<span class="sy0">-</span>woff woff<span class="sy0">;</span>
font<span class="sy0">/</span>opentype ott<span class="sy0">;</span></pre>
<p>
Edit file /etc/nginx/nginx.conf
</p>
<pre class="code perl">gzip on<span class="sy0">;</span> <span class="co1"># active la compression Gzip</span>
gzip_disable <span class="st0">&quot;msie6&quot;</span><span class="sy0">;</span>
&nbsp;
gzip_vary on<span class="sy0">;</span>
gzip_proxied any<span class="sy0">;</span>
gzip_comp_level <span class="nu0">6</span><span class="sy0">;</span>
gzip_buffers <span class="nu0">16</span> 8k<span class="sy0">;</span>
gzip_http_version <span class="nu0">1.1</span><span class="sy0">;</span>
gzip_min_length <span class="nu0">128</span><span class="sy0">;</span>
gzip_types text<span class="sy0">/</span>plain text<span class="sy0">/</span>css application<span class="sy0">/</span>json application<span class="sy0">/</span>javascript application<span class="sy0">/</span>x<span class="sy0">-</span>javascript text<span class="sy0">/</span>xml application<span class="sy0">/</span>xml application<span class="sy0">/</span>rss<span class="sy0">+</span>xml text<span class="sy0">/</span>javascript application<span class="sy0">/</span>vnd<span class="sy0">.</span>ms<span class="sy0">-</span>fontobject application<span class="sy0">/</span>x<span class="sy0">-</span>font<span class="sy0">-</span>ttf font<span class="sy0">/</span>opentype image<span class="sy0">/</span>jpeg image<span class="sy0">/</span>png image<span class="sy0">/</span>svg<span class="sy0">+</span>xml image<span class="sy0">/</span>x<span class="sy0">-</span>icon<span class="sy0">;</span></pre>
<p>
Restart NGINX and watch web-browser console.
</p>
</div>
<!-- EDIT15 SECTION "NGINX performances" [12762-13684] -->
<h2 class="sectionedit16" id="manager_performances">Manager performances</h2>
<div class="level2">
</div>
<!-- EDIT16 SECTION "Manager performances" [13685-13718] -->
<h3 class="sectionedit17" 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, notifications explorer and second factor 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>
<!-- EDIT17 SECTION "Disable unused modules" [13719-13980] -->
<h3 class="sectionedit18" 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|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|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>
<!-- EDIT18 SECTION "Use static HTML files" [13981-] --></div>
</body>
</html>