前言
平時工作中用過dubbo和grpc, 也看過一些性能測評文章, 大致看出grpc一開始(2016年前)的性能貌似是dubbo的2/3左右
但是2017年的一篇博客看出grpc已經開始超越dubbo了,自己也一直很想親手試試,畢竟grpc的適用場景更多,dubbo的
編碼友好性更好。兩個都是好的框架。
GRPC 環境
直接git clone https://github.com/grpc/grpc-java
進入裏面的examples, 有
grpc-java/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
grpc-java/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
讀裏面的readme
然後改造了下 HelloWorldClient.java
/*
* Copyright 2015 The gRPC Authors
*
* 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.
*/
package io.grpc.examples.helloworld;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.helloworld.HelloRequest.Builder;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A simple client that requests a greeting from the {@link HelloWorldServer}.
*/
public class HelloWorldClient {
private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName());
private final ManagedChannel channel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
private final Long testScale = 1000000L;
/** Construct client connecting to HelloWorld server at {@code host:port}. */
public HelloWorldClient(String host, int port) {
this(ManagedChannelBuilder.forAddress(host, port)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext()
.build());
}
/** Construct client for accessing HelloWorld server using the existing channel. */
HelloWorldClient(ManagedChannel channel) {
this.channel = channel;
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
/** Say hello to server. */
public void greet(String name) {
logger.info("Will try to greet " + name + " ...");
Long start = Instant.now().getEpochSecond();
HelloReply response;
HelloRequestOrBuilder request = HelloRequest.newBuilder().setName(name);
try {
for(int idx = 0 ; idx <= testScale; idx ++){
((Builder) request).setName(String.format("%s:%d", name, idx));
response = blockingStub.sayHello(((Builder) request).build());
System.out.println(String.format("Greeting: %s" , response.getMessage()));
((Builder) request).clear();
}
} catch (StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
return;
}
Long durTime = Instant.now().getEpochSecond() - start;
System.out.println(String.format("spend time: %d can handle %d per second", durTime,
testScale/durTime));
}
/**
* Greet server. If provided, the first element of {@code args} is the name to use in the
* greeting.
*/
public static void main(String[] args) throws Exception {
HelloWorldClient client = new HelloWorldClient("localhost", 50051);
try {
/* Access a service running on the local machine on port 50051 */
String user = "world";
if (args.length > 0) {
user = args[0]; /* Use the arg as the name to greet if provided */
}
client.greet(user);
} finally {
client.shutdown();
}
}
}
打算循環1000000次調用看平均調用表現
用maven去啓動
mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldServer
mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldClient
測出性能大致是
spend time: 126 can handle 7936 per second
然後打算去看一下dubbo的表現了
DUBBO環境
zookeeper 啓動在本地
zkServer.sh start
啓動dubber service server
dubbo service server
@Service(version = "1.0.0")
public class HelloServiceImpl implements HelloService {
@Override
public String SayHello(String name) {
return "Hello , "+name;
}
}
dubbo service client
@RestController
public class HelloController {
private final Long testScale = 1000000L;
@Reference(version = "1.0.0")
HelloService helloService;
@GetMapping("sayHello")
public String sayHello( String name){
name = " world";
Long now = Instant.now().getEpochSecond();
for(int idx = 0; idx < testScale; idx++){
System.out.println( helloService.SayHello(String.format("%s:%d",name,idx)));
}
Long duration = Instant.now().getEpochSecond() - now;
System.out.println(String.format("can handle %d per second", testScale/duration));
return String.format("can handle %d per second", testScale/duration);
}
}
運行結果
can handle 12987 per second
結論
看上去貌似還是dubbo快一點
但是直覺grpc經過多年改進不可能還是停留在這個表現上, 懷疑是maven啓動java進程導致一些performance 的效率低
轉折
有了這個懷疑,就動手直接在ide 裏面啓動client
輸出結果
spend time: 83 can handle 12048 per second
在這裏插入圖片描述
最後結果
經過幾年改進, grpc在性能上已經和dubbo不相上下了, 但是grpc的擴展性,多語言可支持特點導致選型方面的優勢是無可替代的。