You can achieve significant improvement of throughput and a high optimization of latency by using transient processes, as almost no remote calls to the database are necessary and the amount of data stored in the database is reduced. Refer to chapter Transient Processes of the Key Concepts part for details on the concept of transient processes.
To increase performance by using transient processes, you need to perform the following steps:
Enable transient process execution via one of the following two options:
Carnot.Engine.Tuning.SupportTransientProcesses.
Set this property in your carnot.properties file to on. For
details refer to section Tuning of chapter Server Side Properties.Now configure your internal in-memory storage, e.g. Hazelcast. If you are using Hazelcast, refer to section Application Server Setup in the Deployment Guide for details on how to set up Hazelcast for your requirements. Choose the description for the application server you use or the according chapter for Spring if you use Spring.
If there is no need for exposing the in-memory storage, you can set the property
Carnot.Engine.Tuning.TransientProcesses.ExposeInMemStorage in your
carnot.properties file to false to achieve a performance
improvement due to internal optimizations.
Per default, this property is set to true to ensure that during the
execution of transient process instances the process instance in question and all
related persistences are accessible via API, e.g. via WorkflowService#getProcessInstance(long)
(for accesses not using any queries).
Per default, a cluster provider for Hazelcast is used in Stardust (ClusteredEnvHazelcastObjectProvider).
You have the option to write your own provider, which you can set to be used via the
following server-side property Carnot.Engine.Tuning.SupportTransientProcesses.ClusterSafeObjectProvider.
The default setting for this property in Stardust uses the cluster provider for Hazelcast mentioned above:
Carnot.Engine.Tuning.SupportTransientProcesses.ClusterSafeObjectProvider = org.eclipse.stardust.engine.core.persistence.jdbc.transientpi.ClusteredEnvHazelcastObjectProvider
See the provided implementation for Hazelcast as example:
package org.eclipse.stardust.engine.core.persistence.jdbc.transientpi;
import java.util.Map;
import javax.resource.ResourceException;
import javax.resource.cci.ConnectionFactory;
import org.eclipse.stardust.common.config.ExtensionProviderUtils;
import org.eclipse.stardust.common.error.PublicException;
import org.eclipse.stardust.engine.core.runtime.beans.BpmRuntimeEnvironment;
import org.eclipse.stardust.engine.core.runtime.beans.interceptors.PropertyLayerProviderInterceptor;
import org.eclipse.stardust.engine.core.runtime.beans.removethis.KernelTweakingProperties;
import org.eclipse.stardust.engine.core.spi.cluster.ClusterSafeObjectProvider;
import org.eclipse.stardust.engine.core.spi.jca.HazelcastJcaConnectionFactoryProvider;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.Transaction;
public class ClusteredEnvHazelcastObjectProvider implements ClusterSafeObjectProvider
{
private static final HazelcastJcaConnectionFactoryProvider CONNECTION_FACTORY_PROVIDER;
static
{
CONNECTION_FACTORY_PROVIDER = ExtensionProviderUtils.getFirstExtensionProvider(HazelcastJcaConnectionFactoryProvider.class, KernelTweakingProperties.HZ_JCA_CONNECTION_FACTORY_PROVIDER);
if (CONNECTION_FACTORY_PROVIDER == null)
{
throw new IllegalStateException("No Hazelcast JCA connection factory provider could be found.");
}
}
@Override
public <K, V> Map<K, V> clusterSafeMap(final String mapId)
{
if (mapId == null)
{
throw new NullPointerException("Map ID for Hazelcast map must not be null.");
}
return Hazelcast.getMap(mapId);
}
@Override
public void beforeAccess()
{
final BpmRuntimeEnvironment rtEnv = PropertyLayerProviderInterceptor.getCurrent();
final ConnectionFactory connectionFactory = CONNECTION_FACTORY_PROVIDER.connectionFactory();
try
{
/* Hazelcast can only cope with one transaction per thread */
if (Hazelcast.getTransaction().getStatus() != Transaction.TXN_STATUS_ACTIVE)
{
/* enlists Hazelcast objects in the current tx */
rtEnv.retrieveJcaConnection(connectionFactory);
}
}
catch (final ResourceException e)
{
throw new PublicException("Failed enlisting Hazelcast objects in the current transaction.", e);
}
}
@Override
public void exception(final Exception ignored)
{
/* nothing to do */
}
@Override
public void afterAccess()
{
/* nothing to do */
}
}
The location from where the (Hazelcast) JCA connection factory can be retrieved
from can be defined via the SPI org.eclipse.stardust.engine.core.spi.jca.HazelcastJcaConnectionFactoryProvider.
Stardust provides the following implementations:
org.eclipse.stardust.engine.core.persistence.jca.JndiHazelcastJcaConnectionFactoryProviderorg.eclipse.stardust.engine.spring.integration.jca.SpringAppContextHazelcastJcaConnectionFactoryProviderSet the implementation to be used via the property Carnot.Engine.Hazelcast.JcaConnectionFactoryProvider
in your carnot.properties file, e.g.:
Carnot.Engine.Hazelcast.JcaConnectionFactoryProvider = org.eclipse.stardust.engine.spring.integration.jca.SpringAppContextHazelcastJcaConnectionFactoryProvider
Configure fast caching sequence generators to optimize database sequence
fetching and achieve less database communication. Set the following properties in
your carnot.properties file:
Carnot.Engine.Tuning.SequenceBatchSizeAuditTrail.SequenceGeneratorFor example, set the following values:
Carnot.Engine.Tuning.SequenceBatchSize = 5000 AuditTrail.SequenceGenerator = org.eclipse.stardust.engine.core.persistence.jdbc.sequence.FastCachingSequenceGenerator
The FastCachingSequenceGenerator is used to retrieve sequence numbers
in a batch and cache the retrieved sequences separately for every entity type.
Perform the following statements to obtain the according database schema changes:
ALTER SEQUENCE activity_instance_seq INCREMENT BY 5000; ALTER SEQUENCE activity_instance_log_seq INCREMENT BY 5000; ALTER SEQUENCE act_inst_property_seq INCREMENT BY 5000; ALTER SEQUENCE trans_inst_seq INCREMENT BY 5000; ALTER SEQUENCE trans_token_seq INCREMENT BY 5000; ALTER SEQUENCE daemon_log_seq INCREMENT BY 5000; ALTER SEQUENCE data_value_seq INCREMENT BY 5000; ALTER SEQUENCE event_binding_seq INCREMENT BY 5000; ALTER SEQUENCE log_entry_seq INCREMENT BY 5000; ALTER SEQUENCE link_type_seq INCREMENT BY 5000; ALTER SEQUENCE model_dep_seq INCREMENT BY 5000; ALTER SEQUENCE property_seq INCREMENT BY 5000; ALTER SEQUENCE timer_log_seq INCREMENT BY 5000; ALTER SEQUENCE usergroup_seq INCREMENT BY 5000; ALTER SEQUENCE usergroup_property_seq INCREMENT BY 5000; ALTER SEQUENCE user_seq INCREMENT BY 5000; ALTER SEQUENCE user_property_seq INCREMENT BY 5000; ALTER SEQUENCE wfuser_session_seq INCREMENT BY 5000; ALTER SEQUENCE user_participant_seq INCREMENT BY 5000; ALTER SEQUENCE user_usergroup_seq INCREMENT BY 5000; ALTER SEQUENCE process_instance_seq INCREMENT BY 5000; ALTER SEQUENCE proc_inst_property_seq INCREMENT BY 5000; ALTER SEQUENCE structured_data_value_seq INCREMENT BY 5000; ALTER SEQUENCE domain_seq INCREMENT BY 5000; ALTER SEQUENCE domain_hierarchy_seq INCREMENT BY 5000; ALTER SEQUENCE wfuser_domain_seq INCREMENT BY 5000; ALTER SEQUENCE wfuser_realm_seq INCREMENT BY 5000; ALTER SEQUENCE clob_data_seq INCREMENT BY 5000; ALTER SEQUENCE model_seq INCREMENT BY 5000; ALTER SEQUENCE STRING_DATA_SEQ INCREMENT BY 5000; ALTER SEQUENCE partition_seq INCREMENT BY 5000; ALTER SEQUENCE department_seq INCREMENT BY 5000; COMMIT;
Note
Note that if you use MySQL, you need
to prepare a MYSQL sequence support first as described in detail in section
MySQL Sequence Support (required for using Transient Processes) of chapter
MySQL Audit Trail Database Setup in the
Deployment Guide.