微服务应用容器化场景中常见问题总结

简介:云原生技术栈是下一代应用转型的必然选择,它包含了微服务架构,DevOps和容器技术。对于微服务架构来说,应用是“第一公民”,他逐渐蚕食原来底层软件或者硬件的功能,例如服务注册与发现以及负载均衡;而对于容器平台来说,容器是“第一公民”,他提供了容器注册与发现和负载均衡,同时容器技术将应用和外面的世界做了隔离,这样很多应用运行的假设就会失效。那当微服务应用运行在容器中的时候,我们会遇到哪些常见问题?我们又该如何解决呢?

企业应用在向微服务架构转型的过程中,微服务如何划分是最基本的问题。我们可以通过业务架构的梳理来理解业务,并同时使用领域设计的方法进行微服务的设计。其次,我们需要做系统设计,系统设计会更关注性能、可用性、可扩展性和安全性等;当然,我们还需要做接口设计,定义微服务之间的契约。

Java在企业中被广泛应用,当前,选择Spring Cloud作为微服务开发框架成为一个广泛的趋势。微服务架构的复杂性需要容器技术来支撑,应用需要容器化,并使用CaaS平台来支撑微服务系统的运行。

本文探讨的主题是来自于企业级Java应用在容器化过程中遇到的基础问题(与计算和网络相关),希望以小见大探讨微服务转型过程中遇到的挑战。

容器内存限制问题


让我们来看一次事故,情况如下:当一个Java应用在容器中执行的时候,某些情况下会容器会莫名其妙退出。

1.Dockfile如下:

FROM airdock/oracle-jdk:latest
MAINTAINER Grissom Wang <grissom.wang@daocloud.io>
ENV TIME_ZONE Asia/Shanghai
RUN echo "$TIME_ZONE" > /etc/timezone
WORKDIR /app
RUN apt-get update
COPY myapp.jar /app/ myapp.jarEXPOSE 8080CMD [ "java", "-jar", "myapp.jar" ]


2.运行命令

docker runit –m=100M –memory-swap=100M grissom/myapp:latest

3.日志分析

执行docker logs container_id,出现了java.lang.OutOfMemoryError。

4.问题初步分析

因为我们在执行容器的时候,对内存做了限制,同时在Java启动参数重,没有对内存使用做限制,是不是这个原因导致了容器被干掉呢?

当我们执行没有任何参数设置(如上面的myapp)的 Java 应用程序时,JVM 会自动调整几个参数,以便在执行环境中具有最佳性能,但是在使用过程中我们逐步发现,如果让 JVM ergonomics (即JVM人体工程学,用于自动选择和行为调整)对垃圾收集器、堆大小和运行编译器使用默认设置值,运行在容器中的 Java 进程会与我们的预期表现严重不符(除了上诉的问题)。

首先我们来做一个实验:

1.在我本机(Mac)上执行docker info命令

Server Version: 17.06.0-ce
Kernel Version: 4.9.31-moby
Operating System: Alpine Linux v3.5OSType: linuxArchitecture: x86_64CPUs: 2Total Memory: 1.952GiBName: moby

2.执行docker run -it -m=100M –memory-swap=100M debian cat /proc/meminfo

MemTotal:        2047048 kB = 2GMemFree:          609416 kB = 600MMemAvailable:    1604928 kB = 1.6G

虽然我们启动容器的时候,指定了容器的内存限制,但是从容器内部看到的内存信息和主机上的内存信息几乎一致。

因此我们找到原因了:docker switches(-m,-memory和-memory-swap) 在进程超过限制的情况下,会指示 Linux 内核杀死该进程。但 JVM 是完全不知道限制,因此会很有可能超出限制。在进程超过限制的时候,容器进程就被杀掉了!

解决问题的一种思路就是使用JVM参数来限制内存的使用,这个需要根据JVM内存参数的定义来做巧妙的设置,但是幸运的是从Java SE 8u131和JDK 9开始,Java SE开始支持Docker CPU和内存限制。

具体实现逻辑如下: 如果-XX:ParalllelGCThreads或-XX:CICompilerCount未指定为命令行选项,则JVM将Docker CPU限制应用于JVM在系统上看到的CPU数。然后JVM将调整GC线程和JIT编译器线程的数量,就像它在裸机系统上运行一样,其CPU数量设置为Docker CPU限制。如果-XX:ParallelGCThreads或-XX:CICompilerCount指定为JVM命令行选项,并且指定了Docker CPU限制,则JVM将使用-XX:ParallelGCThreads和-XX:CICompilerCount值。

对于Docker内存限制、最大Java堆的设置还有一些工作要做。要在没有通过-Xmx设置最大Java堆的情况下告知JVM要注意Docker内存限制,需要两个JVM命令行选项:

-XX:+ UnlockExperimentalVMOptions-XX:+ UseCGroupMemoryLimitForHeap

-XX:+ UnlockExperimentalVMOptions是必需的,因为在将来版本中,Docker内存限制的透明标识是目标。当使用这两个JVM命令行选项,并且未指定-Xmx时,JVM将查看Linux cgroup配置,这是Docker容器用于设置内存限制的方式,以透明地指定最大Java堆大小。 Docker容器也使用Cgroups配置来执行CPU限制。

服务注册与发现


在微服务的场景中,运行的微服务实例将会达到成百上千个,同时微服务实例存在失效,并在其他机器上启动以保证服务可用性的场景,因此用IP作为微服务访问的地址会存在需要经常更新的需求。

服务注册与发现就应用而生,当微服务启动的时候,它会将自己的访问Endpoint信息注册到注册中心,以便当别的服务需要调用的时候,能够从注册中心获得正确的Endpoint。

如果用Java技术栈开发微服务应用,Spring Cloud(https://spring.io/)将会是大家首选的微服务开发框架。Spring Cloud Service Discovery就提供了这样的能力,它底层可以使用Eureka(Netflix),ZooKeeper,ETCD。这里我们以使用Spring Cloud Eureka为例(使用Spring Cloud Eureka的文档可以参考http://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.3.1.RELEASE/)。

在本机运行如下命令:

java -jar target/discovery-client-demo-0.0.1-SNAPSHOT.jar

该应用会将自己的信息注册到本地Eureka。我们可以通过打开Eureka的Dashboard,看到如下信息:


图 1 物理机上运行Eureka Client


我们可以看到应用的如下信息:

•   名称:discovery-client-demo•   IP: 10.8.0.67•   Port: 9090

但是我们在容器化场景中,遇到了问题。Dockerfile如下:

FROM airdock/oracle-jdk:latest
MAINTAINER Grissom Wang <grissom.wang@daocloud.io>ENV TIME_ZONE Asia/Shanghai
RUN echo "$TIME_ZONE" > /etc/timezone
WORKDIR /app
RUN apt-get update
COPY target/discovery-client-demo-0.0.1-SNAPSHOT.jar /app/discovery-client-demo.jar
EXPOSE 8080CMD [ "java", "-jar", "discovery-client-demo.jar" ]

假设我们现在在本机使用Docker run命令执行容器化discovery-client-demo,命令行如下:

docker run -d --name discovery-client-demo1 -e eureka.client.serviceUrl.defaultZone=http://10.8.0.67:8761/eureka/ -e spring.application.name=grissom  -p 8080:8080 discovery-client-demo:latestdocker run -d --name discovery-client-demo2 -e eureka.instance.prefer-ip-address=true –e eureka.client.serviceUrl.defaultZone=http://10.8.0.67:8761/eureka/ -e spring.application.name=grissom2  -p 8081:8080 discovery-client-demo:latest

前后两个容器的区别在于,第二个指示应用注册的使用IP,而默认是Hostname。

打开Eureka的Dashboard,我们可以看到如下信息: 

图 2 容器中运行Eureka Client

调用Eureka的Apps接口,我们可以看到更加详细的信息: 



图 3 注册应用的详细信息


这个时候我们发现了问题,两个应用注册的信息中,Hostname, IP和端口都使用了容器内部的主机名,IP和端口(如8080)。这就意味着在Port-Mapping的场景下,应用注册到Eureka的时候,注册信息无法被第三方应用使用。

解决这个问题的第一个思路如下: 



图 4 对Eureka进行扩展


我们对Eureka进行扩展,对所有客户端过来的请求进行拦截,然后从Docker Daemon中拿到正确的外部访问信息来进行替换,从而确保注册到Eureka中的信息是外部能够访问的。

该方案需要做的工作:

  • 需要同时对Eureka Client和Server改造,能够在Client上报的信息中加入container ID等信息。 

  • Eureka服务端需要加入一个过滤器,需要对所有的注册请求进行处理,根据container ID将内部hostname,IP和端口改为外部可以访问的IP和端口。

该方案的挑战:

  • 因为只有容器被创建后才有ID,无法在启动参数中指定,因此应用在容器启动的时候,无法拿到容器的ID。 

  • 对于Eureka Server和Client的改造,无法贡献回社区,因此需要自己维护版本,存在极大的风险。

AWS的EC2 提供了实例元数据和用户数据的API,它可以通过REST API的方式供运行在EC2内部的应用使用。API形式如下:

http://169.254.169.254/latest/meta-data/ 

其中IP地址是固定的一个IP地址。

因此我们也可以提供一个类似的元数据和用户数据API,供容器内部的应用调用。同时为了减少对应用的侵入,我们可以在应用启动之前执行一个脚本来获取相应的信息,并设置到环境变量中,供应用启动后读取并使用,流程如下: 

图 5 方案流程

总结


本文总结了使用Java开发的企业级应用在向微服务架构应用转型过程中,在容器化运行过程中遇到的常见问题、原因分析及解决方法。总结下来,由于容器技术的内在特性,我们需要对应用做一些改造,同时相应的工具如JVM也需要对容器有更好的本地支持。

作者简介:

  • 王天青, DaoCloud首席架构师,负责用新技术帮助企业做下一代应用转型。

  •  夏岩, DaoClozud微服务架构师,帮助企业进行微服务架构转型。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/525818.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux用date指令,Linux中date指令的使用

1. 只输入date就会显示年月日时间二&#xff0e;date的设置 使用 -s设置时间和日期的的命令1..date –s 11:32:342..date –s 20101232就会显示年月日&#xff0c;但这样会把时间清零3..date –s ‘2010-10-2 11:22:21’这样就会显示修改的信息4.. date –s “2010-10-2 11:22…

Swarm的进化和大规模应用

目前在容器编排领域&#xff0c;Kubernetes、Mesos以及Swarm呈现“三分天下”的格局&#xff0c;各自都有着不同的应用场景。短期内&#xff0c;很难看到“一统天下”的局面&#xff0c;本文&#xff0c;来自阿里云高级专家陈萌辉将带你了解阿里内部在推行容器化过程中的一些着…

linux可以用dos命令是什么意思,Linux系统常用命令与DOS命令的类似之处和本质区别各是什么?...

满意答案iedsa3641推荐于 2019.09.13采纳率&#xff1a;56% 等级&#xff1a;8已帮助&#xff1a;361人Linux是一个非常优秀的操作系统&#xff0c;与MS&#xff0d;WINDOWS相比具有可靠、稳定、速度快等优点&#xff0c;且拥有丰富的根据UNIX版本改进的强大功能。下面做一个…

从 0 到 300,Instagram 创始人 CTO 分享工程团队成长的经验

最初&#xff0c;Instagram 被 Facebook 收购时公司只有六个工程师&#xff0c;且都是全栈。本文Instagram 创始人兼 CTO Mike Krieger 分享了创业初期并在资源有限的情况下&#xff0c;人才招聘、技术专攻的实践经验&#xff0c;将时间、精力用在最有价值的地方。以下为译文&a…

深度揭秘Twitter的新一代流处理引擎Heron

流计算又称实时计算&#xff0c;是继以Map-Reduce为代表的批处理之后的又一重要计算模型。随着互联网业务的发展以及数据规模的持续扩大&#xff0c;传统的批处理计算难以有效地对数据进行快速低延迟处理并返回结果。由于数据几乎处于不断增长的状态中&#xff0c;及时处理计算…

linux生成图片快捷方式,在Deepin Linux系统下给AppImage格式软件创建快捷方式的方法...

这两天使用deepin的过程中&#xff0c;无意中发现了一个叫krita的程序&#xff0c;是一个图像处理软件&#xff0c;类似Photoshop&#xff0c;于是就下载krita-4.2.8-x86_64的这个版本。但是麻烦的就是他是一个AppImage格式&#xff0c;每次我打开的时候需要打开相应文件夹中的…

图数据库在CMDB领域的应用

【导语】在上期的图数据库介绍中&#xff0c;我们对什么是图数据库&#xff0c;以及图数据库所擅长的领域做了一个初步的介绍&#xff0c;也收到了众多的反馈和咨询&#xff0c;特别要求我们对图数据库在一些具体行业的应用能做一些深入介绍。为此&#xff0c;从本期文档开始&a…

北理在线作业答案c语言,北理工19春《面向对象程序设计》在线作业【标准答案】...

北理工《面向对象程序设计》在线作业-0003试卷总分:100 得分:0一、 单选题 (共 38 道试题,共 76 分)1.对虚函数的调用()A.一定使用动态联编B.必须使用动态联编C.一定使用静态联编D.不一定使用动态联编2.下列关于派生类的描述中&#xff0c;错误的是()。A.派生类继承了基类的…

从分布式到微服务,深挖Service Mesh

原文&#xff1a;Pattern: Service Mesh &#xff08;作者&#xff0f;Phil Calado&#xff0c;翻译&#xff0f;雁惊寒&#xff0c;责编&#xff0f;魏伟 &#xff09; 摘要&#xff1a;在前一段时间&#xff0c;我们CSDN推出了《深度剖析Service Mesh服务网格新生代Istio》一…

c语言程序设计安徽区笔试部分,2021年安徽省二级C语言程序设计笔试样题-20210419093521.doc-原创力文档...

第1套 C语言程序设计笔试样题一 单项选取题(每题1分&#xff0c;共40分)1.某微型计算机型号规格标有PentiuШ600字样&#xff0c;其中PentiuШ是指 __C____A. 厂家名称 B. 机器名称 C. CPU型号 D. 显示屏名称2.当前微型机上普通使用光驱及光盘&#xff0c;它采用是__C____A. 超…

应用开发者必须了解的Kubernetes网络二三事

Kubernetes网络基本的部署调度单元&#xff1a;Pod Kubernetes中的基本管理单元并非是一个容器&#xff0c;而是一个叫做pod的东西。我们认为部署了一个或多个容器的环境是一个pod单元。通常情况下&#xff0c;它们代表了提供部分服务的单个功能端点。 举两个有效的pods单元为例…

c51编程语言基础习题,《单片机基础》练习题及答案

单片机基础(第3版)第1章计算机基础知识(一)填空题1.十进制数14对应的二进制数表示为(1110B)&#xff0c;十六进制数表示为(0EH)。十进制数-100的补码为(9CH)&#xff0c;100的补码为(64H)。2.在一个非零的无符号二进制整数的末尾加两个0后&#xff0c;形成一个新的无符号二进制…

高可用Docker容器云在58集团的实践

58私有云平台是58同城架构线基于容器技术为内部服务开发的一套业务实例管理平台&#xff0c;支持业务实例按需扩展&#xff0c;秒级伸缩&#xff0c;平台提供友好的用户交互过程&#xff0c;规范化的测试、上线流程&#xff0c;旨在将开发、测试人员从基础环境的配置与管理中解…

c语言程序设计课件数组,数组(C语言程序设计)课件

数组(C语言程序设计)课件 前牙反颌和开颌的原因多由于不良喂养方式和吮指等不良习惯造成&#xff0c;也可因多颗乳磨牙过早缺失&#xff0c;迫使儿童用前牙咀嚼&#xff0c;下颌逐渐前伸移位造成。 前牙反颌和开颌的原因多由于不良喂养方式和吮指等不良习惯造成&#xff0c;也可…

Docker CE/EE 原生支持Kubernetes

在今天的 DockerCon EU (2017) 上&#xff0c;Solomon 宣布 Docker 将原生支持 Kubernetes&#xff0c;也就是说 Kubernetes 将和 Swarm 一样作为 Docker 平台的编排管理系统。这包括 Docker EE、Docker CE 以及 Docker for Mac/Windows 等全平台的支持。 Docker for Mac/Windo…

c语言创建一个hello.txt文件,并检查是否成功,广东工业大学C语言验(上机)任务书2015版.doc...

广东工业大学C语言验(上机)任务书2015版广东工业大学实验(上机)任务书(2015 — 2016 学年度第 1 学期)课程名称 高级语言程序设计 课程设计 实验室名称及地点&#xff1a; 实验2号楼306指导教师&#xff1a; 孟安波、王星华 周次节次实验主要内容每组学生人数具体任务要求65-8熟…

网易云容器服务基于Kubernetes的实践探索

Kubernetes的特点 近年来Docker容器作为一种轻量级虚拟化技术革新了整个IT领域软件开发部署流程&#xff0c;如何高效自动管理容器和相关的计算、存储等资源&#xff0c;将容器技术真正落地上线&#xff0c;则需要一套强大容器编排服务&#xff0c;当前大红大紫的Kubernetes已经…

c语言程序设计中三子棋游戏,C语言实现简易版三子棋游戏

本文实例为大家共享了C语言实现三子棋游戏的详细代码&#xff0c;供大家参考&#xff0c;详细内容如下什么是多文件&#xff1f;多数大型的工程的头文件和源文件非常多&#xff0c;我们也不可能把所有的代码都写在同一个文件里&#xff0c;这样也不方便代码的阅读与维护&#x…

Rancher创始人谈Docker,创新愈发困难,未来将何去何从?

导读:本文由Rancher Labs CEO及联合创始人梁胜博士在参加DockerCon之前和之后写的两篇文章综合整理而成。从各家容器编排方案均很不成熟的初期到三足鼎立的编排之战&#xff0c;到如今kubernetes似已全面胜利&#xff0c;梁胜博士作为整个发展历程的参与者与见证者&#xff0c;…

ld 指令c语言实现,C语言符号、指令表.doc

C语言符号、指令表.docC语语语 言言言 符符符 号号号 控控控 制制制 命命命 令令令 表表表 编译指令 编译指令 说明 i n c l u d e 包含另一个文件 d e f i n e 定义一个宏( m a c r o)或是常量 u n d e f 取消一个宏常量的定义 a s m 和 e n d a s m 在程序中加入汇编语言的程…