rpc框架之 grpc vs dubbo 性能比拼

前言

平时工作中用过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

输出结果

扫描二维码关注公众号,回复: 8724117 查看本文章
spend time: 83 can handle 12048 per second

ide里面启动HelloWorldClient.java测试grpc
在这里插入图片描述

最后结果

经过几年改进, grpc在性能上已经和dubbo不相上下了, 但是grpc的扩展性,多语言可支持特点导致选型方面的优势是无可替代的。

发布了14 篇原创文章 · 获赞 3 · 访问量 8138

猜你喜欢

转载自blog.csdn.net/magasea/article/details/89397641