When dealing with performance issues, configuring the right tools is required in order to collect relevant data from your running environment. This blog post describes how to use Java Profilers (like VisualVM and YourKit Java Profiler) and PostgreSQL stats when using Docker Compose to deploy Alfresco Community 6.2.
Sample Docker Compose templates are available in https://github.com/aborroy/alfresco-6-profiling
VisualVM
This app uses JMX to gather JVM stats from a running Java process.
In order to have access from your computer to Repository and Search service, following configuration must be added to JAVA_OPTS variables in docker-compose.yml file.
-Dcom.sun.management.jmxremote.rmi.port=9091 -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=9091 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=false -Djava.rmi.server.hostname=127.0.0.1
Exposing the port (9090, 9091) is also required in docker-compose.yml file.
Once Docker Compose is running, Visual VM app can be connected to Repository and Search JVMs by using the following settings:
This tool provide access to configuration, environment settings, process and memory performance and threads. Thread and Core dumps can be also generated for further analysis.
Sample configuration is available in https://github.com/aborroy/alfresco-6-profiling/tree/master/visual-vm
YourKit Java Profiler
This app can use different protocols to gather JVM stats from a running Java process. It's available a trial license, but YourKit Java Profiler requires a paid subscription.
In order to have access from your computer to Repository, following configuration must be added to Alfresco Repository image in docker-compose.yml file.
CATALINA_OPTS: '
-agentpath:/usr/local/YourKit-JavaProfiler-2019.8/bin/linux-x86-64/libyjpagent.so=port=10001,listen=all
'
Exposing the port (10002) is also required in docker-compose.yml file.
Additionally, installing YourKit server agent must be added to Alfresco Dockerfile.
USER root RUN set -x \ && yum install -y wget \ && yum install -y unzip # YourKit RUN wget https://www.yourkit.com/download/docker/YourKit-JavaProfiler-2019.8-docker.zip -P /tmp/ && \ unzip /tmp/YourKit-JavaProfiler-2019.8-docker.zip -d /usr/local && \ rm /tmp/YourKit-JavaProfiler-2019.8-docker.zip EXPOSE 10001
For Search Services, exposing the port (10001) in docker-compose.yml file is required and also the agent installation to SOLR Dockerfile.
USER root RUN set -x \ && yum install -y wget # YourKit RUN wget https://www.yourkit.com/download/docker/YourKit-JavaProfiler-2019.8-docker.zip -P /tmp/ && \ unzip /tmp/YourKit-JavaProfiler-2019.8-docker.zip -d /usr/local && \ rm /tmp/YourKit-JavaProfiler-2019.8-docker.zip EXPOSE 10001 USER solr CMD $DIST_DIR/solr/bin/search_config_setup.sh "$DIST_DIR/solr/bin/solr start -f -a \"-agentpath:/usr/local/YourKit-JavaProfiler-2019.8/bin/linux-x86-64/libyjpagent.so=port=10001,listen=all\""
Once Docker Compose is running, YourKit Java Developer app can be connected to Repository and Search JVMs by using the following settings:
This tool provide advanced access to configuration, environment settings, process and memory performance, exceptions and threads. Thread and Core dumps can be also generated for further analysis.
Sample configuration is available in https://github.com/aborroy/alfresco-6-profiling/tree/master/yourkit
PostgreSQL
The pg_stat_statements module provides a means for tracking execution statistics of all SQL statements executed by a server.
In order to have access to this feature, following configuration must be added to Postgres Docker image command in docker-compose.yml file.
-c shared_preload_libraries='pg_stat_statements'
-c pg_stat_statements.max=10000
-c pg_stat_statements.track=all
Once Docker Compose is running, access to PostgreSQL Docker Image and enable the module.
$ docker exec -it postgres_postgres_1 sh # psql -U alfresco alfresco=# CREATE EXTENSION pg_stat_statements; alfresco=# SELECT pg_stat_statements_reset();
Different metrics can be obtained from database queries by using pg_stat_statements table.
# select substr(replace(regexp_replace(query, E'[\\n\\r]+', ' ', 'g'), ' ', ''),0,80), calls, total_time from pg_stat_statements order by total_time desc limit 20; substr | calls | total_time ---------------------------------------------------------------------------------+-------+------------------ SELECT$1ASTABLE_CAT,n.nspnameASTABLE_SCHEM,ct.relnameASTABLE_NAME,NOTi.indisuni | 142 | 856.017925 insertintoalf_node_properties(node_id,qname_id,locale_id,list_index,actual_type | 2736 | 685.161372 SELECT$1::textASPKTABLE_CAT,pkn.nspnameASPKTABLE_SCHEM,pkc.relnameASPKTABLE_NAM | 142 | 652.549819 insertintoalf_child_assoc(id,version,parent_node_id,child_node_id,type_qname_id | 891 | 411.546461999999 insertintoalf_node(id,version,store_id,uuid,type_qname_id,locale_id,acl_id,tran | 819 | 400.114111 insertintoalf_node_aspects(node_id,qname_id)values($1,$2) | 1677 | 269.889251 SELECT$1ASTABLE_CAT,n.nspnameASTABLE_SCHEM,ct.relnameASTABLE_NAME,a.attnameASCO | 142 | 218.917234 select$1[s],s-pg_catalog.array_lower($1,$2)+$3frompg_catalog.generate_series(pg | 74266 | 121.553584 insertintoalf_content_data(id,version,content_url_id,content_mimetype_id,conten | 242 | 120.325833 updatealf_nodesetversion=$1,audit_creator=$2,audit_created=$3,audit_modifier=$4 | 609 | 103.211222 insertintoalf_node(id,version,store_id,uuid,type_qname_id,locale_id,acl_id,tran | 43 | 98.873413 CREATETABLEalf_applied_patch(idVARCHAR(64)NOTNULL,descriptionVARCHAR(1024),fixe | 2 | 77.130529 SELECT$1ASTABLE_CAT,n.nspnameASTABLE_SCHEM,c.relnameASTABLE_NAME,CASEn.nspname~ | 16 | 75.544505 insertintoalf_node_assoc(id,version,source_node_id,target_node_id,type_qname_id | 15 | 75.363276 deletefromalf_nodewhereid=$1 | 1 | 74.94232 insertintoalf_acl_member(id,version,acl_id,ace_id,pos)values($1,$2,$3,$4,$5) | 151 | 68.966517 SELECT*FROM(SELECTn.nspname,c.relname,a.attname,a.atttypid,a.attnotnullOR(t.typ | 142 | 61.701457 insertintoalf_qname(id,version,ns_id,local_name)values($1,$2,$3,$4) | 230 | 54.407586 insertintoalf_prop_link(root_prop_id,prop_index,contained_in,key_prop_id,value_ | 9 | 49.142844 insertintoalf_access_control_entry(id,version,permission_id,authority_id,allowe | 20 | 46.05998
Sample configuration is available in https://github.com/aborroy/alfresco-6-profiling/tree/master/postgres
Other alternatives
Above some alternatives are described, but check out some other contributions from the Community related with the same topic. Like Using Elastic APM for Alfresco Performance Monitoring by @cesarista and stagemonitor.