在Docker中运行Dubbo应用

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文通过Spring Boot构建了一个最小的Dubbo应用,容器化后成功部署到阿里云容器服务上。

logos

更新历史

  • 2017.11.30 增加利用v3版本compose文件部署示例。

Dubbo概述

Dubbo是阿里开源的一个分布式服务框架,在国内粉丝很多。官网上的介绍是:

DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

Dubbo的文档很完整,网络上资源也很多,这里就不再重复了。本文做这样一个尝试,将一个Dubbo应用容器化,部署到阿里云的容器服务上。

极简Dubbo应用结构

在Dubbo世界里,服务调用方和服务提供方通过Dubbo的发现机制互相发现。一个最小的Dubbo应用包含如下三个服务:

  • 服务提供者
  • 服务调用方
  • 发现机制(例如zookeeper)

arch

zookeeper已经有Docker镜像了,下面我们就会用Spring Boot开发服务提供方Service Producer和服务调用方Service Consumer。

定义服务接口

创建一个Maven模块service-api,定义服务接口。

public interface Greetings {
    String say(String name);
}

这个接口很简单,就是问好。

在pom.xml中引入对Dubbo的依赖:

<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.5.3</version>
    </dependency>
</dependencies>

我们用的是dubbo 2.5.3版本,读者如果愿意尝试更新的版本,可以自行升级。

服务提供方 Service Producer

创建一个Maven模块service-producer,提供服务接口的实现。

public class GreetingsImpl implements Greetings {
    public String say(String name) {
        return "Greetings from " + name;
    }
}

为了能找到服务接口模块,需要在pom.xml中定义对service-api的依赖。

<dependencies>
    ...
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>dubbo-service-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

Dubbo通过spring xml配置文件的方式声明对zookeeper的访问。在resources目录下创建services.xml,其中最重要的内容是指定zookeeper的地址和端口,为了不把zookeeper的地址写死在配置文件中,我们采用环境变量来指明服务地址。这也是12 factor应用的一个推荐实践之一。

<dubbo:registry protocol="zookeeper" address="${ZOOKEEPER_SERVER}:2181" />

<dubbo:protocol name="dubbo" port="20880" />

<dubbo:service interface="com.example.service.Greetings" ref="greetingService"/>

<bean id="greetingService" class="com.example.service.producer.GreetingsImpl" />

xml文件中的其他内容包括指定本服务的侦听端口为20880GreetingsImpl类实现的接口API类等。

下面要在pom.xml引入dubbo的项目依赖。

<dependencies>
    ...
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.5.3</version>
        <exclusions>
            <exclusion>
                <artifactId>spring</artifactId>
                <groupId>org.springframework</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.1</version>
    </dependency>

我们准备用spring 4.x,所以把dubbo中自带的老版本springframework剔除。

现在服务的实现类有了,我们需要一个主函数把实现类运行起来。Springboot有一个很好的特性,就是把一个Java应用的所有相关依赖打包成为一个超级JAR包,对于生成Docker镜像来说非常方便。

首先在pom.xml中引入springboot依赖。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
...

创建一个Spring主应用。由于Dubbo采用xml配置文件的方式,要通过@ImportResource声明加载services.xml配置文件。

@SpringBootApplication
@ImportResource({"classpath:services.xml"})
public class Application {
    public static void main(String[] args) throws Exception{
        SpringApplication.run(Application.class, args);
    }
}

Springboot Web应用启动后会自动侦听8080端口。不过我们在这里没有用到内置的tomcat和8080端口。如果你不喜欢这个多余的tomcat,可以用spring-boot-starter替换本文中的spring-boot-starter-web项目,但要注意的是,没有tomcat的代码需要增加不退出应用的逻辑。

服务调用方 Service Consumer

Service Consumer的结构和Producer的结构类似,也需要在pom.xml中引入对dubbo, service-api和springboot的依赖。在resouces目录下创建services.xml,声明zookeeper的地址和要访问的服务接口:

<dubbo:registry protocol="zookeeper" address="${ZOOKEEPER_SERVER}:2181" />
<dubbo:reference id="greetingService" interface="com.example.service.Greetings" />

远程调用的服务bean名字为greetingService,在下面的代码中要用到。

在Application主应用中调用Service Producer。

Greetings greetingService = (Greetings)context.getBean("greetingService");
String result = greetingService.say("Dubbo Docker");

为了能够用HTTP访问Consumer应用,我们用@RequestMapping将context root /映射到方法上。

@RequestMapping("/")
public String greetings(){
   ...

Consumer启动侦听的端口在resources/application.properties文件中指定:

server.port=${SERVER_PORT:0}

编译并在本地运行

在项目的根目录下运行Maven编译:

mvn package

从Docker镜像中启动zookeeper,并把2181端口映射到本机:

docker run -d -p 2181:2181 -p 2888:2888 -p 3888:3888 registry.aliyuncs.com/acs-sample/zookeeper:3.4.8

在环境变量中指定zookeeper地址,启动Service Producer。

export ZOOKEEPER_SERVER=127.0.0.1
java -jar target/dubbo-service-producer-1.0-SNAPSHOT.jar

启动Service Consumer时除了要指定zookeeper地址外,还要指定consumer自己侦听的地址,本示例中使用的是8899。

export ZOOKEEPER_SERVER=127.0.0.1
export SERVER_PORT=8899
java -jar target/dubbo-service-consumer-1.0-SNAPSHOT.jar

访问一下cosumer的HTTP 8899端口,可以看到消息的输出。说明服务调用方从zookeeper中获得了正确的producer的地址,并用dubbo远程调用协议成功调用了producer的GreetingService。

$curl http://localhost:8899/
Greetings from Dubbo Docker

构建Docker镜像

为Producer和Consumer构建Docker镜像和正常的SpringBoot应用一样,Dockerfile内容如下:

FROM openjdk:8-jre
VOLUME /tmp
COPY target/*.jar app.jar
RUN sh -c 'touch /app.jar'
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

把这个文件分别放在Producer和Consumer的目录下,执行Docker的编译命令即可打包生成容器镜像。

在service-producer目录下运行:

mvn package
docker build -t producer .

生成service-consumer镜像类似,这里就不重复了。

两个镜像生成后,可以用Docker Compose命令启动。对应的docker-compose.yml内容如下:

version: "2"
services:
  zookeeper:
    image: 'registry.aliyuncs.com/acs-sample/zookeeper:3.4.8'
    hostname: zookeeper
  producer:
    image: 'producer:latest'
    environment:
      - ZOOKEEPER_SERVER=zookeeper
  consumer:
    image: 'consumer:latest'
    environment:
      - ZOOKEEPER_SERVER=zookeeper
      - SERVER_PORT=8899
    ports:
      - 8899:8899

在这里把zookeeper容器的主机名hostname设置为zookeeper并通过环境变量传给producer和consumer。运行Docker Compose启动三个容器。

$docker-compose up -d
Creating docker_consumer_1
Creating docker_zookeeper_1
Creating docker_producer_1

容器启动成功后用同样方式访问8899端口可以看到正确的输出。

$curl http://localhost:8899/
Greetings from Dubbo Docker

部署到阿里云容器上

好了,至此我们已经成功地在本地Docker环境中运行了Dubbo应用,下面就要将这个应用部署到阿里云容器服务上。

首先登陆阿里云Docker镜像仓库,地址在此https://cr.console.aliyun.com/,创建2个镜像仓库。在本示例中命名为dubbo-springboot-producerdubbo-springboot-consumer

创建一个为阿里云部署的模版文件,docker-compose-acs.yml,内容和docker-compose.yml类似。

version: "2"
services:
  zookeeper:
    image: 'registry.aliyuncs.com/acs-sample/zookeeper:3.4.8'
    hostname: zookeeper
  producer:
    image: 'registry.cn-hangzhou.aliyuncs.com/${rname}/dubbo-springboot-producer:latest'
    environment:
      - ZOOKEEPER_SERVER=zookeeper
  consumer:
    image: 'registry.cn-hangzhou.aliyuncs.com/${rname}/dubbo-springboot-consumer:latest'
    environment:
      - ZOOKEEPER_SERVER=zookeeper
      - SERVER_PORT=8899
    labels:
      aliyun.routing.port_8899: http://ds-consumer

这个部署文件和docker-compose.yml内容不同之处在于,所有容器到主机端口映射都去掉了,为了能访问consumer,使用了aliyun.routing.port_8899为consumer指定一个子域名。集群部署后可用如下URL访问consumer服务。

http://ds-consumer.c67***8cd5.cn-shenzhen.alicontainer.com

登陆阿里云容器服务控制台 https://cs.console.aliyun.com,利用部署模版创建一个新应用,部署模版的内容就是上面docker-compose-acs.yml内容,提示rname时输入你的容器仓库用户名,很快应用部署就会成功。

在控制台中进入consumer服务页面,找到访问端点:

consumer1

点击地址,可以在浏览器中看到输出:

consumer2

至此,我们成功地在云上运行了Dubbo应用。

本文中的compose模版部署为v2版本,如果大家想尝试利用v3版本部署,可以访问github

讨论

在网上有讨论容器化的Dubbo应用发送的IP地址不对,经实测在Docker 1.12版本下没有这个问题,部署到阿里云容器服务上也正常。本文的示例代码在github上,大家可以参考。

小节

本文通过Spring Boot构建了一个最小的Dubbo应用,容器化后成功部署到阿里云容器服务上。

相关实践学习
Docker镜像管理快速入门
本教程将介绍如何使用Docker构建镜像,并通过阿里云镜像服务分发到ECS服务器,运行该镜像。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
4天前
|
存储 安全 数据安全/隐私保护
【Docker 专栏】Docker 容器化应用的备份与恢复策略
【5月更文挑战第9天】本文探讨了Docker容器化应用的备份与恢复策略,强调了备份在数据保护、业务连续性和合规要求中的关键作用。内容涵盖备份的重要性、内容及方法,推荐了Docker自带工具和第三方工具如Portainer、Velero。制定了备份策略,包括频率、存储位置和保留期限,并详细阐述了恢复流程及注意事项。文章还提及案例分析和未来发展趋势,强调了随着技术发展,备份与恢复策略将持续演进,以应对数字化时代的挑战。
【Docker 专栏】Docker 容器化应用的备份与恢复策略
|
4天前
|
监控 Kubernetes Docker
【Docker 专栏】Docker 容器内应用的健康检查与自动恢复
【5月更文挑战第9天】本文探讨了Docker容器中应用的健康检查与自动恢复,强调其对应用稳定性和系统性能的重要性。健康检查包括进程、端口和应用特定检查,而自动恢复则涉及重启容器和重新部署。Docker原生及第三方工具(如Kubernetes)提供了相关功能。配置检查需考虑检查频率、应用特性和监控告警。案例分析展示了实际操作,未来发展趋势将趋向更智能和高效的检查恢复机制。
【Docker 专栏】Docker 容器内应用的健康检查与自动恢复
|
4天前
|
关系型数据库 MySQL Shell
4.Docker 应用部署
4.Docker 应用部署
|
4天前
|
NoSQL Redis Docker
Mac上轻松几步搞定Docker与Redis安装:从下载安装到容器运行实测全程指南
Mac上轻松几步搞定Docker与Redis安装:从下载安装到容器运行实测全程指南
21 0
|
4天前
|
存储 安全 数据库
【Docker 专栏】Docker 容器内应用的状态持久化
【5月更文挑战第9天】本文探讨了Docker容器中应用状态持久化的重要性,包括数据保护、应用可用性和历史记录保存。主要持久化方法有数据卷、绑定挂载和外部存储服务。数据卷是推荐手段,可通过`docker volume create`命令创建并挂载。绑定挂载需注意权限和路径一致性。利用外部存储如数据库和云服务可应对复杂需求。最佳实践包括规划存储策略、定期备份和测试验证。随着技术发展,未来将有更智能的持久化解决方案。
【Docker 专栏】Docker 容器内应用的状态持久化
|
4天前
|
机器学习/深度学习 人工智能 异构计算
【Docker 专栏】Docker 与 GPU 加速应用的结合
【5月更文挑战第9天】GPU加速技术在处理大规模数据和复杂计算时展现强大性能,尤其在AI和深度学习领域。Docker作为轻量级容器化工具,提供隔离、可移植和高效的环境。结合GPU加速,关键在于容器访问GPU设备和安装相应驱动。NVIDIA提供了支持工具,允许Docker利用GPU。应用场景包括人工智能、科学计算和视频处理。优势包括资源利用率提升和部署灵活性,但面临驱动兼容性、资源管理和监控调试的挑战。未来,随着技术发展,Docker与GPU加速在边缘计算中的应用将有广阔前景。
【Docker 专栏】Docker 与 GPU 加速应用的结合
|
4天前
|
存储 Prometheus 监控
【Docker 专栏】Docker 容器内应用的调试与故障排除
【5月更文挑战第8天】本文探讨了Docker容器内应用的调试与故障排除,强调其重要性。方法包括:通过日志排查、进入容器检查、使用监控工具及检查容器配置。常见问题涉及应用启动失败、性能问题、网络连接和数据存储。案例分析展示了实战场景,注意事项提醒避免不必要的容器修改、备份数据和理解应用架构。掌握这些技能能确保Docker应用的稳定运行和性能优化。
【Docker 专栏】Docker 容器内应用的调试与故障排除
|
4天前
|
开发框架 安全 网络安全
【Docker 专栏】Docker 多平台应用构建与部署
【5月更文挑战第8天】Docker作为一种关键的容器化技术,简化了多平台应用的构建与部署。它提供一致的运行环境,确保应用在不同平台无缝运行;通过分层构建机制加速镜像创建,提升开发效率。Docker的可移植性、高效部署及资源利用率是其主要优势。流程包括开发环境准备、构建镜像、测试验证及部署。然而,面临操作系统差异、网络安全和资源限制等挑战,需注意安全、版本管理和性能优化。Docker在多平台场景的应用将持续发挥价值。
【Docker 专栏】Docker 多平台应用构建与部署
|
4天前
|
Kubernetes Cloud Native 持续交付
【Docker专栏】Kubernetes与Docker:协同构建云原生应用
【5月更文挑战第7天】本文探讨了Docker和Kubernetes如何协同构建和管理云原生应用。Docker提供容器化技术,Kubernetes则负责容器的部署和管理。两者结合实现快速部署、自动扩展和高可用性。通过编写Dockerfile创建镜像,然后在Kubernetes中定义部署和服务进行应用暴露。实战部分展示了如何部署简单Web应用,包括编写Dockerfile、构建镜像、创建Kubernetes部署配置以及暴露服务。Kubernetes还具备自动扩展、滚动更新和健康检查等高级特性,为云原生应用管理提供全面支持。
【Docker专栏】Kubernetes与Docker:协同构建云原生应用
|
4天前
|
前端开发 API 数据库
【Docker专栏】Docker Compose实战:编排多容器应用
【5月更文挑战第7天】Docker Compose是Docker的多容器管理工具,通过YAML文件简化多容器应用部署。它能一键启动、停止服务,保证开发、测试和生产环境的一致性。安装后,创建`docker-compose.yml`文件定义服务,如示例中的web和db服务。使用`docker-compose up -d`启动服务,通过`docker-compose ps`、`stop`、`down`和`logs`命令管理服务。
【Docker专栏】Docker Compose实战:编排多容器应用