JDK 8, Golang >= 1.15, Dubbo 3.0.2, zookeeper enabled,
The transfer structure defined by Go/Java is consistent
proto for Go
// The response message containing the greetings
message User {
string name = 1;
string id = 2;
int32 age = 3;
}
proto for Java
// The response message containing the greetings
message User {
string name = 1;
string id = 2;
int32 age = 3;
}
POJO for Go, please refer to Dubbogo Hessian serialization support document
type User struct {
ID string
name string
Age int32
}
func (u *User) JavaClassName() string {
return "org.apache.dubbo.User"
}
func init(){
hessian.RegisterPOJO(&User{})
}
POJOs for Java
package org.apache.dubbo
public class User {
private String id;
private String name;
private int age;
}
Java requires the same method signature as Go
E.g:
Java Interface
public interface IGreeter {
/**
* <pre>
* Sends a greeting
* </pre>
*/
User sayHello(HelloRequest request);
}
Go client (automatically generated by protoc-gen-go-triple based on proto files)
type GreeterClientImpl struct {
// Sends a greeting
SayHello func(ctx context.Context, in *HelloRequest) (*User, error)
}
Go server (defined by the developer)
type GreeterProvider struct {
api. GreeterProviderBase
}
func (s *GreeterProvider) SayHello(ctx context.Context, in *api.HelloRequest) (*api.User, error) {
logger.Infof("Dubbo3 GreeterProvider get user name = %s\n", in.Name)
return &api.User{Name: "Hello " + in.Name, Id: "12345", Age: 21}, nil
}
Go methods need to comply with Dubbogo 3.0 User Service Interface Definition Specification
Java’s triplet is consistent with the interface configured by Go service/reference
The triplet is configured at the interface level: interface, group, version. **It should be noted that the concept of group and version is the group and vesion of the dubbo interface, which are configured in the properties file of spring cloud when starting the dubbo-java service, not the version that mvn depends on in pom.xml. ** group and version are empty by default, in the dubbo-go framework, you can specify group and version in the corresponding position of service/reference.
E.g:
Java interface full name: com.apache.dubbo.sample.basic.IGreeter, interface version is v1.0.1, group is
Go-client:
references:
GreeterClientImpl:
protocol: tri
interface: com.apache.dubbo.sample.basic.IGreeter # must be compatible with grpc or dubbo-java
group: dubbogo # need to correspond to the server, the default is empty
version: v1.0.1 # needs to correspond to the server, the default is empty
Go-server:
services:
GreeterProvider:
protocol-ids: tripleProtocol
interface: com.apache.dubbo.sample.basic.IGreeter # must be compatible with grpc or dubbo-java
group: dubbogo # need to correspond to the server, the default is empty
version: v1.0.1 # needs to correspond to the server, the default is empty
Reference dubbo-go-samples/helloworld
syntax = "proto3";
option java_package = "org.apache.dubbo.sample.hello";
package helloworld;
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message User {
string name = 1;
string id = 2;
int32 age = 3;
}
The interface description file defines the generated Java class org.apache.dubbo.sample.hello.Helloworld, and the transmission structure HelloRequest and User class included in the class.
Define the service interface:
com.apache.dubbo.sample.basic.IGreeter
package com.apache.dubbo.sample.basic;
// Import the class generated according to PB
import org.apache.dubbo.sample.hello.Helloworld.User;
import org.apache.dubbo.sample.hello.Helloworld.HelloRequest;
public interface IGreeter {
/**
* <pre>
* Sends a greeting
* </pre>
*/
// define the interface
User sayHello(HelloRequest request);
}
Implement the service interface:
IGreeter1Impl.java
package com.apache.dubbo.sample.basic;
import org.apache.dubbo.sample.hello.Helloworld.User;
import org.apache.dubbo.sample.hello.Helloworld.HelloRequest;
public class IGreeter1Impl implements IGreeter {
@Override
public User sayHello(HelloRequest request) {
System.out.println("receiv: " + request);
User usr = User. newBuilder()
.setName("hello " + request.getName())
.setAge(18)
.setId("12345").build();
return usr;
}
}
Use the Dubbo3 framework to start the service
ApiProvider.java
package com.apache.dubbo.sample.basic;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import java.util.concurrent.CountDownLatch;
public class ApiProvider {
public static void main(String[] args) throws InterruptedException {
ServiceConfig<IGreeter> service = new ServiceConfig<>();
service.setInterface(IGreeter.class);
service.setRef(new IGreeter1Impl());
// Use the Triple protocol
service.setProtocol(new ProtocolConfig(CommonConstants.TRIPLE, 50051));
service.setApplication(new ApplicationConfig("demo-provider"));
// Use ZK as the registration center
service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
service. export();
System.out.println("dubbo service started");
new CountDownLatch(1). await();
}
}
Start the service, you can see the following log output, which means that the Java Triple Server started successfully
main INFO bootstrap.DubboBootstrap: [DUBBO] DubboBootstrap has started., dubbo version: 3.0.2, current host: 192.168.0.108
dubbo service started
For the Dubbo service that has been started, if you need to develop its corresponding Go-client, you need to perform the following steps:
Write a proto file adapted to Java
samples_api.proto
syntax = "proto3";
package api; // pacakge name is optional
//necessary
option go_package = "./;api";
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (User) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message User {
string name = 1;
string id = 2;
int32 age = 3;
}
protoc -I .samples_api.proto --triple_out=plugins=triple:.
dubbo:
registries:
demoZK:
protocol: zookeeper
address: 127.0.0.1:2181
consumer:
references:
GreeterClientImpl:
protocol: tri
interface: com.apache.dubbo.sample.basic.IGreeter # must be compatible with grpc or dubbo-java
// Import the generated interface structure
var grpcGreeterImpl = new(api. GreeterClientImpl)
// export DUBBO_GO_CONFIG_PATH=dubbogo.yml
func main() {
config. SetConsumerService(grpcGreeterImpl)
if err := config.Load(); err != nil {
panic(err)
}
time. Sleep(3 * time. Second)
logger.Info("start to test dubbo")
req := &api.HelloRequest{
Name: "Laurence",
}
reply, err := grpcGreeterImpl.SayHello(context.Background(), req)
if err != nil {
logger. Error(err)
}
logger.Infof("client response result: %v\n", reply)
}
cmd/client.go:53 client response result: name:"hello laurence" id:"12345" age:18
-java-server
receiver: name: "laurence"
dubbo:
registries:
demoZK:
protocol: zookeeper
address: 127.0.0.1:2181
protocols:
triple:
name: tri
port: 20000
provider:
services:
GreeterProvider:
interface: com.apache.dubbo.sample.basic.IGreeter # must be compatible with grpc or dubbo-java
type GreeterProvider struct {
api. GreeterProviderBase
}
func (s *GreeterProvider) SayHello(ctx context.Context, in *api.HelloRequest) (*api.User, error) {
logger.Infof("Dubbo3 GreeterProvider get user name = %s\n", in.Name)
return &api.User{Name: "Hello " + in.Name, Id: "12345", Age: 21}, nil
}
// export DUBBO_GO_CONFIG_PATH=dubbogo.yml
func main() {
config. SetProviderService(&GreeterProvider{})
if err := config.Load(); err != nil {
panic(err)
}
select {}
}
Proto file writing and interface generation refer to the introduction of the above java-server
Start Consumer
ApiCnosumer.java
public class ApiConsumer {
public static void main(String[] args) throws InterruptedException, IOException {
ReferenceConfig<IGreeter> ref = new ReferenceConfig<>();
ref. setInterface(IGreeter. class);
ref. setCheck(false);
ref.setProtocol(CommonConstants.TRIPLE);
ref. setLazy(true);
ref. setTimeout(100000);
ref. setApplication(new ApplicationConfig("demo-consumer"));
ref.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
final IGreeter iGreeter = ref. get();
System.out.println("dubbo ref started");
Helloworld.HelloRequest req = Helloworld.HelloRequest.newBuilder().setName("laurence").build();
try {
final Helloworld. User reply = iGreeter. sayHello(req);
TimeUnit. SECONDS. sleep(1);
System.out.println("Reply:" + reply);
} catch (Throwable t) {
t. printStackTrace();
}
System.in.read();
}
}
Reference dubbo-go-samples/rpc/dubbo
package org.apache.dubbo;
// The service interface that needs to be exposed
public interface UserProvider {
User getUser(int usercode);
}
package org.apache.dubbo;
public class User implements Serializable {
private String id;
private String name;
private int age;
private Date time = new Date();
/* ... */
}
UserProviderImpl.java
package org.apache.dubbo;
public class UserProviderImpl implements UserProvider {
public User getUser(int userCode) {
return new User(String. valueOf(userCode), "userCode get", 48);
}
}
Provider.java
package org.apache.dubbo;
// use when config by API
/*
import java.util.concurrent.CountDownLatch;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
*/
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Provider {
// main function, config from spring boot
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo.provider.xml"});
context. start();
System.in.read(); // press any key to exit
}
// config by API
// public static void startComplexService() throws InterruptedException {
// ServiceConfig<ComplexProvider> service = new ServiceConfig<>();
// service.setInterface(ComplexProvider.class);
// service. setRef(new ComplexProviderImpl());
// service.setProtocol(new ProtocolConfig(CommonConstants.DUBBO_PROTOCOL, 20001));
// service.setApplication(new ApplicationConfig("demo-provider"));
// service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
// service. export();
// System.out.println("dubbo service started");
// new CountDownLatch(1). await();
// }
}
Configure Dubbo parameters through Spring
Resources/META-INF.spring/dubbo.provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed under the Apache License, Version 2.0 (the "License");
You may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- application name -->
<dubbo:application name="user-info-server"/>
<!-- which local registry to connect to -->
<dubbo:registry id="dubbogo" address="zookeeper://127.0.0.1:2181" />
<!-- Use dubbo protocol to expose services on port 20880 -->
<dubbo:protocol id="dubbo" name="dubbo" host="127.0.0.1" port="20010" />
<!-- Declare the service interface that needs to be exposed -->
<dubbo:service id="aaa" registry="dubbogo" timeout="3000" interface="org.apache.dubbo.UserProvider" ref="demoService"/>
<dubbo:service id="bbb" registry="dubbogo" timeout="3000" interface="org.apache.dubbo.UserProvider" ref="otherService" version="2.0"/>
<dubbo:service id="ccc" registry="dubbogo" timeout="3000" interface="org.apache.dubbo.UserProvider" ref="otherService" group="as" version="2.0"/>
<bean id="demoService" class="org.apache.dubbo.UserProviderImpl" />
<bean id="otherService" class="org.apache.dubbo.UserProviderAnotherImpl"/>
</beans>
Start the Provider class, and you can see the following log output, which means that the Dubbo Server has started successfully
[DUBBO] Dubbo Bootstrap is ready., dubbo version: 2.7.7, current host: 127.0.0.1
[DUBBO] Dubbo Bootstrap has started., dubbo version: 2.7.7, current host: 127.0.0.1
For the Dubbo service that has been started, if you need to develop its corresponding Go-client, you need to perform the following steps:
import(
hessian "github.com/apache/dubbo-go-hessian2"
)
// The field needs to correspond to the Java side, with the first letter capitalized
type User struct {
ID string
name string
Age int32
Time time. Time
}
func (u *User) JavaClassName() string {
return "org.apache.dubbo.User" // needs to correspond to the User class name on the Java side
}
func init(){
hessian.RegisterPOJO(&pkg.User{}) // register POJO
}
Write a client stub class that is consistent with the Java side, and its interface method needs to correspond to the Java side
It is stipulated that the first parameter must be context.Context, and the last return value must be error
import(
"dubbo.apache.org/dubbo-go/v3/config"
)
var (
userProvider = &pkg. UserProvider{}
)
// UserProvider client stub class
type UserProvider struct {
// The dubbo label is used to adapt the uppercase method name of the go side client -> the lowercase method name of the java side, only the dubbo protocol client needs to use it
GetUser func(ctx context.Context, req int32) (*User, error) `dubbo:"getUser"`
}
func init(){
// Register the client stub class to the framework, and instantiate the client interface pointer userProvider
config. SetConsumerService(userProvider)
}
dubbo:
registries:
demoZK: # Define the registration center ID
protocol: zookeeper
timeout: 3s
address: 127.0.0.1:2181
consumer:
references:
UserProvider: # stub class name
protocol: dubbo # dubbo protocol, default hessian2 serialization method
interface: org.apache.dubbo.UserProvider # The interface needs to correspond to the Java side
logger:
zap-config:
level: info # log level
Or use Triple + Hessian2 to serialize the request Server. If this example communicates with Java Server, Triple cannot be used.
dubbo:
registries:
demoZK:
protocol: zookeeper
timeout: 3s
address: 127.0.0.1:2181
consumer:
references:
UserProvider:
protocol: tri # triple protocol
serialization: hessian2 # serialization method hessian2, triple protocol defaults to pb serialization, if not configured, an error will be reported
interface: org.apache.dubbo.UserProvider
logger:
zap-config:
level: info
func main(){
config. Load()
var i int32 = 1
user, err := userProvider. GetUser2(context. TODO(), i)
if err != nil {
panic(err)
}
logger.Infof("response result: %v", user)
}
response result: User{ID:1, Name:userCode get, Age:48, Time:2021-10-21 20:25:26.009 +0800 CST}
dubbo:
registries:
demoZK:
protocol: zookeeper
address: 127.0.0.1:2181
protocols:
dubbo:
name: dubbo
port: 20000
provider:
services:
UserProvider:
interface: org.apache.dubbo.UserProvider
logger:
zap-config:
level: info
type UserProvider struct {
}
func (u *UserProvider) GetUser(ctx context.Context, req int32) (*User, error) {
var err error
logger.Infof("req:%#v", req)
user := &User{}
user.ID = strconv.Itoa(int(req))
return user, err
}
// MethodMapper defines method name mapping, from Go method name to Java lowercase method name, only dubbo protocol service interface needs to use
func (s *UserProvider) MethodMapper() map[string]string {
return map[string]string{
"GetUser": "getUser",
}
}
func init(){
config.SetProviderService(&pkg.UserProvider{})
}
// export DUBBO_GO_CONFIG_PATH=dubbogo.yml
func main() {
if err := config.Load(); err != nil {
panic(err)
}
select {}
}
Java client Spring configuration
resources/META-INF.spring/dubbo.consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed under the Apache License, Version 2.0 (the "License");
You may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- Consumer application name, used to calculate dependencies, not a matching condition, do not be the same as the provider -->
<dubbo:application name="user-info-client" />
<!-- which local registry to connect to -->
<dubbo:registry id="dubbogo" address="zookeeper://127.0.0.1:2181" />
<!-- dubbo.registry.address from dubbo.properties -->
<!-- dubbo:registry address="${dubbo.registry.address}" / -->
<!-- Use dubbo protocol to expose services on port 20880 -->
<dubbo:protocol id="dubbo" name="dubbo" />
<!-- Declare the service interface that needs to be used -->
<dubbo:reference registry="dubbogo" check="false" id="userProvider" protocol="dubbo" interface="org.apache.dubbo.UserProvider">
<!--<dubbo:parameter key="heartbeat" value="10000"/ -->
</dubbo:reference>
<dubbo:reference registry="dubbogo" check="false" id="userProvider1" protocol="dubbo" version="2.0" interface="org.apache.dubbo.UserProvider">
</dubbo:reference>
<dubbo:reference registry="dubbogo" check="false" id="userProvider2" protocol="dubbo" version="2.0" group="as" interface="org.apache.dubbo.UserProvider">
</dubbo:reference>
</beans>
Initiate the call
public class Consumer {
// Define a private variable (Required in Spring)
private static UserProvider userProvider;
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo.consumer.xml"});
userProvider = (UserProvider)context. getBean("userProvider");
testGetUser();
}
private static void testGetUser() throws Exception {
User user = userProvider. getUser(1);
System.out.println(user.getId());
}
}