基于SpringBoot工程开发Docker化微服务

2023-11-02

目录

1. 微服务容器化治理的优缺点

1.1 微服务容器化的优点

 1.2 微服务容器化的缺点

2. 微服务的两种模式

2.1 Microservice SDK

2.2 ServiceMesh

3. 微服务容器化治理的推荐模式

4.Windows下开发容器化微服务(非K8S)

4.1 开发环境

4.2 代码框架

4.2.1 SpringBoot开发框架

4.2.2 增加docker支持

4.3 运行Docker化的微服务

5. 部署基于SpringBoot的微服务容器到K8S

5.1 微服务容器在K8S上的部署架构

5.1.1 K8S集群内服务访问方式

5.1.2 K8S集群外访问K8S集群内服务的方式

5.1.3 采用NodePort模式部署微服务到K8S

5.1.4 采用LoadBalancer模式部署微服务到K8S

6 创建基于K8S的ServiceMesh


1. 微服务容器化治理的优缺点

1.1 微服务容器化的优点

       最近一直在研究在项目中推进Docker化的可行性,原来项目组采用的技术栈是SpringCloud,而Docker化带来的价值主要包括以下几个SpringCloud体系所不具备的优势:

  1. 产品的安装部署和版本发布效率会提升。这里的背景是我们的产品主要是需要能够为不同的客户进行本地化部署,而不是目前主要的互联网公司的一个网站的模式。用SpringCloud,则产品的安装部署主要是用自己写安装部署脚本,或开发安装部署工具,较为复杂。
  2. 产品的动态伸缩能力会更强。基于K8S可以实现Docker容器的动态伸缩,而SpringCloud体系实现该能力要难度高一些。
  3. 灰度发布能力会更强。这点SpringCloud也能实现,但是需要借助第三方工具,且相对于K8S,实现起来会比较复杂。
  4. 写代码时可以更聚焦业务,不需要把微服务的治理和业务代码耦合。而SpringCloud体系本身需要业务代码和微服务治理体系耦合,如微服务需要知道Nacos,SpringCloud的SDK中也要求微服务对微服务治理相关的组件要了解,并做好配置。

 1.2 微服务容器化的缺点

       当然,采用全面的Docker化也存在一些缺点:

  1. 第一就是运维成本的升高。采用K8S对微服务进行治理,虽然将业务代码和微服务管理进行了剥离,但是K8S本质上是将微服务管理IaaS化了,所以对K8S运维的要求比较高,对人员技能要求也比较高。
  2. 第二就是这种模式并不太成熟。K8S对微服务的管理,本质上是ServiceMesh模式,而非SpringCloud的Microservice SDK模式。而ServiceMesh模式目前主流的技术方案是Istio+K8S,技术成熟度还不太高。

2. 微服务的两种模式

       刚刚学习Docker和K8S的时候,习惯性的想把SpringCloud的微服务治理体系装到K8S里面。但直觉上一直认为这种模式很别扭,因为K8S也有类似SpringCloud的完整微服务治理体系,如etcd、API Server等。只到后来看到一个华为大神写的文章《最佳实践:从Spring Cloud 到 Istio》(https://zhuanlan.zhihu.com/p/358891699),才恍然大悟:SpringCloud是Microservice SDK模式,K8S时ServiceMesh模式;两者完全是不同的两种设计思想,强行把他们揉到一起,有点儿要把马车和汽车焊在一起的赶脚。

2.1 Microservice SDK

       微服务SDK曾经是一个常用的解决方案。将微服务化后通用的能力封装在一个开发框架中,开发者使用这个框架开发写自己的业务代码,生成的微服务自然就内置了这些能力。这种模式中,业务代码和微服务框架代码是耦合在一起的的。SpringCloud就是这种模式的典型代表,采用SpringCloud框架,业务代码和SpringCloud框架的Nacos、Sentinel、SpringCloud Gateway等是强耦合的,业务代码的Maven工程和SpringCloud的这些工具集是强绑定的。如果后续不采用SpringCloud框架了,那业务代码基本上也要进行大面积的重构。

       这里适当展开一下,SpringCloud本身包含最核心的Spring Framework,和简化配置开发能力的SpringBoot框架,以及SpringCloud框架。

      早期SpringCloud大部分基于Netflix的版本,采用Eureka、Ribbon、Hystrix、Zuul/Zuul2、SpringCloud Config等工具库来实现微服务治理的基本框架。但随着框架的演进,Netflix版本目前已经不再维护了。

       当前业界采用的主要是SpringCloudAlibaba版本,是阿里基于SpringCloud开发的版本,采用Nacos、Sentinel、SpringCloud Gateway等工具实现了微服务治理的基本框架。

       目前SpringCloudAlibaba版本的主要工具库如下图所示。

2.2 ServiceMesh

       ServiceMesh,也就是常说的服务网格,是通过另一种形态提供治理能力。不同于SDK方式,服务治理的能力在一个独立的代理进程中提供,完全和业务代码开发解耦。从本质上讲,微服务SDK是一种开发框架,而ServiceMesh是一个基础设施。

       当前最流行的ServiceMesh模式是K8S + Istio,采用SideCar模式实现业务代码和服务治理的解耦。

3. 微服务容器化治理的推荐模式

       根据上一章的说明,大家应该可以看到,如果要将微服务容器化,建议大家采用ServiceMesh模式。在该模式下,可以灵活的采用不同的开发语言,如Golang、Node.js、Python、Java等;同时也不需要再绑定SpringCloud等微服务框架,只需要聚焦最核心的业务代码开发既可。

       仍然以Java语言为例,采用ServiceMesh模式,只需要采用Maven + SpringBoot框架开发既可。

4.Windows下开发容器化微服务(非K8S)

       按照前面的总结,我们将采用SpringBoot为开发框架,搭建容器化的微服务环境。

4.1 开发环境

       开发语言:Java

       代码框架:Maven + SpringBoot

       开发工具:VSCode

       开发插件:Extension Pack for Java, Spring Boot Extension Pack, Docker

       Docker环境:Docker Desktop

       K8S环境:利用Docker Desktop中自带的对Kubernetes的支持

       具体的安装部署这里不再赘述,大家可以上网搜索。配置国内的Maven库和Docker Registry也不再赘述,大家网上搜索既可。

       这里重点要说一下VSCode真的是很不错的开发环境,微软官方的开发插件对开发效率有极大的提升,上述几个开发插件大家一定要用好。

4.2 代码框架

4.2.1 SpringBoot开发框架

       VSCode的Extension Pack for Java和Spring Boot Extension Pack对SpringBoot的Maven工程创建支持非常好,可以在VSCode中按照引导一步步创建工程即可。

        这里建议创建Spring Boot类型的工程,然后再选择Maven类型工程,再按提示选择。

       不建议创建Maven类型的工程,然后再选择SpringBoot类型的archetype。因为这种模式,可选的archetype比较杂,对SpringBoot的版本配置也比较乱,需要手动做不少调整。

4.2.2 增加docker支持

4.2.2.1 pom中增加dockerfile-maven-plugin

       这里用到了dockerfile-maven-plugin插件,来为maven工程增加docker能力的支持。该插件是spotify公司开发的插件,将docker和maven进行了集成,可以在maven工程中,基于Dockerfile的配置,将工程打包成docker镜像,并支持push和tag等功能。具体的pom配置请见下图。

 

        需要注意的是,该插件的前身是docker-maven-plugin,官方已经声明docker-maven-plugin不再继续演进,建议开发者切换到dockerfile-maven-plugin。目前往上有大量的docker-maven-plugin的教程,需要大家注意不要被误导采用老旧的插件。

4.2.2.2 工程中增加Dockerfile

       在VScode中按F1键,输入Docker: Add Docker File to Workspace,可以在工程中增加Dockerfile。默认增加Dockerfile到根目录,如果手动添加到其他目录,会出现编译错误。

       Dockerfile创建后,VSCode的Docker插件会根据Maven工程自动初始化Dockerfile的内容,如下图所示。

       这里需要注意的是,Docker镜像打包时,需要有底层OS和JDK的支持,开发人员可以根据自己工程采用的java版本,在hub.docker.com上搜索对应的底层docker依赖,并写到Dockerfile的FROM部分。如上图所示,这里用到的是JDK 19,在hub.docker.com中可以搜到很多版本,这里选择的事openjdk: 19-jdk-alpine。选择openjdk是为了避免被Oracle收费,19-jdk表示jdk 19版本,alpine表示基于alpine的linux,这个版本的linux比较小,占用的资源较少,连同jdk合计185.34MB。

       另外,根据工程的需要,刻在Dockerfile中通过EXPOSE port,开放指定端口,以便外部访问。示例工程中开放到是8080端口。

       Dockerfile配置完成后,启动本地的Docker Desktop,再执行Maven编译,可以生成docker image,并自动推送到Docker Desktop。如下图所示:

        至此,该工程的docker文件已编译打包完成,并成功push到本地的docker库上。

4.3 运行Docker化的微服务

       基于Docker Desktop可以启动上面创建的微服务的Docker容器,启动时需要配置一下端口映射,将容器暴露的端口映射到本地端口,以便可以通过本地浏览器访问发布的docker服务。具体操作可以用Docker Desktop提供的功能设置。

       如下图所示,选择要运行的image,点击Run按钮。

 

        在弹出的窗口中可以配置Container name和端口映射,完成后点击Run:

       执行Run后,可以在Docker Desktop上看到启动日志,如下图所示,启动正常。

       Terminal标签是该Container的shell,可以在里面执行shell命令,如下图所示。

 

5. 部署基于SpringBoot的微服务容器到K8S

       根据前面章节的步骤,我们创建出了基于SpringBoot框架的微服务的Docker image,并上传到了本地Repository上。本章我们将前面创建的微服务部署到K8S上,并能通过外部访问。

       本文主要介绍具体的实操,对于K8S的架构和原理不做深入介绍。如果需要了解,请访问K8S官网(https://kubernetes.io),上面有详细的学习文档。

5.1 微服务容器在K8S上的部署架构

       由于K8S内部有自己的网络结构,K8S集群外部访问K8S上部署的服务时有多种方法。这里先简单介绍一下K8S内部署的服务的内外部访问方式,以便于大家理解本文示例的部署架构。

       在往下看之前,请大家先自行学习K8S的网络结构,理解Pod、Service、Node几个概念,以及各自的IP和Port分别是在哪个子网中,是否和外网相通等概念。

5.1.1 K8S集群内服务访问方式

       K8S集群内的Pod之间,可以通过两种方式互相访问:

5.1.1.1 通过ServiceIP访问

       ServiceIP可以通过kubectl get svc命令获取。

5.1.1.2 通过服务名访问

       通过服务名访问,会通过K8S的DNS进行解析。访问方式有2种:

       1.在同一个Namespace下的服务,通过http://servicename:port来互相访问。

       2.在不同Namespace下的服务,通过http://servicename.namespace:port来互相访问。

5.1.2 K8S集群外访问K8S集群内服务的方式

5.1.2.1 通过hostNetwork访问

       在Pod中设置hostNetwork: true,即可通过http://NodeIP:PodPort来访问。

       该方式由于Pod动态启停,部署到的Node会变化,NodeIP会变化,所以只适合临时访问,或者每一个Node只能启动一个同deployment的Pod的情况下。

5.1.2.2 通过hostPort访问

       通过将Pod的端口直接映射为Node上的端口,即可通过http://NodeIP:NodePort来访问。

       该方式需要维护端口映射关系,不然Pod重新调度后端口的变化会导致地址失效。所以也只适合临时访问。

5.1.2.3 通过NodePort访问

       为Pod创建NodePort类型的Service后,即可通过http://NodeIP:PodPort来访问。

       该方式下,NodeIP和PodPort是固定的,不会随着K8S的动态调度而发生变化。

5.1.2.4 通过LoadBalancer访问

       这种方式一般是部署到华为云、阿里云等公有云上,利用他们提供的LoadBalancer,来通过外网IP和Port来访问。

       当然,也可以通过MetalLB等第三方中间件实现本地化部署的LoadBalancer。

5.1.2.5 通过Ingress访问

       通过部署K8S官网的Ingress-Nginx-Controller,可以配置以域名的方式访问K8S上部署的服务。

5.1.3 采用NodePort模式部署微服务到K8S

       这里先采用NodePort的方式将微服务部署K8S上,部署架构大体如下图所示:

       上图为网上找到的一张图,对NodePort的描述比较形象。如图所示,NodePort模式下,只能通过一个固定的Node的IP+Port来访问本Node中部署的Pod上的服务,并未经过API Server,也不支持负载均衡。如果Pod被部署到多个Node上,实际上只会访问NodeIP对应的一个Node上,无法实现多个Node之间的负载均衡。

       由于在Service定义时,会通过nodePort配置,把K8S内部的服务映射到Node本地的端口上,所有可以使用Node的本地IP加上映射出的外部端口(nodePort)实现外网访问。

       整个部署过程,主要通过deployment文件进行相应的配置,并通过kubectl apply命令来完成部署。

 5.1.3.1 创建Namespace

       为了将微服务统一部署到一个Namespace下,首先需要通过yaml文件创建Namespace,如下图所示。

       然后执行kubectl apply -f namespace.yaml命令,可以创建名称为accchn的Namespace。如下图所示。 

5.1.3.2 通过deployment文件部署pod

       编写微服部署到K8S的deployment.yaml文件,内容如下图所示。其中,spec.containers.image,按照第4章生成的Docker Image的实际路径获取。spec.containers.ports.containerPort配置程8080,因为该Docker容器下的微服务暴露了8080端口。 

       然后执行kubectl apply -f deployment.yaml,来部署微服务,如下图所示。 

5.1.3.3 创建访问该微服务的Service 

       编写相应的Service部署的yaml文件,如下图所示。通过配置spec.ports.nodePort,将服务端口映射到Node服务器本地的30777端口,可以直接通过Node的外网IP:30777来访问。

       执行kubectl apply -f service.yaml来创建该服务。

 

5.1.3.4 通过NodePort方式访问部署好的微服务 

        通过前面的3个步骤,将服务映射到了Node上。因为我们是在单机的Docker Desktop上部署了K8S,所以Node的外网IP就是localhost。通过http://localhost:30777即可访问部署好的微服务。

5.1.3.5 该模式存在的问题

       由于采用了NodePort的模式,并未实现LoadBalancer。后续继续学习LoadBalancer的部署模式,从而实现基于外网IP的、不需要域名的全面负载均衡。

       有同学可能会问,为什么不直接用Ingress?主要是因为Ingress必须要映射域名,而我自己的测试环境,没有公网IP,同时配置host文件又会增加跨用户/开发设备调测的复杂度,不利于刚刚接触项目的开发人员更快的熟悉环境。所以才会研究LoadBalancer的模式。

 

5.1.4 采用LoadBalancer模式部署微服务到K8S

(未完待续。。。)

6 创建基于K8S的ServiceMesh

(未完待续。。。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于SpringBoot工程开发Docker化微服务 的相关文章

随机推荐

  • 微信小程序的this.setData()方法更新二级属性数据

    在用this setData 更新数据时 如果要更新的数据如下 data person name xiaoming occupation front end engineer 要把person name更新为 xiaogang 我们如果通过
  • ElementUI 之 el-tabs添加自定义按钮

  • oauth2 jwt token 返回accessToken对象中携带用户字段信息

    oauth2 源码中用户信息只返回用户名称 现有需求要求返回userId 只能重写某些方法 server端和client端都要修改 方法一 结果 userId 封装在token中 需要解析access token才能看到 但是经测试发现 使
  • 【Java基础】Scanner中next与nextLine区别

    Scanner概念 scanner可以用来获取用户的输入 八个基本数据类型除字符外都可以输入 另外输入字符串有两种方式next与nextLine 接下来介绍他们的区别 1 next与nextLine的区别 1 1 区别一 String st
  • 上传AppStore 报错 ERRPR ITMS-90700

    小萌在解决乱七八糟的警告的时候 加入了Background Modes 然后就报了上述错误 把这个去掉之后重新打包 然后就顺利上线了
  • win10上python3密码库pycryptodome使用

    环境安装 python 在 Windows下使用密码库时要安装的是pycryptodome模块 pip install pycryptodome python 在 Linux下使用密码库时要安装的是pycrypto模块 pip instal
  • C/C++中字符串数组及strlen()和sizeof()区别

    1 字符串数组 标准C语言中没有字符串 string 类型 而只是在C 后添加了字符串string类 但是并不属于基础数据类型 只是类功能很强大 得到广泛应用 所以一般我们平时处理字符串 即字符序列 使用的都是字符串数组 1 1 字符串数组
  • 提升企业网络安全的重要性:EventLog Analyzer的角色

    在今天的数字时代 企业对网络安全的需求愈发迫切 随着互联网的不断发展和企业信息的数字化 网络攻击的威胁也不断增加 为了保护企业数据和系统的完整性 网络安全已经成为每个企业都必须认真对待的重要问题 在这个背景下 我们不得不提到一种强大的工具
  • SSM+mysql课程题库管理系统-计算机毕业设计源码18655

    摘 要 随着科学技术的飞速发展 各行各业都在努力与现代先进技术接轨 通过科技手段提高自身的优势 对于课程题库管理系统当然也不能排除在外 随着网络技术的不断成熟 带动了课程题库管理系统 它彻底改变了过去传统的管理方式 不仅使服务管理难度变低了
  • ENVI_IDL: 基础语法详解

    01 题目 02 代码说明 题目本身很简单 但是我自己加了一些东西进去增加难度 主要包括print函数的封装 格式化字符串 但是不影响代码的阅读 注 对于没有语言基础的人而言相对阅读困难 但是由于IDL是解释型语言 类似于Python 所以
  • 【PyTorch】如何取得预训练模型的标签label列表(以 Alexnet 在 ImageNet 上的预训练模型为例)

    PyTorch 预训练模型 PyTorch 提供过了大量的预训练模型可以直接拿来使用 或者进行增量训练和微调 拿 Alexnet 的预训练模型为例 import torch import torchvision model torchvis
  • Ubuntu系统下 .7z 文件压缩解压命令

    安装软件 sudo apt install p7zip full 解压文件 解压命令 7z x filename 7z r o test 参数说明 7z 解压缩文件命令 x 表示解压缩 r 表示递归解压缩所有的子文件夹 o 指定解压到的那个
  • JProfile 分析OOM hprof文件

    JProfile 分析OOM OutOfMemoryError 1 JVM组成 首先要明白JVM组成 方法区 非堆 Method Area No Heap Java栈 虚拟机栈 VM Stack Java Stack 本地方法栈 Nativ
  • 解决浏览器”您的连接不是私密链接“的问题!最详细!!!

    Google的Chorom浏览器打开baidu主页 显示 您的连接不是私密连接 攻击者可能会试图从 x x x x 窃取您的信息 例如 密码 通讯内容或信用卡信息 了解详情 NET ERR CERT INVALID 网上找了很多人的解决办法
  • LeetCode 465. Optimal Account Balancing

    原题网址 https leetcode com problems optimal account balancing A group of friends went on holiday and sometimes lent each ot
  • linux ftp查看用户目录权限,linux 指定ftp用户 特定目录及权限

    Linux添加FTP用户并设置权限 在linux中添加ftp用户 并设置相应的权限 操作步骤如下 1 环境 ftp为vsftp 被限制用户名为test 被限制路径为 home test 2 建用户 在root用户下 useradd d ho
  • MyBatis-Plus——代码自动生成器

    哈喽 大家好 我是 一位上进心十足的 Java领域博主 的写作风格 喜欢用 通俗易懂 的文笔去讲解每一个知识点 而不喜欢用 高大上 的官方陈述 博客的领域是 面向后端技术 的学习 未来会持续更新更多的 后端技术 以及 学习心得 如果有对 后
  • Cesium中文教程-Cesium Workshop(一)

    欢迎来到Cesium社区 非常高兴能加入我们 为了帮助您开发自己的web地图应用程序 本教程将从头到尾介绍如何开发一款简单但有广泛影响的Cesium应用程序 本教程将接触到许多CesiumJS API重要的方面 但这并不意味着包括所有 Ce
  • openLDAP安装卸载与重装

    安装卸载 安装与卸载点击跳转 openLDAP与phpldapadmin安装点击跳转 重装问题 点击跳转
  • 基于SpringBoot工程开发Docker化微服务

    目录 1 微服务容器化治理的优缺点 1 1 微服务容器化的优点 1 2 微服务容器化的缺点 2 微服务的两种模式 2 1 Microservice SDK 2 2 ServiceMesh 3 微服务容器化治理的推荐模式 4 Windows下