Build dubbo interface test platform with dubbo go

background

http interface test only needs a curl command, but dubbo protocol has no such ready-made interface test tool. Usually, the dubbo console or other platforms in the company will integrate a dubbo interface testing tool.

When calling a dubbo interface, you need to know the service name, method name and parameter args.

For normal calls, the caller needs to import the interface jar package defined by the service provider.

As an interface test platform, it is impossible to import all interface jar packages defined by the provider. The following solutions can be adopted:

  1. dubbo supports telnet protocol calling dubbo interface
  2. dubbo's generalized call can call the interface without introducing the provider interface definition jar package

For scheme 1, the implementation cost is very low, and it can even be tested directly with telnet on the server

It also has disadvantages

  • The call cannot pass through the filter
  • Cannot carry implicit parameter attachment

We just trampled on the advantages and disadvantages of scheme 1. Our dubbo console is written in go language and implemented quickly in a short time, so we adopted telnet.

With the development of business, traffic coloring or label routing need to carry implicit parameters.

We didn't use the custom filter, resulting in the execution of the business interface not meeting expectations, which forced us to upgrade to generalized calls.

When the console is written by go, there are also two options for dubbo interface generalization call:

  1. Set up a separate java process, expose the http port, interact with the go process, and write the generalized call using dubbo's java sdk
  2. Dubbo go is introduced into the console, and Dubbo go is used for general calls

Based on the understanding of dubbo java version, scheme 1 is certainly feasible, but the architecture becomes complex.

As Dubbo go is a relatively new project and is not well understood, scheme 2 is uncertain about its feasibility and compatibility, but if it can be implemented, it will greatly reduce the complexity of the architecture.

Introduction to Dubbo go

dubbo go is the Gobbo implementation version of dubbo. Its original intention is to make the Gobbo ecology of golang and java interoperate.

Today, dubbo go supports the provider and consumer side, and can be used as an independent rpc framework. At the same time, the community is also the hottest one in dubbo ecology.

If you want to talk about its significance, I think in addition to interworking with java, there is another very important point, that is, it can play a great role in golang collaboration. This can be used in dubbo gateway. If dubbo go is used to implement dubbo gateway, there is no need to worry about thread pool, asynchrony and other problems.

Use of generalized calls

First, the provider side provides an interface, which is very simple. The interface definition is as follows

package org.newboo.basic.api;

import org.newboo.basic.model.RpcResult;
import org.newboo.basic.model.User;

public interface MyDemoService {
    RpcResult<String> call(User user);
}
package org.newboo.basic.model;

import java.io.Serializable;

public class User implements Serializable {
    private String uid;
    private String name;
    private String remoteServiceTag;
    ...
}

Then write the java version of the generalized calling code without introducing the jar package of the provider:

ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
// ① Reference service name
reference.setInterface("org.newboo.basic.api.MyDemoService");
// ② Set generalized call flag
reference.setGeneric("true");

DubboBootstrap bootstrap = DubboBootstrap.getInstance();
bootstrap.application(new ApplicationConfig("dubbo-demo-api-consumer"))
        .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
        .reference(reference)
        .start();

GenericService genericService = ReferenceConfigCache.getCache().get(reference);
String[] ps = new String[1];
// ③ Parameter type
ps[0] = "org.newboo.basic.model.User";
Object[] ags = new Object[1];
// ④ pojo parameters are constructed using map
Map<String, String> user = new HashMap<>();
user.put("uid", "1");
user.put("name", "roshi");
user.put("remoteServiceTag", "tag");
ags[0] = user;
// ⑤ Initiate call
Object res = genericService.$invoke("call", ps, ags);
System.out.println(res);

The key steps are indicated in the code comments

golang version

Directly modify the Dubbo go samples code, refer to https://github.com/apache/dubbo-go-samples
The configuration file path ENV needs to be set at startup

var (
	appName         = "UserConsumer"
	referenceConfig = config.ReferenceConfig{
		InterfaceName: "org.newboo.basic.api.MyDemoService",
		Cluster:       "failover",
    // registry requires a configuration file
		Registry:      "demoZk",
		Protocol:      dubbo.DUBBO,
		Generic:       true,
	}
)

func init() {
	referenceConfig.GenericLoad(appName) //appName is the unique identification of RPCService
	time.Sleep(1 * time.Second)
}

// need to setup environment variable "CONF_CONSUMER_FILE_PATH" to "conf/client.yml" before run
func main() {
	call()
}

func call() {
  // Set attachment
	ctx := context.WithValue(context.TODO(), constant.AttachmentKey, map[string]string{"tag":"test"})

	resp, err := referenceConfig.GetRPCService().(*config.GenericService).Invoke(
		ctx,
		[]interface{}{
			"call",
			[]string{"org.newboo.basic.model.User"},
			[]interface{}{map[string]string{"uid":"111","name":"roshi","remoteServiceTag":"hello"}},
		},
	)
	if err != nil {
		panic(err)
	}
	gxlog.CInfo("success called res: %+v\n", resp)
}

Here I set an attachment, which can also be recognized by the provider normally

Generalized call principle

GenericService is a service provided by dubbo by default.

It provides a method named $invoke, which has three parameters. The first parameter is the real method name to be called, the second is the parameter type array, and the third is the real parameter array, which is defined as

public interface GenericService {
    Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException;
    ...
}

With these three parameters, you can call the real interface using reflection.

java implementation details

The implementation of this generalization call mainly involves two filter s:

  • GenericImplFilter on the consumer side
  • GenericFilter on the provider side

The filter on the consumer side sets the generic flag to the attachment and encapsulates the call as genericservice$ invoke

When the provider side filter judges that the request is generic, it intercepts it, obtains the calling method name, parameters and parameter values, serializes them into pojo objects, and then reflects and calls the real interface.

Dubbo go version details

It is basically consistent with the java implementation, in which generic_ The filter acts as the filter on the consumer side and encapsulates the call as genericservice$ Invoke, which also involves a parameter type conversion, converting the map to dubbo-go-hessian 2 Object, so that the provider can deserialize it into an object object.

The relevant version changes are as follows

  • v1.3.0 supports generalized calls
  • v1.4.0 supports user setting attachment
  • v1.5.1 start to support dynamic tag routing
  • v1.5.7-rc1 fixed the bug that the filter cannot be accessed when the direct provider is connected

Step pit: v1 Before 5.7-rc1, if the direct provider is used, the filter will not be used, resulting in an error in parameter serialization, and the provider will report a type conversion exception

conclusion

The generalization call of Dubbo go is recommended to use > = v1 The function of version 5.7-rc1 is almost equal to that of java, and even its implementation is similar to java.

It is a good choice to use Dubbo go to build a gateway, interface test platform, or get through the technology ecology of golang and java.

Search focuses on official account of WeChat public, bug catch, technology sharing, architecture design, performance optimization, source code reading, problem checking, and paging practice.

Keywords: Go Dubbo

Added by AnnieKay on Tue, 18 Jan 2022 16:59:32 +0200