Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 79 additions & 8 deletions async/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,95 @@
[[English](README.md) | [中文](README_zh.md)]

This sample showcases how to invoke Dubbo services asynchronously with the new
`client`/`server` APIs over the Triple protocol. The client issues both a regular
async call (`GetUser`) and a fire-and-forget style call (`SayHello`) while the
server uses Protobuf serialization to serve Triple requests. Note: This sample
demonstrates the non-blocking nature of async calls; the response can be obtained
through the return value.
`client`/`server` APIs over the Triple protocol. It demonstrates both Go-to-Go
and Java-to-Go async interoperability.

## Run the sample
## Features

1. **Start the provider**
- **Go Client & Server**: Async calls using `client.WithAsync()`
- **Java Client**: Async calls using `CompletableFuture` API
- **Java Server**: Async service implementation with `CompletableFuture`
- **Interoperability**: Java client can call Go server, Go client can call Java server

## Run Go to Go sample

1. **Start the Go server**

```bash
go run ./async/go-server/cmd/main.go
```

2. **Start the consumer**
2. **Start the Go client** (connects to Go server by default)

```bash
go run ./async/go-client/cmd/main.go
```

The client prints "non-blocking before async callback resp: do something ... " and "test end" logs, demonstrating the non-blocking nature of async calls.

## Run Java-Go interoperability sample

This demonstrates **cross-language async calls**:

- **Go client****Java server**
- **Java client****Go server**

### Prerequisites

- Java 11 or higher
- Maven 3.6+

### Build Java modules

From the `async` directory:

```bash
mvn clean compile
```

### Test: Go client → Java server

1. **Modify the Go client URL** in `go-client/cmd/main.go`:

```go
client.WithClientURL("tri://127.0.0.1:50051"),
```
Comment on lines +54 to +58
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states that the Go client can be modified to connect to the Java server by changing the URL to "tri://127.0.0.1:50051", but the actual Go client code in go-client/cmd/main.go currently hardcodes "tri://127.0.0.1:20000". The README should clarify that this is the default configuration for Go-to-Go communication, and users need to manually change this line in the code to test Java interoperability as described.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MrSibe Please consider copilot's suggestion.


2. **Start the Java server** (port 50051)

```bash
cd java-server
./run.sh
```

3. **Start the Go client**

```bash
go run ./async/go-client/cmd/main.go
```

The Go client will send async requests to the Java server and print "non-blocking before async callback resp: do something ... " logs.

### Test: Java client → Go server

1. **Start the Go server** (port 20000)

```bash
go run ./async/go-server/cmd/main.go
```

2. **Start the Java client**

```bash
cd java-client
./run.sh
```

The Java client will send async requests to the Go server using `CompletableFuture` callbacks.

## Port allocation

- **Go Server**: 20000
- **Java Server**: 50051

Both servers can run simultaneously without conflicts.
88 changes: 81 additions & 7 deletions async/README_zh.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,96 @@
# 异步 RPC Dubbo for Dubbo-go
# Dubbo-go 异步 RPC

[[English](README.md) | [中文](README_zh.md)]

该示例基于新版 `client` / `server` API 展示 Triple 协议下的 Dubbo 异步调用:客户端
在发送 `GetUser` 请求后可以继续执行其他逻辑(非阻塞调用),同时也包含 `SayHello` 的单向调用示例。注意:本示例仅演示异步调用的非阻塞特性,实际响应可通过返回值获取
本示例展示了如何使用新的 `client`/`server` API 通过 Triple 协议异步调用 Dubbo 服务。
演示了 Go 和 Java 之间的异步互操作

## 运行步骤
## 功能特性

1. **启动服务端**
- **Go 客户端和服务端**: 使用 `client.WithAsync()` 实现异步调用
- **Java 客户端**: 使用 `CompletableFuture` API 实现异步调用
- **Java 服务端**: 使用 `CompletableFuture` 实现异步服务
- **互操作性**: Java 客户端可调用 Go 服务端,Go 客户端可调用 Java 服务端

## 运行 Go 到 Go 示例

1. **启动 Go 服务端**

```bash
go run ./async/go-server/cmd/main.go
```

2. **启动客户端**
2. **启动 Go 客户端**(默认连接 Go 服务端)

```bash
go run ./async/go-client/cmd/main.go
```

客户端会打印 "non-blocking before async callback resp: do something ... " 和 "test end" 日志,演示异步调用的非阻塞特性。

## 运行 Java-Go 互操作示例

演示**跨语言异步调用**

- **Go 客户端****Java 服务端**
- **Java 客户端****Go 服务端**

### 前置条件

- Java 11 或更高版本
- Maven 3.6+

### 构建 Java 模块

`async` 目录下执行:

```bash
mvn clean compile
```

### 测试:Go 客户端 → Java 服务端

1. **修改 Go 客户端 URL**,在 `go-client/cmd/main.go` 中修改:

```go
Comment on lines +53 to +55
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states that the Go client can be modified to connect to the Java server by changing the URL to "tri://127.0.0.1:50051", but the actual Go client code in go-client/cmd/main.go currently hardcodes "tri://127.0.0.1:20000". The README should clarify that this is the default configuration for Go-to-Go communication, and users need to manually change this line in the code to test Java interoperability as described.

Suggested change
1. **修改 Go 客户端 URL**,在 `go-client/cmd/main.go` 中修改:
```go
1. **修改 Go 客户端 URL**。Go 客户端默认配置为连接 Go 服务端(端口 `20000`),在 `go-client/cmd/main.go` 中通常如下:
```go
client.WithClientURL("tri://127.0.0.1:20000"),

为了让 Go 客户端连接到 Java 服务端,请将上述行修改为:

Copilot uses AI. Check for mistakes.
client.WithClientURL("tri://127.0.0.1:50051"),
```

2. **启动 Java 服务端**(端口 50051)

```bash
cd java-server
./run.sh
```

3. **启动 Go 客户端**

```bash
go run ./async/go-client/cmd/main.go
```

客户端会打印"non-blocking before async callback resp: do something ... "和"test end"日志, 演示异步调用的非阻塞特性。
Go 客户端会向 Java 服务端发送异步请求,并打印 "non-blocking before async callback resp: do something ... " 日志。

### 测试:Java 客户端 → Go 服务端

1. **启动 Go 服务端**(端口 20000)

```bash
go run ./async/go-server/cmd/main.go
```

2. **启动 Java 客户端**

```bash
cd java-client
./run.sh
```

Java 客户端会向 Go 服务端发送异步请求,使用 `CompletableFuture` 回调处理响应。

## 端口分配

- **Go 服务端**: 20000
- **Java 服务端**: 50051

两个服务端可以同时运行,不会产生端口冲突。
79 changes: 79 additions & 0 deletions async/java-client/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.dubbo.samples</groupId>
<artifactId>async-parent</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

<modelVersion>4.0.0</modelVersion>
<artifactId>java-async-client</artifactId>
<name>java-async-client</name>
<description>Java client module for async RPC sample</description>

<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/protobuf/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>org.apache.dubbo.samples.async.JavaAsyncClient</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
23 changes: 23 additions & 0 deletions async/java-client/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#

echo "Building Java async client..."
mvn -q clean package

echo "Starting Java async client..."
mvn -q exec:java -Dexec.mainClass=org.apache.dubbo.samples.async.JavaAsyncClient
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/

package org.apache.dubbo.samples.async;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.samples.async.proto.*;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;

public class JavaAsyncClient {

public static void main(String[] args) throws Exception {
ReferenceConfig<UserProvider> userProviderRef = new ReferenceConfig<>();
userProviderRef.setInterface(UserProvider.class);
userProviderRef.setUrl("tri://127.0.0.1:20000");

ReferenceConfig<UserProviderV2> userProviderV2Ref = new ReferenceConfig<>();
userProviderV2Ref.setInterface(UserProviderV2.class);
userProviderV2Ref.setUrl("tri://127.0.0.1:20000");

DubboBootstrap bootstrap = DubboBootstrap.getInstance();
bootstrap.application(new ApplicationConfig("java-async-client"))
.reference(userProviderRef)
.reference(userProviderV2Ref)
.start();

UserProvider userProvider = userProviderRef.get();
UserProviderV2 userProviderV2 = userProviderV2Ref.get();

CountDownLatch latch1 = new CountDownLatch(1);
GetUserRequest getUserReq = GetUserRequest.newBuilder().setId("003").build();
CompletableFuture<GetUserResponse> future1 = userProvider.getUserAsync(getUserReq);

System.out.println("async request sent, doing other work...");

future1.whenComplete((response, throwable) -> {
if (throwable != null) {
System.err.println("error: " + throwable.getMessage());
} else {
User user = response.getUser();
System.out.println("received user: " + user.getName() + ", age: " + user.getAge());
}
latch1.countDown();
});

CountDownLatch latch2 = new CountDownLatch(1);
SayHelloRequest sayHelloReq = SayHelloRequest.newBuilder().setUserId("002").build();
CompletableFuture<SayHelloResponse> future2 = userProviderV2.sayHelloAsync(sayHelloReq);

future2.whenComplete((response, throwable) -> {
if (throwable == null) {
System.out.println("sayHello completed");
}
latch2.countDown();
});
Comment on lines +68 to +73
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling for the second async call (sayHelloAsync) is inconsistent with the first. The callback at line 68-73 only checks if throwable is null and prints "sayHello completed", but it doesn't handle or log the error case when throwable is not null. This means errors in the SayHello call will be silently ignored. Consider adding error handling similar to the first callback to ensure errors are properly logged.

Copilot uses AI. Check for mistakes.

latch1.await();
latch2.await();
bootstrap.stop();
}
}
Loading
Loading