实测Tengine开源的Dubbo功能

捉虫大师 等级 730 0 0

本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。

背景

  • Tengine是阿里巴巴基于Nginx开发并开源的Web服务器,它继承了Nginx所有的功能和特性,并在其基础上做了大量的扩展和增强,其中像动态模块加载,四层负载均衡,reuseport支持等能力,都逐渐被Nginx官方吸收引用。Tengine在开源以后大受欢迎,成为了Nginx最好的替代品之一,官方网站(http://tengine.taobao.org/)。

  • Dubbo是阿里巴巴开源的一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

2019年9月,Tengine 2.3.2版本发布了dubbo_pass模块,支持HTTP协议到Dubbo协议的转换。Release页面如下:

https://github.com/alibaba/tengine/releases/tag/2.3.2

意义

《Gateway技术革命 - Tengine开源Dubbo功能》对Tengine支持Dubbo协议的意义讲的比较清楚,总结有如下几点:

  • 架构优化:减少一层转发,降低系统复杂度;
  • 性能优势:文中给出数据,“Tengine直接支持Dubbo的架构在CPU消耗和RT上的表现在不同场景下,有28%-73%不等的性能优势”

实测

Tengine环境搭建

这里我用centos的基础镜像搭了一套Tengine环境,简单说明一下步骤:

  • 进入容器,创建工作目录
    mkdir -p /home/roshi && cd /home/roshi/
  • 下载相关源码并解压
    wget https://github.com/alibaba/tengine/archive/2.3.2.zip
    unzip 2.3.2.zip && cd tengine-2.3.2/
    

wget https://ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz tar xvf pcre-8.43.tar.gz

wget https://www.openssl.org/source/openssl-1.0.2s.tar.gz tar xvf openssl-1.0.2s.tar.gz

wget http://www.zlib.net/zlib-1.2.11.tar.gz tar xvf zlib-1.2.11.tar.gz

- 安装相关依赖

yum install gcc yum install gcc-c++ yum -y install gcc automake autoconf libtool make

- 编译

./configure --add-module=./modules/mod_dubbo --add-module=./modules/ngx_multi_upstream_module --add-module=./modules/mod_config --with-pcre=./pcre-8.43/ --with-openssl=./openssl-1.0.2s/ --with-zlib=./zlib-1.2.11 make && make install

- 启动

/usr/local/nginx/sbin/nginx


### Dubbo例子

这里要提一下之前在[《dubbo应用级服务发现初体验》](../dubbo应用级服务发现初体验/dubbo应用级服务发现初体验.md)中提到的快速搭建Dubbo调试环境的方法:

- git clone https://github.com/apache/dubbo.git
- 使用/dubbo-demo目录下的例子,本文使用/dubbo-demo/dubbo-demo-api-provider下的例子

由于Tengine有限制,接口的出参和入参必须是`Map<String, Object>`,所以需要对例子进行修改:

- DemoService

public interface DemoService {

String sayHello(String name);

default Map<String, Object> testTengine(Map<String, Object> args) {
    return null;
}

default CompletableFuture<String> sayHelloAsync(String name) {
    return CompletableFuture.completedFuture(sayHello(name));
}

}

- DemoServiceImpl.java

public class DemoServiceImpl implements DemoService { private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);

@Override
public String sayHello(String name) {
    logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
    return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}

@Override
public Map<String, Object> testTengine(Map<String, Object> args) {
    Map<String, Object> res = new HashMap<>();
    res.put("body", "hello tengine dubbo\n");
    res.put("status", "200");
    System.out.println("testTengine");
    return res;
}

@Override
public CompletableFuture<String> sayHelloAsync(String name) {
    return null;
}

}

为了更好的测试多个provider的情况,可以用同一份代码,在不同的端口起多个服务。

### 修改Tengine配置
- vi /usr/local/nginx/conf/nginx.conf

worker_processes 1;

events { worker_connections 1024; }

http { include mime.types; default_type application/octet-stream;

sendfile        on;

server {
    listen       8080;
    server_name  localhost;

    #pass the Dubbo to Dubbo Provider server listening on 127.0.0.1:20880
    location / {
        dubbo_pass_all_headers on;
        # dubbo_pass_set args $args;
        dubbo_pass_set args hello;
        dubbo_pass_set uri $uri;
        dubbo_pass_set method $request_method;

        dubbo_pass org.apache.dubbo.demo.DemoService 0.0.0 testTengine dubbo_backend;
    }
}


#pass the Dubbo to Dubbo Provider server listening on 127.0.0.1:20880
upstream dubbo_backend {
    multi 1;
    server host.docker.internal:20880;
    server host.docker.internal:20881;
}

}

- 修改配置后reload配置,使其生效

/usr/local/nginx/sbin/nginx -s reload


### 测试

使用如下命令测试

curl -X POST http://127.0.0.1:8080/dubbo -i -d "hello=roshi"


![](https://img-hello-world.oss-cn-beijing.aliyuncs.com/a1b4d7590815c5d277119c70acf53e01.jpeg)


看一下传参情况


![](https://img-hello-world.oss-cn-beijing.aliyuncs.com/7bf6d558f8455e23573e35f88a6c3275.jpeg)

### 总结

经过测试,总结以下几点:

- 接口的出参入参固定为Map<String, Object>,否则会报错
- 使用body传参,到Dubbo侧是byte[],还需要解析
- 可以控制返回的body和http状态码,其中返回的body可以是String,也可以是byte[]类型,状态码是String类型
- 具备Tengine原生的负载均衡算法
- 具备故障摘除,Tegine与Dubbo Provider会建立长连接,断开则摘除
- 未实现version、group分组功能,文档中的version实测没有任何效果

# 最后
正如[《Gateway技术革命 - Tengine开源Dubbo功能》](https://mp.weixin.qq.com/s/NoJlPG4yxwTfpdr8WaS7oA)文中所说,Tengine只是完成了作为Dubbo Consumer的协议支持,像服务发现、自定义接口、服务分组、容错降级等其他功能暂未实现,暂时还离生产有些距离。

最后吐槽一下Tengine官网的文档

![](https://img-hello-world.oss-cn-beijing.aliyuncs.com/04eee0a4f28591b2f14c2e981d95c225.jpeg)

# 参考
- 官方文档 http://tengine.taobao.org/document_cn/ngx_http_dubbo_module_cn.html
- 官方例子 https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-tengine

---


> 搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。


![](https://img-hello-world.oss-cn-beijing.aliyuncs.com/0d3289b7511912eb78df37b7d579fb29.jpeg)
收藏
评论区

相关推荐

升级dubbo,小心default.version
上周遇到个关于升级dubbo 2.6 到2.7的兼容性问题,差点造成线上故障,这里记录下,也给大家提个醒。 问题回放有一个接口的提供方(dubbo 2.6.6)这么配置接口的版本号xml<dubbo:provider version"1.0.0"/消费方(也是dubbo 2.6.6)的reference这么配置xml<dubbo:
几个你不知道的dubbo注册中心细节
你会正确配置backup地址吗?在配置dubbo注册中心时,一般会这样写dubbo.registry.protocolzookeeperdubbo.registry.address127.0.0.1:2181也会简单地写成dubbo.registry.addresszookeeper://127.0.0.1:2181当z
聊聊dubbo协议
协议协议通俗易懂地解释就是通信双方需要遵循的约定。我们了解的常见的网络传输协议有tcp、udp、http等。再到我们常用的基础组件,一般来说client端与server端也有相应的协议,如redis、mysql、zookeeper等都是各自约定的私有协议,同样今天标题中的dubbo协议也是一种私有协议,他们都是应用层协议,基于tcp或udp设计。
聊聊dubbo协议2
在中介绍了attachments在consumer和provider间的传递情况,有个疑问没有给出答案。为什么2.7.x版本的dubbo不支持provider端向consumer端回传隐式参数呢?今天的续集将揭晓答案。 抓包确定是provider没发还是consumer丢掉 以下测试基于dubbo 2.7.6版本在provider端加入下面的代码
Dubbo 源码分析 - 服务调用过程
Dubbo 源码分析 服务调用过程注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 中阅读本系列文章。1\. 简介在前面的文章中,我们分析了 Dubbo SPI、服务导出与引入、以及集群容错方面的代码。经过前
Dubbo 源码分析 - 集群容错之 LoadBalance
Dubbo 源码分析 集群容错之 LoadBalance注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 中阅读本系列文章。1.简介LoadBalance 中文意思为负载均衡,它的职责是将网络
Dubbo 源码分析 - 集群容错之Directory
注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 中阅读本系列文章。1\. 简介前面文章分析了服务的导出与引用过程,从本篇文章开始,我将开始分析 Dubbo 集群容错方面的源码。这部分源码包含四个部分,分别是服务目录 Directory、服务路由 Router、集群 Cluster 和负载均衡 LoadBalance。这几个部分的源码逻辑比
dubbo应用级服务发现初体验
dubbo应用级服务发现介绍了解dubbo的朋友知道,dubbo的provider启动时向注册中心注册,consumer从注册中心消费。目前dubbo往注册中心上注册的数据是接口级,而应用级服务发现是往注册中心上注册实例(ip+port),两者的区别只是注册的粒度不同。至于为什么会出现应用级服务发现,有如下几点原因 与业界主流微服务模型对齐,比如 Sprin
dubbo的前世今生
背景在很久以前,网站应用是单体应用的架构,流量小,所有功能、代码都部署在一起,成本低。此时数据库访问框架ORM是关键。后来流量逐渐增大,单体应用被拆分为互不相干的多个应用,这就是垂直架构,此时加速前端页面开发的Web框架MVC是关键。再后来,垂直应用越来越大,应用间的交互不可避免,分布式服务框架RPC变成了关键。 dubboRPC,全称Remote Proc
排查dubbo接口重复注销问题,我发现了一个巧妙的设计
背景我在公司内负责自研的dubbo注册中心相关工作,群里经常接到业务方反馈dubbo接口注销报错。经排查,确定是同一个接口调用了两次注销接口导致,由于我们的注册中心注销接口不能重复调用,调用第二次会因为实例已经注销而报实例找不到的错误。虽然这个报错仅会打印一条错误日志,不影响业务,但本着 follow through的精神,我决定还是一探究竟,更何况重复注销
redis在微服务领域的贡献
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 前言说到redis,可能大家的脑海中蹦出的关键词是:NoSQL、KV、高性能、缓存等。但今天的文章从另一个角度——微服务来展开。这篇文章的起因也是源自一次面试经历,在面试一位来自陌陌的候选人(就是那个交友的陌陌)时,他提到一点让我觉得很有意思,他说red
实测Tengine开源的Dubbo功能
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 背景 Tengine是阿里巴巴基于Nginx开发并开源的Web服务器,它继承了Nginx所有的功能和特性,并在其基础上做了大量的扩展和增强,其中像动态模块加载,四层负载均衡,reuseport支持等能力,都逐渐被Nginx官方吸收引用。Tengine在开
给dubbo贡献源码,做梦都在修bug
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 一在之前的文章《redis在微服务领域的贡献》中,从一次面试经历中了解了redis可以在微服务中玩的这么溜,同时也从源码角度分析了dubbo的redis注册中心。最后得出了dubbo的redis注册中心不能用于生产的结论,其中原因有如下两点: 使用了ke
dubbo 2.7应用级服务发现踩坑小记
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 背景本文记录最近一位读者反馈的dubbo 2.7.x中应用级服务发现的问题,关于dubbo应用级服务发现的相关介绍可以参考之前的文章,这里不再赘述。读者反馈他们在基于dubbo 2.7应用级服务发现开发dubbo网关,根据文章《dubbo应用级服务发现初
使用dubbo-go搭建dubbo接口测试平台
背景http接口测试只需要一个curl命令,但dubbo协议没有这样的现成接口测试工具。通常公司内的dubbo控制台或其他平台会集成一个dubbo接口测试工具。调用一个dubbo接口,需要知道服务名service、方法名method和参数args。正常的调用,调用方需引入服务提供方定义的接口jar包。作为接口测试平台,没办法引入所有提供方定义的接口jar包,