In Dubbo3, there is a mechanism for lightweight service downgrading, that is, local mocking.
Mock is a subset of Stub, facilitating service providers to implement fault tolerance logic on the client side. It is often necessary to handle exceptions during RpcException
(e.g., network failures, timeouts), while fault tolerance is not needed for business exceptions (e.g., login username/password errors). Using Stub may require capturing and depending on RpcException
, whereas Mock does not, since its agreement is to only execute when RpcException
occurs.
Local mocking is often used for service downgrading. For example, if an authentication service is completely down, and a service consumer initiates a remote call, this call will fail and throw an RpcException
. To avoid such situations where exceptions are directly thrown, the client can use local mocking to return mock data indicating authorization failure.
Other usage scenarios include:
For complete example source code, please refer to dubbo-samples-mock
In the Spring XML configuration file, configure as follows:
<dubbo:reference interface="com.foo.BarService" mock="true" />
or
<dubbo:reference interface="com.foo.BarService" mock="com.foo.BarServiceMock" />
Provide Mock implementation in the project [^2]:
Place a Mock implementation next to the interface that implements the BarService interface and has a no-argument constructor. If the Mock class is not explicitly specified in the configuration file, ensure the fully qualified class name of the Mock class is in the form of original qualified class name + Mock
, e.g., com.foo.BarServiceMock
, otherwise the Mock will fail.
package com.foo;
public class BarServiceMock implements BarService {
public String sayHello(String name) {
// You can fabricate fault tolerance data; this method is only executed if RpcException occurs
return "Fault Tolerance Data";
}
}
Use return
to return a string representation of an object as the Mock return value. Valid strings can include:
null
.null
true
false
For example, if the service consumer frequently needs to try-catch exceptions, like:
public class DemoService {
public Offer findOffer(String offerId) {
Offer offer = null;
try {
offer = offerService.findOffer(offerId);
} catch (RpcException e) {
logger.error(e);
}
return offer;
}
}
Consider changing this to a Mock implementation and returning null
in the Mock implementation. If you simply want to ignore the exception, in versions 2.0.11
and above, you can use:
<dubbo:reference interface="com.foo.BarService" mock="return null" />
Use throw
to return an Exception object as the Mock return value.
When an error occurs during the call, throw a default RPCException
:
<dubbo:reference interface="com.foo.BarService" mock="throw"/>
When an error occurs during the call, throw a specified Exception:
Custom exceptions must have a constructor with a String
parameter that will be used to accept the exception message.
<dubbo:reference interface="com.foo.BarService" mock="throw com.foo.MockException"/>
force:
represents enforcing the use of Mock behavior, in which case remote calls will not be made.
fail:
behaves as default, only using Mock behavior when remote calls fail. That is, it is possible not to use the fail
keyword in the configuration, directly using throw
or return
.
force:
and fail:
can both be combined with throw
or return
.
Force returning a specified value:
<dubbo:reference interface="com.foo.BarService" mock="force:return fake"/>
Force throwing a specified exception:
<dubbo:reference interface="com.foo.BarService" mock="force:throw com.foo.MockException"/>
Return a specified value on call failure:
<dubbo:reference interface="com.foo.BarService" mock="fail:return fake"/>
<!-- Equivalent to the following -->
<dubbo:reference interface="com.foo.BarService" mock="return fake"/>
Throw an exception on call failure
<dubbo:reference interface="com.foo.BarService" mock="fail:throw com.foo.MockException"/>
<!-- Equivalent to the following -->
<dubbo:reference interface="com.foo.BarService" mock="throw com.foo.MockException"/>
Mock can be specified at the method level. Assume com.foo.BarService
has several methods; we can specifically set Mock behavior for the sayHello()
method.
The specific configuration is as follows. In this example, whenever sayHello()
is called, it will force a return of “fake”:
<dubbo:reference id="demoService" check="false" interface="com.foo.BarService">
<dubbo:parameter key="sayHello.mock" value="force:return fake"/>
</dubbo:reference>
Application consumer side introduce dubbo-mock-admin
dependency
Set the JVM parameter when the application consumer starts: -Denable.dubbo.admin.mock=true
Start dubbo-admin and set the Mock rules under the service Mock -> Rule Configuration menu
Set rules at the level of service methods, dynamically enabling/disabling rules that return mock data
If you have more advanced and professional rate-limiting requirements, we recommend using professional rate limiting and downgrading components such as Sentinel for the best experience. Refer to example practices: Microservices Governance/Rate Limiting and Downgrading
Service downgrading refers to emergency handling of services under abnormal conditions.
Dubbo will check the configuration at startup, and if the mock property value is misconfigured, the startup will fail. You can troubleshoot based on the error message.
return+null
, will cause errors and be treated as mock types. The text after return
can be omitted or followed by the return value after a space.