By Tiecheng, a member of the Dubbo-go community
This article describes how to use Dubbo-go to call service providers provided by Dubbo-go or Dubbo in detail.
This article is based on Dubbo-go 1.5.4.
Before the Dubbo-go development tests started recently, samples were used for functional verification. Now, to reproduce a functional problem, a project of Dubbo-go and Dubbo calling has been planned from scratch to record the potential problems newcomers might encounter.
This article contains two parts:
Define DemoService
interface:
public interface DemoService {
String sayHello(String name);
String sayHello(User user);
String sayHello(User user, String name);
}
Define User
object:
public class User implements Serializable {
private String name;
private int age;
......
}
Use Dubbo official sample code:
public static void main(String[] args) throws IOException {
// Service implementation
DemoService demoService = new DemoServiceImpl();
// Current application configuration
ApplicationConfig application = new ApplicationConfig();
application.setName("demoProvider");
// Connect to the configuration of the registry center
RegistryConfig registry = new RegistryConfig();
registry.setAddress("127.0.0.1:2181");
registry.setProtocol("zookeeper");
registry.setUsername("");
registry.setPassword("");
// Protocol configuration of service providers
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName("dubbo");
protocol.setPort(12345);
protocol.setThreads(200);
// Note: ServiceConfig is a heavy instance, which internally encapsulates the connection with the registry center and starts the service port.
// Exposed service configuration by service providers
ServiceConfig<DemoService> service = new serviceConfig<> (); // This instance is heavy, encapsulating the connection with the registry center. Please cache the instance on your own to prevent memory and connection leakage.
service.setApplication(application);
service.setRegistry(registry); // setRegistries() for multiple registry centers
service.setProtocol(protocol); // setProtocols() for multiple protocols
service.setInterface(DemoService.class);
service.setRef(demoService);
service.setVersion("1.0.0");
service.setGroup("tc");
service.setTimeout(60 * 1000);
// Exposure and services registering
service.export();
System.in.read();
}
Check zookeeper to see if services have been registered successfully:
$ls /dubbo/com.funnycode.DemoService/providers
[dubbo%3A%2F%2F127.0.0.1%3A12345%2Fcom.funnycode.DemoService%3Fanyhost%3Dtrue%26application%3DdemoProvider%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26group%3Dtc%26interface%3Dcom.funnycode.DemoService%26methods%3DsayHello%26pid%3D18167%26release%3D2.7.7%26revision%3D1.0.0%26side%3Dprovider%26threads%3D200%26timestamp%3D1606896020691%26version%3D1.0.0]
The preceding output indicates that the service providers have been started.
Define User object:
type User struct {
Name string
Age int
}
func (User) JavaClassName() string {
return "com.funnycode.User"
}
Define DemoProvider interface:
type DemoProvider struct {
SayHello func(ctx context.Context, name string) (string, error) `dubbo:"sayHello"`
SayHello2 func(ctx context.Context, user User) (string, error) `dubbo:"sayHello"`
SayHello3 func(ctx context.Context, user User, name string) (string, error) `dubbo:"sayHello"`
}
func (p *DemoProvider) Reference() string {
return "DemoProvider"
}
Start Dubbo-go consumer
func main() {
config.Load()
gxlog.CInfo("\n\n\nstart to test dubbo")
res, err := demoProvider.SayHello(context.TODO(), "tc")
if err != nil {
panic(err)
}
gxlog.CInfo("response result: %v\n", res)
user := User{
Name: "tc",
Age: 18,
}
res, err = demoProvider.SayHello2(context.TODO(), user)
if err != nil {
panic(err)
}
gxlog.CInfo("response result: %v\n", res)
res, err = demoProvider.SayHello3(context.TODO(), user, "tc")
if err != nil {
panic(err)
}
gxlog.CInfo("response result: %v\n", res)
initSignal()
}
Problem confirmation
The parameter of the first interface is a string, which normally returns '[2020-12-03/18:59:12 main.main: client.go: 29] response result: Hello tc'.
The second and third interfaces cannot be called because of the User object. The error messages are as follows:
2020-12-02T17:10:47.739+0800 INFO getty/listener.go:87 session{session session-closed, Read Bytes: 924, Write Bytes: 199, Read Pkgs: 0, Write Pkgs: 1} got error{java exception:Fail to decode request due to: java.lang.IllegalArgumentException: Service not found:com.funnycode.DemoService, sayHello
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:134)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:80)
at org.apache.dubbo.remoting.transport.DecodeHandler.decode(DecodeHandler.java:57)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:44)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
}, will be closed.
Errors are as described in the issue. Since the error information is returned to the consumers, the error stack information in Java is available to check. Therefore, check DecodeableRpcInvocation.decode#134
directly.
The code is listed below:
// Deserialization
public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Decodeable {
public Object decode(Channel channel, InputStream input) throws IOException {
......
if (serviceDescriptor != null) {
// Search by method name in method description
MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(getMethodName(), desc);
if (methodDescriptor != null) {
pts = methodDescriptor.getParameterClasses();
this.setReturnTypes(methodDescriptor.getReturnTypes());
}
}
// Indicate that no methods are found
if (pts == DubboCodec.EMPTY_CLASS_ARRAY) {
if (!RpcUtils.isGenericCall(path, getMethodName()) && !RpcUtils.isEcho(path, getMethodName())) {
throw new IllegalArgumentException("Service not found:" + path + ", " + getMethodName());
}
pts = ReflectUtils.desc2classArray(desc);
}
......
}
}
MethodDescriptor
, to find out whether there are methods. If methods exist, ParameterClasses
will be set.pts == DubboCodec.EMPTY_CLASS_ARRAY
will be met to determine whether it is a generic call or an echo call. If neither is true, it will report that the service cannot be found and the method is wrong.Ljava/lang/Object method
and, no method exists in which a parameter is an Object, so an error is inevitable.Note: Method Query
The code is listed below:
public MethodDescriptor getMethod(String methodName, String params) {
Map<String, MethodDescriptor> methods = descToMethods.get(methodName);
if (CollectionUtils.isNotEmptyMap(methods)) {
return methods.get(params);
}
return null;
}
Advantages: Compared with the previous version, the method metadata is cached. Therefore, the efficiency is improved without reflection, namely, trading time for space.
Direct code writing cannot fix the problem, so a comparison is provided to locate the problem.
Start the Dubbo consumers through the API mode. For more information, please see the official example. This operation is to view the transmission content of the Java version.
public static void main(String[] args) throws InterruptedException {
// Current application configuration
ApplicationConfig application = new ApplicationConfig();
application.setName("demoProvider2");
// Connect to the configuration of the registry center
RegistryConfig registry = new RegistryConfig();
registry.setAddress("127.0.0.1:2181");
registry.setProtocol("zookeeper");
registry.setUsername("");
registry.setPassword("");
// Note: ReferenceConfig is a heavy instance, which internally encapsulates the connection with the registry center and the service provider.
// Reference of remote services
ReferenceConfig<DemoService> reference
= new ReferenceConfig<>(); // This instance is very heavy, encapsulating the connection with the registry center and the service provider. Please cache the instance on your own to prevent memory and connection leakage.
reference.setApplication(application);
reference.setRegistry(registry); // setRegistries() for multiple registry centers
reference.setInterface(DemoService.class);
reference.setVersion("1.0.0");
reference.setGroup("tc");
reference.setCheck(true);
reference.setTimeout(1000 * 60);
// Use xxxService like a local bean
DemoService demoService = reference.get(); // Note: The proxy instance encapsulates all communication details. The instance is heavy, so please cache the instance for reuse.
System.out.println(demoService.sayHello(new User("tc", 18)));
TimeUnit.MINUTES.sleep(10);
}
Desc is Lcom/funnycode/User
, and this is the right instance.
Code Location:
protocol/dubbo/impl/hessian.go:120#marshalRequest
Code Implementation:
func marshalRequest(encoder *hessian.Encoder, p DubboPackage) ([]byte, error) {
service := p.Service
request := EnsureRequestPayload(p.Body)
encoder.Encode(DEFAULT_DUBBO_PROTOCOL_VERSION)
encoder.Encode(service.Path)
encoder.Encode(service.Version)
encoder.Encode(service.Method)
args, ok := request.Params.([]interface{})
if !ok {
logger.Infof("request args are: %+v", request.Params)
return nil, perrors.Errorf("@params is not of type: []interface{}")
}
types, err := getArgsTypeList(args)
if err != nil {
return nil, perrors.Wrapf(err, " PackRequest(args:%+v)", args)
}
encoder.Encode(types)
for _, v := range args {
encoder.Encode(v)
}
......
}
From the breakpoint, the types is returned as Object
, and no User
returned. Then, continue to view the code:
protocol/dubbo/impl/hessian.go:394#getArgsTypeList
protocol/dubbo/impl/hessian.go:418#getArgType
func getArgType(v interface{}) string {
// Common type processing
......
default:
t := reflect.TypeOf(v)
if reflect.Ptr == t.Kind() {
t = reflect.TypeOf(reflect.ValueOf(v).Elem())
}
switch t.Kind() {
case reflect.Struct:
return "java.lang.Object"
}
......
}
java.lang.Object
is returned when it is reflect.Struct
, and the parameter becomes Object
. As a result, the call fails because the Java code depends on this type.
Since an error is detected in version 2.7.7, the service provider is switched to Dubbo 2.7.3 to see if errors occur in the former versions. As suggested by the result, the call errors still exist, as shown below:
2020-12-02T21:52:25.945+0800 INFO getty/listener.go:85 session{session session-closed, Read Bytes: 4586, Write Bytes: 232, Read Pkgs: 0, Write Pkgs: 1} got error{java exception:org.apache.dubbo.rpc.RpcException: Failed to invoke remote proxy method sayHello to registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=demoProvider&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.0.113%3A12345%2Fcom.funnycode.DemoService%3Fanyhost%3Dtrue%26application%3DdemoProvider%26bind.ip%3D192.168.0.113%26bind.port%3D12345%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26group%3Dtc%26interface%3Dcom.funnycode.DemoService%26methods%3DsayHello%26pid%3D23889%26register%3Dtrue%26release%3D2.7.3%26revision%3D1.0.0%26side%3Dprovider%26threads%3D200%26timeout%3D60000%26timestamp%3D1606916702204%26version%3D1.0.0&pid=23889®istry=zookeeper&release=2.7.3×tamp=1606916702193, cause: Not found method "sayHello" in class com.funnycode.DemoServiceImpl.
org.apache.dubbo.rpc.RpcException: Failed to invoke remote proxy method sayHello to registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=demoProvider&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.0.113%3A12345%2Fcom.funnycode.DemoService%3Fanyhost%3Dtrue%26application%3DdemoProvider%26bind.ip%3D192.168.0.113%26bind.port%3D12345%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26group%3Dtc%26interface%3Dcom.funnycode.DemoService%26methods%3DsayHello%26pid%3D23889%26register%3Dtrue%26release%3D2.7.3%26revision%3D1.0.0%26side%3Dprovider%26threads%3D200%26timeout%3D60000%26timestamp%3D1606916702204%26version%3D1.0.0&pid=23889®istry=zookeeper&release=2.7.3×tamp=1606916702193, cause: Not found method "sayHello" in class com.funnycode.DemoServiceImpl.
at org.apache.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:107)
at org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker.invoke(DelegateProviderMetaDataInvoker.java:56)
at org.apache.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:56)
at org.apache.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:55)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:92)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
at org.apache.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:48)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
at org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:81)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:96)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:148)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$CallbackRegistrationInvoker.invoke(ProtocolFilterWrapper.java:157)
at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:152)
at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:102)
at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:193)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.dubbo.common.bytecode.NoSuchMethodException: Not found method "sayHello" in class com.funnycode.DemoServiceImpl.
at org.apache.dubbo.common.bytecode.Wrapper1.invokeMethod(Wrapper1.java)
at org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:47)
at org.apache.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:84)
... 27 more
}, will be closed.
Although this is different from the code in 2.7.7, it can also be seen from the errors that the method cannot be found in the proxy enhancement class. It is highly possible that the reflection cannot find the method, which is also a parameter problem.
The repair is simply to obtain JavaClassName
defined by struct
.
case reflect.Struct:
v, ok := v.(hessian.POJO)
if ok {
return v.JavaClassName()
}
return "java.lang.Object"
Execute the consumer again, and the operation is normal in both 2.7.7 and 2.7.3 providers. The output is listed below:
[2020-12-03/20:04:06 main.main: client.go: 29] response result: Hello tc
...
[2020-12-03/20:04:09 main.main: client.go: 41] response result: Hello tc You are 18
...
[2020-12-03/20:04:09 main.main: client.go: 48] response result: Hello tc You are 18
Maybe you have found that the consumer interface in Dubbo-go is called DemoProvider
, and then called DemoService
in the provider. How does it work normally?
It is related to the references
in client.yml
. In the configuration file, interface
, version
, and group
are described in detail. Methods can be used to configure method information, such as the timeout.
references:
"DemoProvider":
# Multiple registries can be specified with commas to separate. If not specified, register with all registry centers by default.
registry: "zk1"
protocol: "dubbo"
interface: "com.funnycode.DemoService"
cluster: "failover"
version: "1.0.0"
group: "tc"
methods:
- name: "SayHello"
retries: 3
......
The following figure shows the configuration file:
# application config
application:
organization: "dubbogoproxy.com"
name: "Demo Micro Service"
module: "dubbogoproxy tc client"
version: "1.0.0"
group: "tc"
owner: "ZX"
environment: "dev"
references:
"DemoProvider":
# Multiple registries can be specified with commas to separate. If not specified, register with all registry centers by default.
registry: "zk1"
protocol: "dubbo"
interface: "com.funnycode.DemoService"
cluster: "failover"
# version: "1.0.0"
# group: "tc"
methods:
- name: "SayHello"
retries: 3
Usually, it must be application
that represents the global configuration. However, when starting version
and group
configured in application
, it will not be assigned to the interface. The result of service not found will be reported after the start:
2020-12-03T20:15:42.208+0800 DEBUG zookeeper/registry.go:237 Create a zookeeper node:/dubbo/com.funnycode.DemoService/consumers/consumer%3A%2F%2F30.11.176.107%2FDemoProvider%3Fapp.version%3D1.0.0%26application%3DDemo+Micro+Service%26async%3Dfalse%26bean.name%3DDemoProvider%26cluster%3Dfailover%26environment%3Ddev%26generic%3Dfalse%26group%3D%26interface%3Dcom.funnycode.DemoService%26ip%3D30.11.176.107%26loadbalance%3D%26methods.SayHello.loadbalance%3D%26methods.SayHello.retries%3D3%26methods.SayHello.sticky%3Dfalse%26module%3Ddubbogoproxy+tc+client%26name%3DDemo+Micro+Service%26organization%3Ddubbogoproxy.com%26owner%3DZX%26pid%3D38692%26protocol%3Ddubbo%26provided-by%3D%26reference.filter%3Dcshutdown%26registry.role%3D0%26release%3Ddubbo-golang-1.3.0%26retries%3D%26side%3Dconsumer%26sticky%3Dfalse%26timestamp%3D1606997742%26version%3D
Version
and group
are empty. The annotations of version
and group
under DemoProvider
must be opened.
When Dubbo-go calls Dubbo, the following errors will occur because method names are capital in Go and lowercase in Java:
2020-12-02T17:10:47.739+0800 INFO getty/listener.go:87 session{session session-closed, Read Bytes: 924, Write Bytes: 199, Read Pkgs: 0, Write Pkgs: 1} got error{java exception:Fail to decode request due to: java.lang.IllegalArgumentException: Service not found:com.funnycode.DemoService, SayHello
java.lang.IllegalArgumentException: Service not found:com.funnycode.DemoService, SayHello
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:134)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:80)
at org.apache.dubbo.remoting.transport.DecodeHandler.decode(DecodeHandler.java:57)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:44)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
}, will be closed.
You may have noticed that there is a dubbo:"sayHello"
on the consumer interface, indicating that the method name is sayHello
. Thus, the service provider can obtain the method name sayHello
.
The three declared methods all are called dubbo:"sayHello"
because Java can reload the same method names and Go cannot duplicate method names.
The following code can be run normally.
The Provider Interface:
type DemoProvider struct{}
func (p *DemoProvider) SayHello(ctx context.Context, name string) (string, error) {
return "Hello " + name, nil
}
func (p *DemoProvider) SayHello4(ctx context.Context, user *User) (string, error) {
return "Hello " + user.Name + " You are " + strconv.Itoa(user.Age), nil
}
func (p *DemoProvider) SayHello5(ctx context.Context, user *User, name string) (string, error) {
return "Hello " + name + " You are " + strconv.Itoa(user.Age), nil
}
func (p *DemoProvider) Reference() string {
return "DemoProvider"
}
func (p *DemoProvider) MethodMapper() map[string]string {
return map[string]string{
"SayHello": "sayHello",
}
}
The Consumer Interface:
type DemoProvider struct {
// Call Java and Go
SayHello func(ctx context.Context, name string) (string, error) `dubbo:"sayHello"`
// Call Java only
SayHello2 func(ctx context.Context, user *User) (string, error) `dubbo:"sayHello"`
SayHello3 func(ctx context.Context, user *User, name string) (string, error) `dubbo:"sayHello"`
// Call Go only
SayHello4 func(ctx context.Context, user *User) (string, error)
SayHello5 func(ctx context.Context, user *User, name string) (string, error)
}
Start the Service Consumer:
func main() {
config.Load()
gxlog.CInfo("\n\n\nstart to test dubbo")
res, err := demoProvider.SayHello(context.TODO(), "tc")
if err != nil {
panic(err)
}
gxlog.CInfo("response result: %v\n", res)
user := &User{
Name: "tc",
Age: 18,
}
res, err = demoProvider.SayHello4(context.TODO(), user)
if err != nil {
panic(err)
}
gxlog.CInfo("response result: %v\n", res)
res, err = demoProvider.SayHello5(context.TODO(), user, "tc")
if err != nil {
panic(err)
}
gxlog.CInfo("response result: %v\n", res)
initSignal()
}
Note: With the MethodMapper
, sometimes the mapping relations of method names need to be configured. Otherwise, the results are still methods not found.
For example, the request SayHello
turns into sayHello
in Go because of the configuration dubbo:"sayHello"
. Then, the service provider becomes the sayHello
when configured with MethodMapper
. The sayHello
exposed in Go and Java is lowercase.
The default value of the SPI mechanism in Dubbo is hessian2:
@SPI("hessian2")
public interface Serialization {
}
The default value in Dubbo-go:
func NewDubboCodec(reader *bufio.Reader) *ProtocolCodec {
s, _ := GetSerializerById(constant.S_Hessian2)
return &ProtocolCodec{
reader: reader,
pkgType: 0,
bodyLen: 0,
headerRead: false,
serializer: s.(Serializer),
}
}
You can view the breakpoints on your own. The two languages are nearly the same by comparison. RpcInvocation.getParameterTypesDesc()
is the parameter of the method.
protocol/dubbo/impl/hessian.go:120#marshalRequest
org.apache.dubbo.rpc.protocol.dubbo.DubboCodec#encodeRequestData(org.apache.dubbo.remoting.Channel, org.apache.dubbo.common.serialize.ObjectOutput, java.lang.Object, java.lang.String)
The previous examples were all copied. This time they are typed out, and the following problem occurred.
If your provider is similar to func (p *DemoProvider) SayHello4(ctx context.Context, user User) (string, error)
, the following error will occur:
2020-12-03T12:42:32.834+0800 ERROR getty/listener.go:280 OnMessage panic: reflect: Call using *main.User as type main.User
github.com/apache/dubbo-go/remoting/getty.(*RpcServerHandler).OnMessage.func1
The User
in the parameter needs to be changed to *User
.
SayHello4 func(ctx context.Context, user *User) (string, error)
// or
SayHello4 func(ctx context.Context, user User) (string, error)
Some operations will be performed on pointers during parameter serialization:
t := reflect.TypeOf(v)
if reflect.Ptr == t.Kind() {
t = reflect.TypeOf(reflect.ValueOf(v).Elem())
}
Dubbo-go has three main configuration files:
server.yaml
: The configuration file of service providersclient.yaml
: The configuration file of service consumerslog.yaml
: The log fileIf no configuration is done, there will be:
2021/01/11 15:31:41 [InitLog] warn: log configure file name is nil
2021/01/11 15:31:41 [consumerInit] application configure(consumer) file name is nil
2021/01/11 15:31:41 [providerInit] application configure(provider) file name is nil
This is not going to work properly. If you are a service provider, the server.yaml file must be configured. If you are a service consumer, the client.yaml file must be configured. The application should be both the consumer and the provider. Therefore, both files need to be configured normally.
The following output is generated when the service provider starts normally:
2021-01-11T15:36:55.003+0800 INFO protocol/protocol.go:205 The cached exporter keys is dubbo://:20000/DemoProvider?accesslog=&app.version=1.0.0&application=Demo+Micro+Service&auth=&bean.name=DemoProvider&cluster=failover&environment=dev&execute.limit=&execute.limit.rejected.handler=&group=tc&interface=com.funnycode.DemoService&loadbalance=random&methods.SayHello.loadbalance=random&methods.SayHello.retries=3&methods.SayHello.tps.limit.interval=&methods.SayHello.tps.limit.rate=&methods.SayHello.tps.limit.strategy=&methods.SayHello.weight=0&methods.SayHello4.loadbalance=random&methods.SayHello4.retries=3&methods.SayHello4.tps.limit.interval=&methods.SayHello4.tps.limit.rate=&methods.SayHello4.tps.limit.strategy=&methods.SayHello4.weight=0&methods.SayHello5.loadbalance=random&methods.SayHello5.retries=3&methods.SayHello5.tps.limit.interval=&methods.SayHello5.tps.limit.rate=&methods.SayHello5.tps.limit.strategy=&methods.SayHello5.weight=0&module=dubbogoproxy+tc+client&name=Demo+Micro+Service&organization=dubbogoproxy.com&owner=ZX¶m.sign=®istry.role=3&release=dubbo-golang-1.3.0&retries=&serialization=&service.filter=echo%2Ctoken%2Caccesslog%2Ctps%2Cgeneric_service%2Cexecute%2Cpshutdown&side=provider&ssl-enabled=false×tamp=1610350614&tps.limit.interval=&tps.limit.rate=&tps.limit.rejected.handler=&tps.limit.strategy=&tps.limiter=&version=1.0.0&warmup=100!
2021-01-11T15:36:55.003+0800 INFO dubbo/dubbo_protocol.go:86 Export service: dubbo://:20000/DemoProvider?accesslog=&app.version=1.0.0&application=Demo+Micro+Service&auth=&bean.name=DemoProvider&cluster=failover&environment=dev&execute.limit=&execute.limit.rejected.handler=&group=tc&interface=com.funnycode.DemoService&loadbalance=random&methods.SayHello.loadbalance=random&methods.SayHello.retries=3&methods.SayHello.tps.limit.interval=&methods.SayHello.tps.limit.rate=&methods.SayHello.tps.limit.strategy=&methods.SayHello.weight=0&methods.SayHello4.loadbalance=random&methods.SayHello4.retries=3&methods.SayHello4.tps.limit.interval=&methods.SayHello4.tps.limit.rate=&methods.SayHello4.tps.limit.strategy=&methods.SayHello4.weight=0&methods.SayHello5.loadbalance=random&methods.SayHello5.retries=3&methods.SayHello5.tps.limit.interval=&methods.SayHello5.tps.limit.rate=&methods.SayHello5.tps.limit.strategy=&methods.SayHello5.weight=0&module=dubbogoproxy+tc+client&name=Demo+Micro+Service&organization=dubbogoproxy.com&owner=ZX¶m.sign=®istry.role=3&release=dubbo-golang-1.3.0&retries=&serialization=&service.filter=echo%2Ctoken%2Caccesslog%2Ctps%2Cgeneric_service%2Cexecute%2Cpshutdown&side=provider&ssl-enabled=false×tamp=1610350614&tps.limit.interval=&tps.limit.rate=&tps.limit.rejected.handler=&tps.limit.strategy=&tps.limiter=&version=1.0.0&warmup=100
Thanks for reading! Due to the limited space, this was only an introduction! You are welcome to participate in the Dubbo-go 3.0 construction.
Tiecheng (GithubID: cityiron) is a member of the Dubbo-go community and Dubbo-go-proxy project leader. He is mainly involved in Dubbo-go 1.5 iteration, Dubbo-go 3.0 service routing, and cloud-native. As an expert in Java and Go, he also focuses on cloud-native and microservices.
Fluid with JindoFS: An Acceleration Tool for Alibaba Cloud OSS
507 posts | 48 followers
FollowAlibaba Cloud Native Community - January 26, 2024
Alibaba Cloud Native Community - April 23, 2023
Alibaba Cloud Native Community - March 6, 2023
Aliware - April 13, 2020
Alibaba Cloud Native Community - December 30, 2021
Alibaba Developer - May 20, 2021
507 posts | 48 followers
FollowA platform that provides enterprise-level data modeling services based on machine learning algorithms to quickly meet your needs for data-driven operations.
Learn MoreThis technology can be used to predict the spread of COVID-19 and help decision makers evaluate the impact of various prevention and control measures on the development of the epidemic.
Learn MoreThis solution enables you to rapidly build cost-effective platforms to bring the best education to the world anytime and anywhere.
Learn MoreMulti-source metrics are aggregated to monitor the status of your business and services in real time.
Learn MoreMore Posts by Alibaba Cloud Native Community