Salmon的全栈知识 Salmon的全栈知识
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • SpringCloud Gateway
  • Apollo
  • Eureka
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • SpringCloud Gateway
  • Apollo
  • Eureka
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Dubbo2.0

    • 基础知识
    • dubbo配置
    • 高可用
    • dubbo原理
  • Dubbo3.0

    • 如何将一个应用改造为一个Dubbo应用
    • Dubbo.3.0新特性介绍
    • Dubbo3.0跨语言调用
      • 1. 前言
      • 2. protobuf
        • 编译成Java
      • 3. go消费者调⽤java服务
  • 《Dubbo》笔记
  • Dubbo3.0
Salmon
2024-04-29
目录

Dubbo3.0跨语言调用

# 1. 前言

在⼯作中,我们⽤ Java 语⾔通过 Dubbo 提供了⼀个服务,另外⼀个应⽤(也就是消费者)想要使⽤这个服务,如果消费者应⽤也是⽤ Java 语⾔开发的,那没什么好说的,直接在消费者应⽤引⼊ Dubbo 和服务接⼝相关的依赖即可。

但是,如果消费者应⽤不是⽤ Java 语⾔写的呢,⽐如是通过 python 或者 go 语⾔实现的,那就⾄少需要满⾜两个条件才能调⽤ Java 实现的 Dubbo 服务:

  1. Dubbo ⼀开始是⽤ Java 语⾔实现的,那现在就需要⼀个 go 语⾔实现的 Dubbo 框架,也就是现在的 dubbo-go,然后在go项⽬中引⼊ dubbo-go,从⽽可以在 go 项⽬中使⽤ dubbo,⽐如使⽤ go 语⾔去暴露和使⽤ Dubbo 服务。

  2. 我们在使⽤ Java 语⾔开发⼀个 Dubbo 服务时,会把服务接⼝和相关类,单独抽象成为⼀个 Maven 项⽬,实际上就相当于⼀个单独的 jar 包,这个 jar 能被 Java 项⽬所使⽤,但不能被 go 项⽬所使⽤,所以 go 项⽬中该如何使⽤ Java 语⾔所定义的接⼝呢?直接⽤是不太可能的,只能通过间接的⽅式来解决这个问题,除开 Java 语⾔之外,那有没有其他技术也能定义接⼝呢?并且该技术也是 Java 和 go 都⽀持,这就是 protobuf。

# 2. protobuf

我们可以通过 protobuf 来定义接⼝,然后通过 protobuf 的编译器将接⼝编译为特定语⾔的实现。

在 provider 项⽬中定义⼀个 userservice.proto ⽂件,路径为 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;
}

相当于定义了⼀个 HelloService 服务,并且定义了⼀个 getUser ⽅法,接收 UserRequest 类型的参数,返回 User 类型的对象。

# 编译成Java

在provider项⽬中的pom⽂件中添加相关maven插件:

<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.classifier}</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>

并且可以把 common 依赖去掉,然后运⾏ provider 中 lifecycle 的 compile,就会进⾏编译了

image-20240430175154567

并且会编译出对应的接⼝等信息,编译完成后,会⽣成⼀些类:

image-20240430175215661

如果Java没有蓝⾊的,就

image-20240430175239304

其中就包括了⼀个 UserService 接⼝,所以我们的 UserServiceImpl 就可以实现这个接⼝了:

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

⽽对于想要调⽤ UserService 服务的消费者⽽⾔,其实也是⼀样的改造,只需要使⽤同⼀份 userservice.proto 进⾏编译就可以了,⽐如现在有⼀个 go 语⾔的消费者。

# 3. go消费者调⽤java服务

⾸先,在IDEA中新建⼀个go模块:

image-20240430175455118

然后把 userservice.proto 复制到 go-consumer/proto 下,然后进⾏编译,编译成为go语⾔对应的服务代码,只不过go语⾔中没有 maven 这种东⻄可以帮助我们编译,我们只能⽤原⽣的 protobuf 的编译器进⾏编译。

这就需要⼤家在机器上下载、安装protobuf的编译器:protoc

  1. 下载地址:https://github.com/protocolbuffers/protobuf/releases/download/v3.20.1/protoc-3.20.1-win64.zip (opens new window)
  2. 解压之后,把 protoc-3.20.1-win64\bin 添加到环境变量中去
  3. 在 cmd 中执⾏ protoc --version,能正常看到版本号即表示安装成功

另外还需要安装go:

  1. 下载地址:https://studygolang.com/dl/golang/go1.18.1.windows-amd64.msi (opens new window)

  2. 然后直接下⼀步安装

  3. 在cmd中(新开⼀个cmd窗⼝)执⾏go version,能正常看到版本号即表示安装成功

然后在 go-consumer 下新建⽂件夹 api,进⼊到 go-consumer/proto 下,运⾏:

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

这样就会在 go-consumer/api下⽣成⼀个 userservice.pb.go ⽂件和 userservice_triple.pb.go ⽂件

如果IDEA中提示要安装插件,就安装⼀下:

image-20240430175909735

安装完之后,代码可能会报错,可以在 go-consumer ⽬录下执⾏命令下载依赖:

go mod tidy

然后就可以写go语⾔的服务消费者了,新建⼀个 consumer.go,内容为:

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)
}

然后在 go-consumer 下新建 conf/dubbogo.yml,⽤来配置注册中⼼:

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

注意这⾥配置的协议为 tri,⽽不是dubbo,在provider端也得把协议改为 tri:

image-20240430180231944

然后就可以运⾏ consumer.go 了,只不过需要在 environment 中添加⼀个参数:

image-20240430180251739

运⾏成功:

image-20240430180320423

上次更新: 2025/07/23, 07:31:13
Dubbo.3.0新特性介绍

← Dubbo.3.0新特性介绍

Theme by Vdoing | Copyright © 2022-2025 Salmon's Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式