Dubbo3.0 introductory tutorial and introduction to new features including modification to dubbo and cross-language calling

Dubbo3.0 introductory tutorial and introduction to new features, including modification to dubbo and cross-language calls.
Here we take the go language as an example.

How to transform an application into a Dubbo application

First, create two new SpringBoot projects, one called consumer and one called provider.

provider project

Project structure
image.png
pom file

<dependencies>
   <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
     <version>2.6.6</version>
   </dependency>
   <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <version>1.18.22</version>
   </dependency>
</dependencies>

ProviderApplication

@SpringBootApplication
public class ProviderApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(ProviderApplication.class);
   }
}

User

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    
    
    private String uid;
    private String username;
}

UserService

@Service
public class UserService {
    
    
    public User getUser(String uid) {
    
    
        User zhouyu = new User(uid, "zhouyu");
        return zhouyu;
   }
}

UserController

@RestController
public class UserController {
    
    
    @Resource
    private UserService userService;
    @GetMapping("/user/{uid}")
    public User getUser(@PathVariable("uid") String uid) {
    
    
        return userService.getUser(uid);
   }
}

application.properties

server.port=8080

consumer project

Project structure
image.png
pom file

<dependencies>
   <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
     <version>2.6.6</version>
   </dependency>
   <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <version>1.18.22</version>
   </dependency>
</dependencies>

ConsumerApplication

@SpringBootApplication
public class ConsumerApplication {
    
    
    @Bean
    public RestTemplate restTemplate(){
    
    
        return new RestTemplate();
   }
    public static void main(String[] args) {
    
    
        SpringApplication.run(ConsumerApplication.class);
   }
}

User

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    
    
    private String uid;
    private String username;
}

UserService

@Service
public class UserService {
    
    
    public User getUser(String uid) {
    
    
        User zhouyu = new User(uid, "zhouyu");
        return zhouyu;
   }
}

OrderService

@Service
public class OrderService {
    
    
    @Resource
    private RestTemplate restTemplate;
    public String createOrder(){
    
    
        User user =
restTemplate.getForObject("http://localhost:8080/user/1", User.class);
        System.out.println("创建订单");
        return user.toString()+" succeeded in creating the order";
   }
}

OrderController

@RestController
public class OrderController {
    
    
    @Resource
    private OrderService orderService;
    @GetMapping("/createOrder")
    public String createOrder() {
    
    
        return orderService.createOrder();
   }
}

application.properties

server.port=8080

The OrderService in the consumer will call the UserService in the provider through RestTemplate.

Transform into Dubbo

To transform into a Dubbo project, there are several things to do:
1. Add dubbo core dependencies
2. Add registration center dependencies to be used
3. Add dependencies to the protocols to be used
4. Configure dubbo-related basic information
5 . Configure the registration center address
6. Configure the protocol used to
add dependencies

<dependency>
   <groupId>org.apache.dubbo</groupId>
   <artifactId>dubbo-spring-boot-starter</artifactId>
   <version>3.0.7</version>
</dependency>
<dependency>
   <groupId>org.apache.dubbo</groupId>
   <artifactId>dubbo-rpc-dubbo</artifactId>
   <version>3.0.7</version>
</dependency>
<dependency>
   <groupId>org.apache.dubbo</groupId>
   <artifactId>dubbo-registry-zookeeper</artifactId>
   <version>3.0.7</version>
</dependency>

Configure properties

dubbo.application.name=provider-application
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.registry.address=zookeeper://127.0.0.1:2181


The User class is used in the transformation service consumer and provider, so you can create a separate maven project to store some classes common to the consumer and provider, add a common module, and transfer the User class to this module
. To transform it into Dubbo, you must first abstract the service and use an interface to represent it.
Like UserService is a service, but we have to define an additional interface. We change the previous UserService to UserServiceImpl, and then define a new interface UserService. This interface represents a service, and UserServiceImpl is the specific implementation of the service. .

public interface UserService {
    
    
    public User getUser(String uid);
}
@DubboService
public class UserServiceImpl implements UserService {
    
    
    public User getUser(String uid) {
    
    
        User zhouyu = new User(uid, "zhouyu");
        return zhouyu;
   }
}

Note: Replace the @Service annotation in Spring with the @DubboService annotation in Dubbo.
Then transfer the UserService interface to the common module and rely on common in the provider.
The provider after the transformation is:
image.png
In fact, the UserController can also be removed. After removing it, the provider will be simpler.

image.png
At this point, you can start the Provider. Be careful to start Zookeeper first (the higher version of Zookeeper will not only occupy 2181 but also 8080 during the startup process , so you can change the provider's port to 8082 )

Open Dubbo

Adding @EnableDubbo(scanBasePackages = “com.zhouyu.service”) to ProviderApplication means that Dubbo will scan @DubboService under a certain path to provide the Dubbo service to the outside world.

@SpringBootApplication
@EnableDubbo(scanBasePackages = "com.zhouyu.service")
public class ProviderApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(ProviderApplication.class);
   }
}

Call Dubbo service

Import dependencies
If you want to call the Dubbo service in the consumer, you must also introduce related dependencies:
1. Import common, mainly import the interface to be called
2. Import dubbo dependencies
3. Import requirements Dependencies of the protocol used
4. Introduce the dependencies of the registration center that need to be used

      	<dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>3.0.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-rpc-dubbo</artifactId>
            <version>3.0.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>3.0.7</version>
        </dependency>
        <dependency>
            <groupId>com.zhouyu</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

The imported service
imports a Dubbo service through the @DubboReference annotation.

@Service
public class OrderService {
    
    
    @DubboReference
    private UserService userService;
    public String createOrder(){
    
    
        User user = userService.getUser("1");
        System.out.println("创建订单");
        return user.toString()+" succeeded in creating the order";
   }
}

This eliminates the need to use RestTemplate.
Configure properties

dubbo.application.name=consumer-application
dubbo.registry.address=zookeeper://127.0.0.1:2181

If
the user does not implement the Serializable interface, an error will be reported.

Summarize

Since then, the transformation of Dubbo has been completed. To summarize:
1. Add pom dependency
2. Configure dubbo application name, protocol, and registration center
3. Define service interface and implementation class
4. Use @DubboService to define a A Dubbo service
5. Use @DubboReference to use a Dubbo service
6. Use @EnableDubbo to enable Dubbo

Introduction to new features of Dubbo3.0

Changes in registration models
In the field of service registration, there are two models on the market, one is application-level registration, and the other is interface-level registration. In Spring Cloud, an application is a microservice, and in Spring Cloud In Dubbo2.7, an interface is a microservice.
Therefore, when Spring Cloud registers a service, it registers the application name, the IP address of the server where the application is located, and the port bound to the application to the registration center. This is equivalent to the key being the application name valueip+port. In Dubbo2.7, the interface name, the IP address of the corresponding application, and the bound port are registered in the registration center. It is equivalent to the key being the interface name and the value being ip+port.
Therefore, in Dubbo2.7, if an application provides 10 Dubbo services, then 10 pairs of keyvalues ​​will be stored in the registration center, while Spring Cloud will only store one pair of keyvalues, so Spring Cloud is the leading application. User-level registration is more suitable.
Therefore, the registration model in Dubbo 3.0 has also been changed to application-level registration, which not only improves efficiency and saves resources, but also lays the foundation for the interoperability of various microservice frameworks by unifying the registration model.

New generation RPC protocol

A new RPC communication protocol - Triple is defined. Triple can be summarized in one sentence: it is an RPC protocol built on HTTP/2, fully compatible with gRPC, and extends richer semantics on this basis. Using the Triple protocol, users will gain the following capabilities

  • It is easier to adapt to gateways and Mesh architectures. The Triple protocol makes it easier for Dubbo to work with various gateways and sidecar components.
  • Multi-language friendly, it is recommended to use Triple protocol with Protobuf, use IDL to define services, and use Protobuf to encode business data.
  • Streaming communication support . Triple protocol supports Request Stream, Response Stream, and Bi-direction Stream. When using Triple protocol for RPC calls, it supports multiple ways to call services, but different methods need to be defined in the service interface. ,

For example:

public interface DemoService {
    
    
    // UNARY
    String sayHello(String name);
    // SERVER_STREAM
    default void sayHelloServerStream(String name, StreamObserver<String>response) {
    
    
   	}
    // CLIENT_STREAM / BI_STREAM
    default StreamObserver<String> sayHelloStream(StreamObserver<String>response) {
    
    
        return response;
   }
}

UNARY unary is the method corresponding to the
normal calling method service implementation class:

// UNARY
@Override
public String sayHello(String name) {
    
    
    return "Hello " + name;
}

Service consumer calling method:

String result = demoService.sayHello("mu");


Methods corresponding to the SERVER_STREAM service implementation class:

// SERVER_STREAM
@Override
public void sayHelloServerStream(String name, StreamObserver<String>
response) {
    
    
    response.onNext(name + " hello");
    response.onNext(name + " world");
    response.onCompleted();
}

Service consumer calling method:

demoService.sayHelloServerStream("zhouyu", new StreamObserver<String>() {
    
    
    @Override
    public void onNext(String data) {
    
    
        // 服务端返回的数据
        System.out.println(data);
   }
    @Override
    public void onError(Throwable throwable) {
    
    }
    @Override
    public void onCompleted() {
    
    
        System.out.println("complete");
   }
});

Service consumer calling method:

StreamObserver<String> streamObserver = demoService.sayHelloStream(new
StreamObserver<String>() {
    
    
     @Override
     public void onNext(String data) {
    
    
         System.out.println("接收到响应数据:"+ data);
     }
     @Override
     public void onError(Throwable throwable) {
    
    }
     @Override
     public void onCompleted() {
    
    
         System.out.println("接收到响应数据完毕");
     }
});
// 发送数据
streamObserver.onNext("request zhouyu hello");
streamObserver.onNext("request zhouyu world");
streamObserver.onCompleted();

BI_STREAM
is the same as CLIENT_STREAM

Dubbo 3.0 cross - language calling

At work, we use Java language to provide a service through Dubbo, and another application (that is, the consumer) wants to use this service. If the consumer application is also developed in Java language, then There is nothing to say, just introduce Dubbo and service interface-related dependencies directly into the consumer application.
However, if the consumer application is not written in Java language, for example, it is implemented through python or go language, then at least two conditions need to be met to call the Dubbo service implemented in Java: 1.
Dubbo It was first implemented in Java language, so now we need a Dubbo framework implemented in go language, which is now dubbo-go, and then introduce dubbo-go in the go project, so that it can be used in the go project Use dubbo in, for example, use go language to expose and use Dubbo services.
2. When we use Java language to develop a Dubbo service, we will abstract the service interface and related classes into a Maven project, which is actually equivalent to a separate jar package. This jar can be It is used by Java projects, but cannot be used by go projects, so how to use the interface defined by the Java language in go projects? It is impossible to use it directly. This problem can only be solved indirectly. In addition to Java language, are there any other technologies that can also define interfaces? And this technology is also supported by both Java and go. This is protobuf.
protobuf
We can define the interface through protobuf, and then compile the interface into a specific language implementation through the protobuf compiler.
Define a userservice.proto file in the provider project, the path is src/main/proto/userservice.proto:

syntax = "proto3";
package api;
option go_package = "./;api";
option java_multiple_files = true;
option java_package = "com.zhouyu";
option java_outer_classname = "UserServiceProto";
service UserService {
    
    
  rpc GetUser (UserRequest) returns (User) {
    
    }
}
// The response message containing the greetings
message UserRequest {
    
    
  string uid = 1;
}
// The response message containing the greetings
message User {
    
    
  string uid = 1;
  string username = 2;
}

It is equivalent to defining a HelloService service and defining a getUser method, which receives parameters of UserRequest type and returns an object of User type.

Compile to Java

Add the relevant maven plug-in to the pom file in the provider project:

<build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.1</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                  
<protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.class
ifier}</protocArtifact>
                  
<outputDirectory>build/generated/source/proto/main/java</outputDirectory
>
                    <clearOutputDirectory>false</clearOutputDirectory>
                    <protocPlugins>
                        <protocPlugin>
                            <id>dubbo</id>
                            <groupId>org.apache.dubbo</groupId>
                            <artifactId>dubbo-compiler</artifactId>
                            <version>0.0.3</version>
                          
<mainClass>org.apache.dubbo.gen.dubbo.Dubbo3Generator</mainClass>
                        </protocPlugin>
                    </protocPlugins>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                          <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                              
<source>build/generated/source/proto/main/java</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

And you can remove the common dependency, and then run the compile of lifecycle in the provider, it will be compiled,
image.png
and the corresponding interface and other information will be compiled. After the compilation is completed, some classes will be generated:
image.png
If Java does not have blue Yes, it
image.png
includes a UserService interface, so our UserServiceImpl can implement this interface:

@DubboService
public class UserServiceImpl implements UserService {
    
    
    public User getUser(UserRequest userRequest) {
    
    
        User user =
User.newBuilder().setUid(userRequest.getUid()).setUsername("zhouyu").buil
d();
        return user;
   }
 
}

For consumers who want to call the UserService service, the same transformation is actually done. They only need to use the same userservice.proto to compile. For example, there is now a consumer in the go language. .

go consumer calls java service

First, create a new go module in IDEA:
image.png
Then copy userservice.proto to go-consumer/proto, and then compile it into the service code corresponding to the go language. However, there is no maven in the go language. Zhongxi can help us compile, but we can only use the native protobuf compiler to compile.
This requires everyone to download and install the protobuf compiler on the machine: protoc
1. Download address: https://github.com/protocolbuffers/protobuf/releases/download/v3.20.1/protoc-3.20.1-win64. zip
2. After decompressing, add protoc-3.20.1-win64\bin to the environment variable
3. Execute protoc --version in cmd. If you can see the version number normally, it means the installation is successful.

You also need to install go:
1. Download address: https://studygolang.com/dl/golang/go1.18.1.windows-amd64.msi
2. Then go to the next step to install
3. In cmd (open a new one cmd window) execute go version. If you can see the version number normally, it means the installation is successful.

Then create a new folder api under go-consumer, enter go-consumer/proto, and run:

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
go get -u github.com/dubbogo/tools/cmd/protoc-gen-go-triple
go install github.com/golang/protobuf/protoc-gen-go
go install github.com/dubbogo/tools/cmd/protoc-gen-go-triple
protoc -I. userservice.proto --go_out=../api --go-triple_out=../api

This will generate a userservice.pb.go file and userservice_triple.pb.go file under go-consumer/api.
If IDEA prompts you to install a plug-in, install it:
image.png
After the installation is complete, the code may report an error. , you can execute the command in the go-consumer directory to download the dependencies:
Then you can write a service consumer in the go language. Create a new consumer.go with the content:

package main
import (
 "context"
 "dubbo.apache.org/dubbo-go/v3/common/logger"
 "dubbo.apache.org/dubbo-go/v3/config"
 _ "dubbo.apache.org/dubbo-go/v3/imports"
 "go-consumer/api"
)
var userServiceImpl = new(api.UserServiceClientImpl)
// export DUBBO_GO_CONFIG_PATH=conf/dubbogo.yml
func main() {
    
    
     config.SetConsumerService(userServiceImpl)
     config.Load()
     logger.Info("start to test dubbo")
     req := &api.UserRequest{
    
    
     	Uid: "1",
     }
     user, err := userServiceImpl.GetUser(context.Background(), req)
     if err != nil {
    
    
     	logger.Error(err)
     }
     logger.Infof("client response result: %v\n", user)
}

Then create a new conf/dubbogo.yml under go-consumer to configure the registration center:

dubbo:
  registries:
    demoZK:
      protocol: zookeeper
      address: 127.0.0.1:2181
  consumer:
    references:
      UserServiceClientImpl:
        protocol: tri
        interface: com.zhouyu.UserService

Note that the protocol configured here is tri, not dubbo. The protocol must also be changed to tri on the provider side:
image.png

Guess you like

Origin blog.csdn.net/weixin_44030143/article/details/130173006
Recommended