Docker下部署微服务实践踩坑总结

简介: Docker下部署微服务实践踩坑总结

【1】java.net.UnknownHostException

① 问题背景与表现

背景:docker启动应用服务注册到别处eureka(注意是别的服务器的eureka),启动命令格式类似如下:

sudo docker run -d --name mallprovider -p 9122:9122 -v /home/app/fs:/root/fs -v /home/app/provider/server:/usr/local/server/   --privileged=true  mallprovide:centos 

以docker化微服务的时候发现注册到eureka中的实例ID变为containerId:服务名称:服务端口号

而且docker 容器每重启一次(这里指删除容器重启,containerId变化),就多一个该服务的实例如d1deb75f7aed:client_instance:9123,并且被删除的容器实例d2b59f32b427:client_instance:9123不下线。也就是说会存在一些“伪活”服务,如果是消费者找服务提供者找到了“伪活”服务,那么肯定是会报错的。


比如客户端访问会提示java.net.UnknownHostException(并且会发现消费者仍旧会向原先被删除的服务发送请求):


这里有两个问题:

  • 如何让docker启动的服务注册实例名称为{主机名称:服务名称:服务端口号}或{主机Ip:服务名称:服务端口号}?
  • 怎么让已经停掉的容器下线(如何找到正确的服务)?


② docker容器启动的服务注册实例名称正常化

正常我们起一个微服务注册到eureka他的实例id是默认这样的:主机名称:服务名称:服务端口号,如果配置eureka.instance.prefer-ip-address=true则实例id为:主机Ip:服务名称:服务端口号。当然我们也可以通过eureka.instance.instance-id自定义实例ID格式。


通常配置实例如下:

eureka:
  client: #客户端注册进eureka服务列表内
    service-url: 
      defaultZone: http://localhost:7001/eureka   
  instance:
    instance-id: ${spring.application.name}:${server.port}
    prefer-ip-address: true     #访问路径可以显示IP地址     

指定容器网络模式为host,如下增加--net host

sudo docker run -d --name --net host mallprovider -p 9122:9122 -v /home/app/fs:/root/fs -v /home/app/provider/server:/usr/local/server/   --privileged=true  mallprovide:centos 

为什么要指定网络模式host(这样就不会使用docker的ip):


--net=bridge:默认选项,用网桥的方式来连接docker容器。

--net=host:docker跳过配置容器的独立网络栈。

--net=container:NAME_or_ID:告诉docker让这个新建的容器使用已有容器的网络配置。

--net=none:告诉docker为新建的容器建立一个网络栈,但不对这个网络栈进行任何配置,所以只能访问本地网络,没有外网。


③ 服务强制下线

通过api强制下线,postman发送delete请求即可

格式如下:

http://{ip}:{port}/eureka/apps/{服务名称}/{inatanceId}

如http://127.0.0.1:3000/eureka/apps/client_instance/348761338c57:client_instance:9123

或者可以通过自定义实例id,让后起的实例挤掉先起的失效实例:

eureka.instance.instance-id=${spring.application.name}:${server.port}
eureka.instance.prefer-ip-address=true
#或者以IP:端口进行注册
eureka.instance.prefer-ip-address:true
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

但是这时仍旧存在一个问题:docker stop 时服务不会从eureka注册中心down!

这里是容器启动的时候通过执行一个脚本来启动服务的,脚本如下:

#!/bin/bash
cd /usr/local/server/
if [ -f nohup.out ];then
        rm -rf nohup.out
else
        touch nohup.out
        chmod 755 nohup.out
fi
nohup java -jar mallmng-client-1.0-SNAPSHOT.jar  &>>nohup.out &
tail -f nohup.out


【2】时间差8小时

背景:使用docker启动应用发现时间少了8小时,但是宿主机、docker容器时区时间都正常。

第一反应,很显然是典型的8小时时区问题啊。Linux中检测时间时区几个常用命令如下所示:

[app@beijing-csmf-4 client]$ date +"%Z %z"
CST +0800
[app@beijing-csmf-4 client]$ date
Thu Aug  6 19:17:28 CST 2020
[app@beijing-csmf-4 client]$ date -R
Thu, 06 Aug 2020 19:17:30 +0800
[app@beijing-csmf-4 client]$ timedatectl
      Local time: Thu 2020-08-06 19:18:06 CST
  Universal time: Thu 2020-08-06 11:18:06 UTC
        RTC time: Thu 2020-08-06 19:18:06
       Time zone: Asia/Shanghai (CST, +0800)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: yes
      DST active: n/a


检测发现宿主机、docker容器都正常,甚至启动命令时直接同步了宿主机的时区:

#同步时区 ro表示read only 即容器内的数据只允许读
-v /etc/localtime:/etc/localtime:ro
#同步时间
 -v /etc/localtime:/etc/localtime:ro
#容器启动命令格式类似如下
docker run -d  -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro   mallprovide:centos 

但是如上所示仍旧不可以,最后不得已在启动的时候硬指定了区域

docker run -d  -e TZ=Asia/Shanghai   mallprovide:centos

如果自定义了Dockerfile,也可以在Dockerfile里面指定环境变量:

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

【3】中文乱码

在Dockerfile中添加一行环境配置即可:

ENV LANG C.UTF-8

C.utf8=POSIX标准兼容的默认语言环境。只有严格的ASCII字符才是有效的,扩展后允许基本使用UTF-8

en_US.utf8=美式英语UTF-8语言环境。


一般来说,C指的是计算机,en_US指的是我们中说英语的人(以及其他想要同样行为的人)。


computer的意味着字符串有时更标准(但仍然是英语),因此程序的输出可以从其他程序读取。使用en_US,字符串可以得到改进,字母顺序可以得到改进(可能通过芝加哥风格规则的新规则等)。所以更方便用户,但可能不太稳定。注意:语言环境不仅用于字符串的转换,还用于排序(字母顺序、数字(例如千位分隔符)、货币(我认为可以安全地预测美元和小数点后两位)、月份、星期几等


C.utf8=POSIX与en_US.utf8只是两个地区的UTF-8版本。通常这个不太重要,应该只更改日志和错误消息(如果您使用locale.setlocale())。


目录
相关文章
kde
|
1月前
|
应用服务中间件 网络安全 nginx
手把手教你使用 Docker 部署 Nginx 教程
本文详解Nginx核心功能与Docker部署优势,涵盖镜像拉取、容器化部署(快速、挂载、Compose)、HTTPS配置及常见问题处理,助力高效搭建稳定Web服务。
kde
658 4
|
30天前
|
应用服务中间件 Linux nginx
在虚拟机Docker环境下部署Nginx的步骤。
以上就是在Docker环境下部署Nginx的步骤。需要注意,Docker和Nginix都有很多高级用法和细节需要掌握,以上只是一个基础入门级别的教程。如果你想要更深入地学习和使用它们,请参考官方文档或者其他专业书籍。
103 5
|
2月前
|
存储 Docker Python
docker 部署 sftp
本文介绍SFTP服务的部署与配置,包括users.conf用户配置规则、Docker容器运行命令及上传目录权限说明,重点解析atmoz/sftp镜像的chroot机制与子目录映射,确保用户登录后正确访问/upload目录,并提供Python脚本实现文件上传示例。
200 12
docker 部署 sftp
kde
|
1月前
|
存储 NoSQL Redis
手把手教你用 Docker 部署 Redis
Redis是高性能内存数据库,支持多种数据结构,适用于缓存、消息队列等场景。本文介绍如何通过Docker快速拉取轩辕镜像并部署Redis,涵盖快速启动、持久化存储及docker-compose配置,助力开发者高效搭建稳定服务。
kde
605 7
kde
|
1月前
|
存储 搜索推荐 数据库
🚀 RAGFlow Docker 部署全流程教程
RAGFlow是开源的下一代RAG系统,融合向量数据库与大模型,支持全文检索、插件化引擎切换,适用于企业知识库、智能客服等场景。支持Docker一键部署,提供轻量与完整版本,助力高效搭建私有化AI问答平台。
kde
1562 8
kde
|
1月前
|
存储 关系型数据库 MySQL
MySQL Docker 容器化部署全指南
MySQL是一款开源关系型数据库,广泛用于Web及企业应用。Docker容器化部署可解决环境不一致、依赖冲突问题,实现高效、隔离、轻量的MySQL服务运行,支持数据持久化与快速迁移,适用于开发、测试及生产环境。
kde
393 4
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
651 6
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
303 1
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2