关于docker:docker在生产环境上的排坑记录更新中

生产环境逐渐容器化的过程中遇到了一些坑,特此记录一下:

Docker默认网络模式带来的ip问题

这是初步应用docker时遇见最多的问题,在多个组件或中间件上体现,然而实质问题还是因为docker默认的网络模式是bridge,会为以后容器调配格局为172.17.0.X的IP地址。这个IP的特点是在一台宿主机上递增,然而如果同一个服务在多个宿主机上都应用容器部署,很可能会呈现IP地址雷同的状况,对于以IP来辨认终端的一些组件和中间件来说,会呈现问题。

针对此问题,大部分状况下能够设置网络模式为host来解决:

--net=host

然而如此一来,同一宿主机上就不能搁置多个同服务的容器,因为端口雷同(host模式下不能应用 -p 设置端口),除非批改源码扭转端口,然而这样代价太大。另外对于个别问题还是解决不了。另外也是在初步波及docker,应用默认模式更保险一些。

RocketMQ消费者客户端因为IP雷同导致反复生产问题

  • 问题表象

    A,B两台宿主机都有一个基于docker的生产客户端,IP地址都为172.17.0.1,在理论生产中呈现了反复生产问题。如下:

    当然,在网上搜寻时也发现有的敌人遇到的是不生产的状态,具体为何没有深究。

  • 问题剖析

    ​ RocketMQ用一个叫ClientID的概念,来惟一标记一个客户端实例,一个客户端实例对于Broker而言会开拓一个Netty的客户端实例。 而ClientID是由ClientIP+InstanceName形成,如下源码:

    public String buildMQClientId() {
      StringBuilder sb = new StringBuilder();
      sb.append(this.getClientIP());
    
      sb.append("@");
      sb.append(this.getInstanceName());
      if (!UtilAll.isBlank(this.unitName)) {
        sb.append("@");
        sb.append(this.unitName);
      }
      return sb.toString();
    }

​ 而instanceName个别咱们时不会设置的,默认的话会取过程号

public void changeInstanceNameToPID() {
  if (this.instanceName.equals("DEFAULT")) {
    this.instanceName = String.valueOf(UtilAll.getPid());
  }
}

​ 故如果一个过程中多个实例(无论Producer还是Consumer)ClientIP和InstanceName都一样,他们将专用一个外部实例(同一套网络连接,线程资源等)

​ 此外,此ClientID在对于Consumer负载平衡的时候起到惟一标识的作用,一旦多个实例(无论不同过程、不通机器、还是同一过程)的多个Consumer实例有一样的ClientID,负载平衡的时候必然RocketMQ任然会把两个实例当作一个client(因为同样一个clientID)。

​ 故为了防止不必要的问题,ClientIP + instance Name的组合倡议惟一,这里我采纳自定义instanceName的形式,在springboot下如下:

@Configuration
@AutoConfigureBefore(RocketMQAutoConfiguration.class)
public class RocketMQCustomFrontConfig {
    static {
        System.setProperty("rocketmq.client.name", String.valueOf(System.currentTimeMillis()));
    }
}

到此问题解决。

应用nacos作为服务发现导致服务间调用不通问题

​ 同样的起因,导致nacos服务节点ip截然不同,然而因为是虚构ip,所以会影响服务间的调用,解决办法也很简略,我是在docker启动脚本中增加如下配置:

--spring.cloud.nacos.discovery.ip=$nacos_discovery_id

​ 当然在springboot环境下配置文件中也能够设置,不过不同环境下就须要批改源码配置文件,所以不做思考。若应用的是其余服务发现组件,都有各自配置反对。

阿里Sentinel下节点状态不对且链路不通问题

​ Sentinel下的问题要从2个方面思考:ip和端口。基于docker环境,默认状况下:

  • 若ip为虚构ip则链路不通。
  • sentinel的客户端裸露数据的端口默认为8719,若端口被占用则自增;然而在docker环境下,每一个客户端的端口都为8719,这时候应用docker -p映射端口就难以确定或者每个节点都须要不同的脚本,这个切实太麻烦了。
  • 若ip和端口都统一,则会呈现多个节点在dashboard被笼罩的问题

​ 解决办法如下:

## 对于ip能够应用一下参数设置
--spring.cloud.sentinel.transport.client-ip=$nacos_discovery_id

## 至于端口,我才用的办法就是设计好端口规定,而后在springboot中手动设置sentinel的数据端口,最初在docker脚本中通过-p配置固定端口,这样至多每一个利用只须要一个脚本,另外对于一个利用的不同节点最好放在不同宿主机上
spring:
  cloud:
    sentinel:
      transport:
        port: 17019

继续更新。。。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理