前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker下部署dubbo,消费者应用无法使用link参数的问题

Docker下部署dubbo,消费者应用无法使用link参数的问题

作者头像
程序员欣宸
发布2018-01-04 15:52:10
1.3K0
发布2018-01-04 15:52:10
举报
文章被收录于专栏:实战docker实战docker

在前一篇文章《Docker下dubbo开发,三部曲之一:极速体验》中,我们快速体验了部署在Docker环境下的dubbo服务,当时一共启动了四个容器,具体情况为:

容器

作用

镜像

功能

link连接

zk_server

一致性协调服务

zookeeper:3.3.6

官方镜像

dubbo_admin

注册中心

bolingcavalry/dubbo_admin_tomcat:0.0.1

定制镜像,用tomcat官方镜像加dubbo_admin.war生成

用别名zkhost连接zk_server

dubbo_provider

服务提供者

bolingcavalry/dubbo_provider_tomcat:0.0.1

定制镜像,用tomcat官方镜像加dubboserviceprovider.war文件生成

用别名zkhost连接zk_server

dubbo_consumer

服务消费者

bolingcavalry/online_deploy_tomcat:0.0.1

定制镜像,是个支持在线部署的tomcat

现状分析

在这个体验环境中,dubbo的服务提供者和消费者其实都是web应用,对应的是dubboserviceprovider.war和dubboserviceconsumer.war这两个文件,分别部署在docker容器的tomcat中。

把一个web应用在docker的tomcat容器中运行起来有两种方式: 1. 写Dockerfile文件做一个定制镜像,用tomcat官方镜像做基础镜像,在Dockerfile中将war包复制到tomcat的webapps目录下,dubbo_provider就是用这种方式; 2. 运行一个支持在线部署的tomcat容器,然后在线部署war包,具体细节请看《实战docker,编写Dockerfile定制tomcat镜像,实现web应用在线部署》,dubbo_consumer用的就是这种方式;

很明显,第一种方式用起来更简单,在docker-compose.yml中把镜像指定了就行,而第二种方式略为麻烦,要自己动手去部署war包;

问题出现

那么问题来了,既然第一种简单,为何dubbo_consumer不用这种方式呢,反而用更为麻烦的第二种?

回答这个问题之前,我们先看下提供服务的应用dubbo_provider,它用的是第一种方式,dubbo服务提供方要把自己注册到dubbo注册中心,所以必然要使用zookeeper服务,在docker-compose.yml中,dubbo_provider的配置如下:

代码语言:javascript
复制
dubbo_provider: 
    image: bolingcavalry/dubbo_provider_tomcat:0.0.1
    links: 
      - zk_server:zkhost
    depends_on:
          - "dubbo_admin"
    environment:
      TOMCAT_SERVER_ID: dubbo_provider_tomcat
    restart: always

dubbo_provider容器配置了link参数zk_server:zkhost,也就是用zkhost取代zookeeper的ip,这样服务提供者的代码中只要使用zkhost就能连接到zookeeper;

那么dubbo_consumer呢,如果也用link参数zk_server:zkhost,然后在代码中用zkhost取代zookeeper的ip,这样不就和dubbo_provider一样了么?

第一种方式的尝试

当初我的确是这么做的,用Dockerfile把dubbo_consumer的war包复制到tomcat镜像中,启动容器的时候用link参数zk_server:zkhost,代码中用zkhost替代zookeeper的ip,如下图:

这里写图片描述
这里写图片描述

在容器运行的时候抛出了以下错误:

代码语言:javascript
复制
May 16, 2017 12:27:35 PM org.apache.catalina.core.ApplicationContext log
INFO: No Spring WebApplicationInitializer types detected on classpath
May 16, 2017 12:27:35 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
May 16, 2017 12:27:38 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubboServiceConsumeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bolingcavalry.service.CalculateService com.bolingcavalry.controller.DubboServiceConsumeController.calculateService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'calculateService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Failed to check the status of the service com.bolingcavalry.service.CalculateService. No provider available for the service com.bolingcavalry.service.CalculateService from the url zookeeper://zkhost:2181/com.alibaba.dubbo.registry.RegistryService?application=dubbo_service_consumer&dubbo=2.5.3&interface=com.bolingcavalry.service.CalculateService&methods=add&pid=1&side=consumer&timestamp=1494937657693 to the consumer 172.28.0.4 use dubbo version 2.5.3
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5118)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5634)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1571)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1561)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bolingcavalry.service.CalculateService com.bolingcavalry.controller.DubboServiceConsumeController.calculateService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'calculateService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Failed to check the status of the service com.bolingcavalry.service.CalculateService. No provider available for the service com.bolingcavalry.service.CalculateService from the url zookeeper://zkhost:2181/com.alibaba.dubbo.registry.RegistryService?application=dubbo_service_consumer&dubbo=2.5.3&interface=com.bolingcavalry.service.CalculateService&methods=add&pid=1&side=consumer&timestamp=1494937657693 to the consumer 172.28.0.4 use dubbo version 2.5.3
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    ... 22 more

注意这一行

代码语言:javascript
复制
No provider available for the service com.bolingcavalry.service.CalculateService from the url zookeeper://zkhost:2181/com.alibaba.dubbo.registry.RegistryService?application=dubbo_service_consumer&dubbo=2.5.3&interface=com.bolingcavalry.service.CalculateService&methods=add&pid=1&side=consumer&timestamp=1494937657693

zookeeper://zkhost:2181/com.alibaba.dubbo.registry.RegistryService?application=dubbo_service_consumer&dubbo=2.5.3&interface=com.bolingcavalry.service.CalculateService&methods=add&pid=1&side=consumer&timestamp=1494937657693是个url,用来查找服务的,这个url中有我们在xml中填入的zkhost。

问题分析

问题已经很清楚了,我们用zkhost替代ip原本是为了网络连接的时候,利用系统中host文件对zkhost的配置,来方便的连接到对应的ip,但是在dubbo的消费者服务中,dubbo运行时会把zkhost当作一个字符串来使用,拿这个字符串生成的url在dubbo注册中心是搜索不到的,因为服务在注册的时候注册中心记录的是ip;

基于以上原因,我才放弃了第一种部署方式,选择了先启动tomcat,再手工在线部署war包的方式(war包中zookeeper的ip已经写成真正的);

其实理论上第一种方式也是可以的,步骤如下: 1. 配置link参数zk_server:zkhost; 2. tomcat不再启动时自动执行; 3. 复制到镜像文件的web应用不是war包,而是从war包解压好的文件夹; 4. 制作一个shell,在容器启动的时候自动执行,shell的功能是从/etc/hosts文件中取得zkhost对应的ip,然后用sed命令将spring-extends.xml中的address=”zookeeper://zkhost:2181”替换成zkhost对应的ip; 5. 启动tomcat;

理论上这种方法也是可以的;

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-05-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 现状分析
  • 问题出现
  • 第一种方式的尝试
  • 问题分析
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档