ClusterForwardProvider
| Property | Value |
|---|---|
| Interface Type | extra-core |
| Module | extra-core |
| Full Class Name | com.fr.stable.fun.ClusterForwardProvider |
Interface Purpose
Use this interface when a plugin needs to forward a series of special requests to a specific node in the cluster.
Specific requests issued by a plugin carry information that must be forwarded to the same node. Once this interface is implemented, requests carrying the same information are forwarded to the same node. All other forwarding follows the cluster's default routing logic, such as load-based or random forwarding.
Interface Definition
Main Interface
package com.fr.stable.fun;
import com.fr.stable.fun.mark.Mutable;
import org.jetbrains.annotations.Nullable;
import javax.servlet.http.HttpServletRequest;
public interface ClusterForwardProvider extends Mutable {
String MARK_STRING = "ClusterForwardProvider";
int CURRENT_LEVEL = 1;
/**
* Get the target node ID for forwarding
*
* @param key cluster shared info key
* @return target node ID
*/
@Nullable
String getTargetNodeID(String key);
/**
* Extract the cluster shared info key from the request
* <p>
* Returns the shared info key if the request carries one;
* returns null otherwise.
*
* @param request req
* @return cluster shared info storage key
* @see #accept(HttpServletRequest)
*/
String getKey(HttpServletRequest request);
/**
* Whether this request should be subject to forwarding logic
* <p>
* Returns <code>true</code> if the request carries a cluster shared info key
* or is a request that creates cluster shared info;
* returns <code>false</code> otherwise.
*
* @param request req
* @return whether forwarding logic should be applied
* @see #getKey(HttpServletRequest)
*/
boolean accept(HttpServletRequest request);
}
Related Interfaces
None
Plugin Registration
Register in plugin.xml:
<extra-core>
<ClusterForwardProvider class="com.fr.plugin.excel.submit.web.cluster.ExcelSubmitClusterForwardProvider"/>
</extra-core>
Example
Using the Batch Excel Import plugin as an example:
The first request is a preparation phase that generates a processid. Subsequent requests โ such as querying the current import status, validating the import, and retrieving import results โ all carry this processid and must be handled by the same node.
After implementing this interface, all requests containing the same processid are forwarded to the same node.
The demo plugin provides three endpoints:
/req/demo/create/req/demo/search/req/demo/view
The search endpoint requires the id returned by the create endpoint. A search request carrying an id parameter is always forwarded to the node that generated that id โ i.e., the node that handled the preceding create request.
Accessing http://host:port/webroot/decision/url/req/demo/create in the browser returns:
{
"id": "4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9",
"isCluster": true,
"clusterId": "M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ==",
"taskName": "4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ=="
}
This request was forwarded to node M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ== by the cluster forwarding strategy (e.g., random or intelligent forwarding).
A subsequent browser request to http://host:port/webroot/decision/url/req/demo/search?id=4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9 is also forwarded to the same node, returning:
{
"id": "4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9",
"isCluster": true,
"clusterId": "M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ==",
"taskName": "4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ=="
}
A request to http://host:port/webroot/decision/url/req/demo/view in the browser is randomly forwarded to a node by the proxy (e.g., nginx).
Interface Example
Example source code: cluster-req-demo
Notes
- Only intercepts URL paths provided by
RequestPreHandleProviderandURLAliasProviderin plugins, i.e.,/url/**and/plugin/**