《Flowable文档大全》
In some (very) high concurrency load cases, the default ID generator may cause exceptions due to not being able to fetch new ID blocks quickly enough. Every process engine has one ID generator. The default ID generator reserves a block of IDs in the database, such that no other engine will be able to use IDs from the same block. During engine operations, when the default ID generator notices that the ID block is used up, a new transaction is started to fetch a new block. In (very) limited use cases this can cause problems when there is a real high load. For most use cases the default ID generator is more than sufficient. The default org.flowable.engine.impl.db.DbIdGenerator also has a property idBlockSize which can be configured to set the size of the reserved block of IDs and to tweak the behavior of the ID fetching.
在一些(非常)高并发性负载情况下,默认的ID生成器可能会由于无法足够快地获取新的ID块而导致异常。每个流程引擎都有一个ID生成器。默认的ID生成器在数据库中保留一个ID块,这样其他引擎就不能使用来自同一块的ID。在引擎操作期间,当默认的ID生成器注意到ID块已用完时,将启动一个新事务来获取新块。在(非常)有限的用例中,当真正的高负载时,这可能会导致问题。对于大多数用例,默认的ID生成器已经足够了。默认的org.flowable.engine.impl.db.DbIdGenerator还有一个属性idBlockSize,可以将其配置为设置ID的保留块的大小并调整ID获取的行为。
The alternative to the default ID generator is the org.flowable.engine.impl.persistence.StrongUuidGenerator, which generates a unique UUID locally and uses that as an identifier for all entities. Since the UUID is generated without the need for database access, it copes better with very high concurrency use cases. Do note that performance may differ from the default ID generator (both positive and negative) depending on the machine.
The UUID generator can be set up in the Flowable configuration as follows:
默认ID生成器的替代方法是org.flowable.engine.impl.persistence.StrongUuidGenerator,它在本地生成唯一的UUID,并将其用作所有实体的标识符。由于UUID是在不需要数据库访问的情况下生成的,因此它可以更好地处理非常高的并发性用例。请注意,根据机器的不同,性能可能不同于默认的ID生成器(正向和负向都可能)。
UUID生成器可以在Flowable配置中设置,如下所示:
<property name="idGenerator">
<bean class="org.flowable.engine.impl.persistence.StrongUuidGenerator" />
</property>
The use of the UUID ID generator has the following extra dependency:
<dependency>
<groupId>com.fasterxml.uuid</groupId>
<artifactId>java-uuid-generator</artifactId>
<version>3.1.3</version>
</dependency>
Multitenancy in general is a concept where the software is capable of serving multiple different organizations. Key is that the data is partitioned and no organization can see the data of other ones. In this context, such an organization (or a department, or a team or whatever, is called a tenant.
Note that this is fundamentally different from a multi-instance setup, where a Flowable Process engine instance is running for each organization separately (and with a different database schema). Although Flowable is lightweight, and running a Process Engine instance doesn’t take much resources, it does add complexity and more maintenance. But, for some use cases it might be the right solution.
多租户通常是指软件能够为多个不同的组织提供服务的概念。关键是数据是分区的,没有组织可以看到其他组织的数据。在这种情况下,这样的组织(或部门、团队或其他任何东西)被称为租户(tenant)。
请注意,这与多实例设置有根本不同,多实例设置为每个组织分别运行一个Flowable流程引擎实例(并且使用不同的数据库schema)。尽管Flowable是轻量级的,并且运行流程引擎实例不需要太多资源,但它确实增加了复杂性和更多的维护。但是,对于某些用例,这可能是正确的解决方案。
Multitenancy in Flowable is mainly implemented around partitioning the data. It is important to note that Flowable does not enforce multi tenancy rules. This means it will not verify when querying and using data whether the user doing the operation belongs to the correct tenant. This should be done in the layer calling the Flowable engine. Flowable does make sure that tenant information can be stored and used when retrieving process data.
When deploying process definition to the Flowable Process engine it is possible to pass a tenant identifier. This is a string (e.g. a UUID, department id, etc.), limited to 256 characters which uniquely identifies the tenant:
Flowable中的多租户主要是围绕数据分区来实现的。需要注意的是,Flowable不强制执行多租户规则。这意味着它在查询和使用数据时不会验证执行操作的用户是否属于正确的租户。这应该在调用Flowable引擎的层中完成。Flowable确保在检索流程数据时可以存储和使用租户信息。
将流程定义部署到Flowable流程引擎时,可以传递租户标识符(tenant identifier)。这是一个字符串(例如UUID、部门id等),限制为256个字符,唯一地标识租户:
repositoryService.createDeployment()
.addClassPathResource(...)
.tenantId("myTenantId")
.deploy();
Passing a tenant ID during a deployment has following implications:
在部署期间传递租户ID具有以下含义:
To actually make use of the tenant identifier on the process data, all the query API’s have the capability to filter on tenant. For example (and can be replaced by the relevant query implementation of the other entities):
为了实际使用流程数据上的租户标识符,所有查询API都有能力对租户进行过滤。例如(可以替换为其他实体的相关查询实现):
runtimeService.createProcessInstanceQuery()
.processInstanceTenantId("myTenantId")
.processDefinitionKey("myProcessDefinitionKey")
.variableValueEquals("myVar", "someValue")
.list()
The query API’s also allow to filter on the tenant identifier with like semantics and also to filter out entities without tenant id.
Important implementation detail: due to database quirks (more specifically: null handling in unique constraints) the default tenant identifier value indicating no tenant is the empty string. The combination of (process definition key, process definition version, tenant identifier) needs to be unique (and there is a database constraint checking this). Also note that the tenant identifier shouldn’t be set to null, as this will affect the queries since certain databases (Oracle) treat empty string as a null value (that’s why the query .withoutTenantId does a check against the empty string or null). This means that the same process definition (with same process definition key) can be deployed for multiple tenants, each with their own versioning. This does not affect the usage when tenancy is not used.
查询API还允许使用like (相似)语义过滤租户标识符,也可以过滤出没有租户id的实体。
重要的实现细节:由于数据库的异常(更具体地说:在唯一约束中的空处理),表示没有租户的默认租户标识符值是空字符串(empty string)。(流程定义键、流程定义版本、租户标识符)的组合必须是唯一的(并且有一个数据库约束检查这一点)。还请注意,租户标识符不应设置为null,因为这将影响查询,因为某些数据库(Oracle)将空字符串视为空值(这就是为什么查询.withoutTenantId会检查空字符串或空值)。这意味着可以为多个租户部署相同的流程定义(具有相同的流程定义键),每个租户都有自己的版本控制。当不使用租约时,这不会影响使用。
Do note that all of the above does not conflict with running multiple Flowable instances in a cluster.
[Experimental] It is possible to change the tenant identifier by calling the changeDeploymentTenantId(String deploymentId, String newTenantId) method on the repositoryService. This will change the tenant identifier everywhere it was inherited before. This can be useful when going from a non-multitenant setup to a multitenant configuration. See the Javadoc on the method for more detailed information.
请注意,以上所有操作与在集群中运行多个Flowable实例并不冲突。
[实验性]通过调用repositoryService上的changeDeploymentTenantId(String deploymentId, String newTenantId)方法,可以更改租户标识符。这将更改以前继承的所有租户标识符。这在从非多租户设置转换为多租户配置时非常有用。有关更多详细信息,请参阅关于该方法的Javadoc。