Router

This article explains how to implement a custom routing strategy by extending the Router, which can achieve specific routing methods based on the characteristics of business scenarios.

By customizing the router, specific routing methods can be implemented based on the characteristics of business scenarios. Please refer to the source code for the router extension implementation in the example at dubbo-samples-extensibility .

Before You Begin

Task Details

Use the first provided service Provider for all requests. If this Provider goes offline, choose a new Provider.

Implementation Method

In the Consumer, customize a Router that saves the Provider used in the first call. If there are subsequent requests and the Provider list includes the Provider used in the first call, continue to use that Provider; otherwise, select a new Provider.

Code Structure

  1. src
  2. |-main
  3. |-java
  4. |-org
  5. |-apache
  6. |-dubbo
  7. |-samples
  8. |-extensibility
  9. |-router
  10. |-consumer
  11. |-router
  12. |-StickFirstStateRouter.java (Implements the StateRouter interface)
  13. |-StickFirstStateRouterFactory.java (Implements the StateRouterFactory interface)
  14. |-resources
  15. |-META-INF
  16. |-application.properties (Dubbo Consumer configuration file)
  17. |-dubbo
  18. |-org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory (Plain text file)

Code Details

  • StickFirstStateRouter
  1. package org.apache.dubbo.samples.extensibility.router.consumer.router;
  2. import org.apache.dubbo.common.URL;
  3. import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
  4. import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
  5. import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
  6. import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
  7. import org.apache.dubbo.common.logger.LoggerFactory;
  8. import org.apache.dubbo.common.utils.CollectionUtils;
  9. import org.apache.dubbo.common.utils.Holder;
  10. import org.apache.dubbo.rpc.Invocation;
  11. import org.apache.dubbo.rpc.Invoker;
  12. import org.apache.dubbo.rpc.RpcException;
  13. import org.apache.dubbo.rpc.cluster.router.RouterSnapshotNode;
  14. import org.apache.dubbo.rpc.cluster.router.state.AbstractStateRouter;
  15. import org.apache.dubbo.rpc.cluster.router.state.BitList;
  16. public class StickFirstStateRouter<T> extends AbstractStateRouter<T> implements ConfigurationListener {
  17. public StickFirstStateRouter(URL url) {
  18. super(url);
  19. }
  20. public static final String NAME = "STICK_FIRST_ROUTER";
  21. private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(StickFirstStateRouter.class);
  22. private volatile BitList<Invoker<T>> firstInvokers;
  23. @Override
  24. protected BitList<Invoker<T>> doRoute(BitList<Invoker<T>> invokers, URL url, Invocation invocation, boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> routerSnapshotNodeHolder, Holder<String> messageHolder) throws RpcException {
  25. if (CollectionUtils.isEmpty(invokers)) {
  26. if (needToPrintMessage) {
  27. messageHolder.set("Directly Return. Reason: Invokers from previous router is empty.");
  28. }
  29. return invokers;
  30. }
  31. BitList<Invoker<T>> copy = invokers.clone();
  32. if (CollectionUtils.isEmpty(copy)) {
  33. this.firstInvokers = new BitList<>(BitList.emptyList());
  34. this.firstInvokers.add(copy.get(0));
  35. } else {
  36. this.firstInvokers = copy.and(invokers);
  37. if(CollectionUtils.isEmpty(this.firstInvokers)){
  38. this.firstInvokers.add(copy.get(0));
  39. }
  40. }
  41. return this.firstInvokers;
  42. }
  43. @Override
  44. public void process(ConfigChangedEvent event) {
  45. if (logger.isDebugEnabled()) {
  46. logger.debug("Notification of tag rule, change type is: " + event.getChangeType() + ", raw rule is:\n " +
  47. event.getContent());
  48. }
  49. // Reset
  50. if (event.getChangeType().equals(ConfigChangeType.DELETED)) {
  51. this.firstInvokers = null;
  52. }
  53. }
  54. @Override
  55. public void stop() {
  56. super.stop();
  57. this.firstInvokers = null;
  58. }
  59. }
  • StickFirstStateRouterFactory
  1. package org.apache.dubbo.samples.extensibility.router.consumer.router;
  2. import org.apache.dubbo.common.URL;
  3. import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
  4. import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
  5. public class StickFirstStateRouterFactory implements StateRouterFactory {
  6. @Override
  7. public <T> StateRouter<T> getRouter(Class<T> interfaceClass, URL url) {
  8. return new StickFirstStateRouter<>(url);
  9. }
  10. }

SPI Configuration

Add the following configuration to the resources/META-INF/dubbo/org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory file:

  1. stickfirst=org.apache.dubbo.samples.extensibility.router.consumer.router.StickFirstStateRouterFactory

Configuration File

Add the following configuration to the resources/application.properties file:

  1. # Configure custom routing
  2. dubbo.consumer.router=stickfirst

Execution Result

Running the task using local IDE, the result is as follows:

dubbo-samples-extensibility-router-output.png

Feedback

Was this page helpful?

Yes No

Last modified September 30, 2024: Update & Translate Overview Docs (#3040) (d37ebceaea7)