OpenShift V3 应用发布部署的简单场景演示

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
简介: 本文讲的是OpenShift V3 应用发布部署的简单场景演示【编者的话】本文是一篇关于OpenShift如何应用在DevOps方面的文章。全文由浅入深,由易到难,通过3种不同场景下的部署,给读者一个对OpenShift功能的全新了解。
本文讲的是OpenShift V3 应用发布部署的简单场景演示【编者的话】本文是一篇关于OpenShift如何应用在DevOps方面的文章。全文由浅入深,由易到难,通过3种不同场景下的部署,给读者一个对OpenShift功能的全新了解。译者以前和有些做容器开发,部署相关工作的同学认为:OpenShift仅仅是在Kubernetes基础之上架设了自己的WebUI,对API和CLI等接口进行了自己的封装(很多kubectl的命令都被oc继承)。但是在接触了OpenShift 1个月后(翻译本文时,我正好接触OpenShift一个月整),我对OpenShift有了全新的认识,特别是读过此文原文后,让我认识到OpenShift之所以能够作为一个PaaS的真正价值所在。

我以前有幸接触过IBM的Bulemix(CloudFoundry),了解过一些基础概念和它大概的运行原理。这段时间经过我对OpenShift的了解,似乎找到了他们之间都作为PaaS的共通之处,也就是它区别于Kubernetes这种容器编排系统的最主要的地方。

【上海站|3天烧脑式微服务架构训练营】培训内容包括:DevOps、微服务、Spring Cloud、Eureka、Ribbon、Feign、Hystrix、Zuul、Spring Cloud Config、Spring Cloud Sleuth等。

1.jpg

概览

如今,对很多公司来说最困难的事情之一就是发布管理。当然我们有很多的方法、工具和技术,但是如何把它们联系在一起并且跨组织功能的工作呢?一个产品的发布不是一个team的事,它会涉及到公司的每一个人。很多公司挣扎于此但效果并不好。这个问题在过去还可以勉强容忍,但现就在就没那么幸运了。当今的公司赖以生存的不仅是创新的能力,而且还有把创新变成产品的能力。我认为创新是比较容易的部分, 在受控的方式下,提供这些创新的产品和服务才是真正的挑战。

通过转移到微服务(micro-services)架构和基于容器技术例如Docker,可以简化或者合理化很多方面的技术。但在OpenShift以前没有一个平台能把它们结合到一起,OpenShift的出现就像隧道尽头的一束光,它允许开发和运维团队在一起工作,而且仍然让他们维护各自关注和控制的领域。在这篇文章中,我们将会看用OpenShift部署应用程序的三个场景,每个场景都会涉及到开发和运维。并且你会从中得到如何使用OpenShift的启发。这些仅仅是一些基本的场景我们也只是蜻蜓点水般带过,但却可以作为在容器世界里应用程序部署或者发布管理的一个起点。

场景 1:开发团队使用运维团队提供的镜像

大多数的运维团队都想控制应用程序的运行环境。并且确保应用程序的运行环境符合所有的安全规则,提供需要的功能并且定期更新。

开发团队关注于创新通过应用程序的功能性,稳定性和性能。

OpenShift允许在两个团队关注各自核心职责的同时,提供一个方法去整合不同团队的输入和输出,最后提供一个端到端的产品发布流程。

在OpenShift里有很多的方法去整合DevOps(开发运维)团队。一个简单的方法就是把开发和运维分开到不同的项目,并且允许开发的应用程序运行在运维提供的环境中,我们将用一个ruby写的hello-world程序作为例子去说明这种情况。

创建项目

为ruby应用创建开发和运维的项目
# oc login -u admin
# oc new-project ruby-ops
# oc new-project ruby-dev 

创建用户

# htpasswd /etc/origin/master/htpasswd dev
# htpasswd /etc/origin/master/htpasswd ops

设置权限

创建三个组ops-edit、dev-view和dev-edit,授予运维组编辑ruby-ops项目的权限,授予开发查看ruby-ops项目和编辑ruby-dev项目的权限。并且让ruby-dev项目可以从拉取ruby-ops项目拉取images。

创建用户和其对应的组
# oadm groups new ops-edit && oadm groups new dev-view && oadm groups new dev-edit
# oadm groups add-users ops-edit ops && oadm groups add-users dev-view dev && \
oadm groups add-users dev-edit dev

关联组到相关的项目,并授权ruby-dev项目可以从ruby-ops拉取images。
# oadm policy add-role-to-group edit ops-edit -n ruby-ops && \
# oadm policy add-role-to-group view dev-view -n ruby-ops && \
# oadm policy add-role-to-group edit dev-edit -n ruby-dev && \
# oadm policy add-role-to-group system:image-puller system:serviceaccounts:ruby-dev -n ruby-ops

Ruby的运行环境

作为运维用户用测试代码创建ruby运行时的image。
# oc login -u ops
# oc project ruby-ops
# oc new-app centos/ruby-22-centos7~https://github.com/openshift/ruby-hello-world.git 

创建应用程序需要的MySQL数据库,并把服务名设置为database。
# oc new-app mysql-ephemeral -p DATABASE_SERVICE_NAME=database
# oc env dc database --list | oc env dc ruby-hello-world -e -

场景 2:生产项目拉取开发项目产生的镜像

如果开发的应用程序根据所需的功能有不同的版本,并且通过了所有的测试,那么就可以部署到其他环境。通常先是质量和测试,然后生成最终的生产版本。在这个简单的例子中,我们用ticket-moster程序,把它从开发环境直接部署到生产环境中。

我们用到了一些场景1中熟悉的概念,这个技术依靠生产环境能够拉取在开发环境中产生的images。在这个场景中我们创建一个了配置并设置一个触发器,它能够在开发更新image之后自动的部署这个带有特定名字或者标签的images到生产环境中。场景1中,这个过程是手动完成的,在场景2中是自动的,在场景3中,我们将看到如何用Jenkins去部署一个比较复杂的,带逐层审批的pipeline流程。

创建项目并设置拉取权限

# oc new-project ticket-monster-dev
# oc new-project ticket-monster-prod
# oc policy add-role-to-group system:image-puller system:serviceaccounts:ticket-monster-prod -n ticket-monster-dev

创建ticket monster项目的开发环境模板

# vi monster.yaml
kind: Template
apiVersion: v1
metadata:
name: monster
annotations:
tags: instant-app,javaee
iconClass: icon-jboss
description: |
Ticket Monster is a moderately complex application that demonstrates how
to build modern applications using JBoss web technologies

parameters:
- name: GIT_URI
value: git://github.com/kenthua/ticket-monster-ose
- name: MYSQL_DATABASE
value: monster
- name: MYSQL_USER
value: monster
- name: MYSQL_PASSWORD
from: '[a-zA-Z0-9]{8}'
generate: expression


objects:
- kind: ImageStream
apiVersion: v1
metadata:
name: monster

-kind: BuildConfig
apiVersion: v1
metadata:
name: monster
spec:
triggers:
- type: Generic
generic:
secret: secret
- type: ImageChange
- type: ConfigChange
strategy:
type: Source
sourceStrategy:
from:
kind: ImageStreamTag
name: jboss-eap64-openshift:latest
namespace: openshift
source:
type: Git
git:
uri: ${GIT_URI}
ref: master
output:
to:
kind: ImageStreamTag
name: monster:latest

-kind: DeploymentConfig
apiVersion: v1
metadata:
name: monster
spec:
replicas: 1
selector:
deploymentConfig: monster
template:
metadata:
labels:
deploymentConfig: monster
name: monster
spec:
containers:
- name: monster
image: monster
ports:
- name: http
containerPort: 8080
- name: jolokia
containerPort: 8778
- name: debug
containerPort: 8787
readinessProbe:
exec:
command:
- /bin/bash
- -c
- /opt/eap/bin/readinessProbe.sh
env:
- name: DB_SERVICE_PREFIX_MAPPING
value: monster-mysql=DB
- name: TX_DATABASE_PREFIX_MAPPING
value: monster-mysql=DB
- name: DB_JNDI
value: java:jboss/datasources/MySQLDS
- name: DB_DATABASE
value: ${MYSQL_DATABASE}
- name: DB_USERNAME
value: ${MYSQL_USER}
- name: DB_PASSWORD
value: ${MYSQL_PASSWORD}
- name: JAVA_OPTS
value: "-Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.logmanager -Djava.awt.headless=true -Djboss.modules.policy-permissions=true"
- name: DEBUG
value: "true"
triggers:
- type: ImageChange
imageChangeParams:
automatic: true
containerNames:
- monster
from:
kind: ImageStream
name: monster

-kind: DeploymentConfig
apiVersion: v1
metadata:
name: monster-mysql
spec:
triggers:
- type: ImageChange
imageChangeParams:
automatic: true
containerNames:
- monster-mysql
from:
kind: ImageStreamTag
name: mysql:latest
namespace: openshift
replicas: 1
selector:
deploymentConfig: monster-mysql
template:
metadata:
labels:
deploymentConfig: monster-mysql
name: monster-mysql
spec:
containers:
- name: monster-mysql
image: mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_USER
value: ${MYSQL_USER}
- name: MYSQL_PASSWORD
value: ${MYSQL_PASSWORD}
- name: MYSQL_DATABASE
value: ${MYSQL_DATABASE}

-kind: Service
apiVersion: v1
metadata:
name: monster
spec:
ports:
- name: http
port: 8080
selector:
deploymentConfig: monster

-kind: Service
apiVersion: v1
metadata:
name: monster-mysql
spec:
ports:
- port: 3306
selector:
deploymentConfig: monster-mysql

-kind: Route
apiVersion: v1
metadata:
name: monster
spec:
to:
name: monster

# oc create -n openshift -f monster.yaml

创建ticket monster项目的生产环境模板

当开发环境中用monster:prod触发了image stream,下面这个触发器将会把image stream部署到生产环境中。
# vi monster-prod.yaml
kind: Template
apiVersion: v1
metadata:
name: monster-prod
annotations:
tags: instant-app,javaee
iconClass: icon-jboss
description: |
Ticket Monster is a moderately complex application that demonstrates how
to build modern applications using JBoss web technologies. This template
is for "production deployments" of Ticket Monster.

parameters:
- name: MYSQL_DATABASE
value: monster
- name: MYSQL_USER
value: monster
- name: MYSQL_PASSWORD
from: '[a-zA-Z0-9]{8}'
generate: expression

objects:
- kind: DeploymentConfig
apiVersion: v1
metadata:
name: monster
spec:
replicas: 3
selector:
deploymentConfig: monster
template:
metadata:
labels:
deploymentConfig: monster
name: monster
spec:
containers:
- name: monster
image: monster
ports:
- name: http
containerPort: 8080
- name: jolokia
containerPort: 8778
readinessProbe:
exec:
command:
- /bin/bash
- -c
- /opt/eap/bin/readinessProbe.sh
env:
- name: DB_SERVICE_PREFIX_MAPPING
value: monster-mysql=DB
- name: TX_DATABASE_PREFIX_MAPPING
value: monster-mysql=DB
- name: DB_JNDI
value: java:jboss/datasources/MySQLDS
- name: DB_DATABASE
value: ${MYSQL_DATABASE}
- name: DB_USERNAME
value: ${MYSQL_USER}
- name: DB_PASSWORD
value: ${MYSQL_PASSWORD}
- name: JAVA_OPTS
value: "-Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.logmanager -Djava.awt.headless=true -Djboss.modules.policy-permissions=true"
triggers:
- type: ImageChange
imageChangeParams:
automatic: true
containerNames:
- monster
from:
kind: ImageStreamTag
name: monster:prod
namespace: ticket-monster-dev

-kind: DeploymentConfig
apiVersion: v1
metadata:
name: monster-mysql
spec:
triggers:
- type: ImageChange
imageChangeParams:
automatic: true
containerNames:
- monster-mysql
from:
kind: ImageStreamTag
name: mysql:latest
namespace: openshift
replicas: 1
selector:
deploymentConfig: monster-mysql
template:
metadata:
labels:
deploymentConfig: monster-mysql
name: monster-mysql
spec:
containers:
- name: monster-mysql
image: mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_USER
value: ${MYSQL_USER}
- name: MYSQL_PASSWORD
value: ${MYSQL_PASSWORD}
- name: MYSQL_DATABASE
value: ${MYSQL_DATABASE}

-kind: Service
apiVersion: v1
metadata:
name: monster
spec:
ports:
- name: http
port: 8080
selector:
deploymentConfig: monster

-kind: Service
apiVersion: v1
metadata:
name: monster-mysql
spec:
ports:
- port: 3306
selector:
deploymentConfig: monster-mysql

-kind: Route
apiVersion: v1
metadata:
name: monster
spec:
to:
name: monster

# oc create -n openshift -f monster-prod.yaml

部署ticket-monster开发环境

用WebUI你可以选择monster的模板。
2.jpg

部署ticket-monster到生产环境

部署ticket-monster生产环境模板(monster-prod)。
3.jpg

你可以看到在开发环境中程序被创建,并且可以通过  http://monster-ticket-monster-dev.apps.lab 访问到它。
4.jpg

你可以看到在生产环境中,虽然数据库已经运行起来了,并且创建了一个服务,但是ticket monster应用却没有启动。这是因为我们创建的生产环境模板会从开发环境中自动拉取这个带有特定名字或者标签images。在开发环境中只部署的规模是1,但是生产环境中部署的规模是4。

部署应用程序的开发版本到生产环境

拉取images stream的spec。
# oc get is monster -o yaml
apiVersion: v1
kind: ImageStream
metadata:
annotations:
openshift.io/image.dockerRepositoryCheck: 2016-08-09T13:37:47Z
creationTimestamp: 2016-08-09T13:14:53Z
generation: 7
name: monster
namespace: ticket-monster-dev
resourceVersion: "107170"
selfLink: /oapi/v1/namespaces/ticket-monster-dev/imagestreams/monster
uid: 42740a3d-5e33-11e6-aa8d-001a4ae42e01
spec:
tags:
- annotations: null
from:
kind: ImageStreamImage
name: monster@sha256:3a48a056a58f50764953ba856d90eba73dd0dfdee10b8cb6837b0fd9461da7f9
generation: 7
importPolicy: {}
name: prod
status:
dockerImageRepository: 172.30.139.50:5000/ticket-monster-dev/monster
tags:
- items:
- created: 2016-08-09T13:26:04Z
dockerImageReference: 172.30.139.50:5000/ticket-monster-dev/monster@sha256:3a48a056a58f50764953ba856d90eba73dd0dfdee10b8cb6837b0fd9461da7f9
generation: 1
image: sha256:3a48a056a58f50764953ba856d90eba73dd0dfdee10b8cb6837b0fd9461da7f9
tag: latest 

一旦你有了一个拉取image stream的说明(就像上面的那个),标记这个images stream为monster:prod。
# oc tag monster@sha256:3a48a056a58f50764953ba856d90eba73dd0dfdee10b8cb6837b0fd9461da7f9 monster:prod 

你可以效验一下这个image stream是否已经生效
# oc get is
NAME DOCKER REPO TAGS UPDATED
monster 172.30.139.50:5000/ticket-monster-dev/monster prod,latest 2 minutes ago

只要这个images stream在ticket-monster-dev中被标记成monster:prod,他就会被部署到生产环境中,并且按照上面的描述把部署规模设置成4。
5.jpg

场景 3:用Jenkins实现AB(应用的名字叫AB)部署

在这个场景中我们将看到如何用Jenkins实现一个简单应用AB的部署。这个场景中用到了在场景1和2中学到的东西。在这个场景中我们会创建一个稍稍有点复杂的三个环境:开发、集成和生产。我们会给应用程序创建2个版本,v1和v2在开发环境里。用Jenkins部属V2版本的应用到集成生产环境。最终我们将在生产环境中展示这个应用从V2版本回滚到V1版本。我很感谢我的同事Torben Jaeger,下面很多内容是他编写的。

创建项目

# oc new-project dev && \
oc new-project int && \
oc new-project prod

设置拉取(pull)的权限

允许int项目从dev项目中拉取images,并且允许prod项目从dev项目和int项目中拉取images。
# oc policy add-role-to-group system:image-puller system:serviceaccounts:int -n dev

# oc policy add-role-to-group system:image-puller system:serviceaccounts:prod -n int

# oc policy add-role-to-group system:image-puller system:serviceaccounts:prod -n dev

在开发项目中设置Jenkins

在WebUI中进入dev项目,选择添加jenkins-ephemeral。
6.jpg

克隆Github的repository

# git clone https://github.com/ktenzer/openshift-demo.git

更新Jenkins的认证tokens

从OpenShift命令获得认证token,这个token可以让Jenkins访问OpenShift环境。你需要更新它
# oc login -u admin
# oc whoami -t
DMzhKyEN87DZiDYV6i1d8L8NL2e6gFVFPpT5FnozKtU

更新下面的Jenkins任务,并且用上面的token替换其中的authToken和destinationAuthToken
# ls jenkins-jobs/
promote-int.xml promote-prod.xml rel-v2.xml rollback-prod.xml

配置三个环境

用你的token更新三个模板并创建三个环境。
# cd openshift-demo

# oc create -f template.json -n dev

# oc create -f acceptance.template.json -n int

# oc create -f production.template.json -n prod

在开发项目中部署nodejs 的hello-world应用

把环境
# oc new-app -f template.json -n dev

这个模板创建了两个版本的应用v1-ab和v2-ab。
7.jpg

在开发项目中测试应用程序

通过http或者curl工具去连接v1-ab因该可以打印出“hello World!”。如果连接v2-ab可以打印出”hello World,welcome to Frankfurt!“。

把V1从开发项目部署到集成项目

把v1的image打一个标记(tag)部署到集成项目。当镜像acceptance:lastest被更新时触发器会部署它到集成项目里。你会看到v1版本的pod被启动并运行起来。
oc tag v1:latest v1:1.0 -n dev
oc tag dev/v1:1.0 acceptance:v1 -n int
oc tag acceptance:v1 acceptance:latest -n int

把v1从集成项目部署到生产项目

把v1打一个标记(tag)部署到生产项目。当镜像production:latest被更新时生产环境中的触发器会部署它到生产项目中。
oc tag int/acceptance:v1 production:v1 -n prod
oc tag production:v1 production:latest -n prod

注意应用被署了4个pod并且代码版本是v1。再次说明一下,这里所有的定义都来自之前的模板。
8.jpg

配置Jenkins

你已经知道了如何手动的,用打标记和设置触发器的方法去部署一个应用程序。下面我们来一点复杂的,通过在jenkins里安装OpenShift的插件去从新编排一下刚才的任务。这次我们将部署v2版本到集成项目和开发项目

这里可以得到jenkins中的4个job:第一个的作用是创建v2版的应用程序,第二个用来从开发部署集成,第三个实现了从集成到生产,第四个可以在生产项目中把应用从v2回滚到v1。
# curl -k -u admin:password -XPOST -d @jenkins-jobs/rel-v2.xml 'https://jenkins-dev.apps.lab/createItem?name=rel-v2' -H "Content-Type: application/xml"
# curl -k -u admin:password -XPOST -d @jenkins-jobs/promote-int.xml 'https://jenkins-dev.apps.lab/createItem?name=promote-int' -H "Content-Type: application/xml"
# curl -k -u admin:password -XPOST -d @jenkins-jobs/promote-prod.xml 'https://jenkins-dev.apps.lab/createItem?name=promote-prod' -H "Content-Type: application/xml"
# curl -k -u admin:password -XPOST -d @jenkins-jobs/rollback-prod.xml 'https://jenkins-dev.apps.lab/createItem?name=rollback-prod' -H "Content-Type: application/xml"

创建4个job,并且登陆到Jenkins,用户名和密码是:admin和password。
9.jpg

这里可以修改一点v2的代码并且开始build

为了让这个代码工作,你需要在Github上fork一个nodejs-ex项目到你自己的账户下,并且更新template.json文件,然后用这个文件从新部署一下开发环境。
"source": {
"type": "Git",
"git": {
"uri": "https://github.com/ktenzer/nodejs-ex.git",
"ref": "master"
}, 

# git clone https://github.com/ktenzer/nodejs-ex

# cd nodejs-ex

Checkout到v2的branch并且commit

# git checkout v2
# vi index.html
Hello World, welcome to Munich!

提交修改

# git commit -a -m "updated to munich"
# git push origin v2

在Jenkins里运行rhel-v2这个build。
10.jpg

如果你克隆了nodejs-ex的repository,这时你可以通过URL看到你的修改已经生效了。

把v2从开发项目部署到集成项目

在Jenkins里运行promote-int这个build,你会看到有一个v2版本的pod在v1版本后启动。
11.jpg

从集成环境部署v2到生产环境

我们在这里深入的看一下在hood的后面实际发生了些什么。

可以用curl观察到应用程序是如何从v1切换到v2的。
# for i in {1..10000};do curl prod-ab.apps.lab; sleep 1;done

在Jenkins里运行promote-prod这个build。
12.jpg

部署已经开始了,v2版本在v1版本之后启动。此时应用的服务仍然还是v1。
13.jpg

两个v2版本的pod运行起来了,探针(readiness)会去检查这两个pod,以确保v2应用提供的服务可用。然后把v1的pod逐个关闭。
14.jpg

当v2版本的4个pod都运行起来的时候,v1版本的pod的数量是0。在这个过程中我们可以看到有一段时间,v1和v2是同时响应请求的。
15.jpg

现在只有v2版本的pod在运行了,同时AB的部署也完成了。
16.jpg

回滚

现在假设我们不满意v2版本,想回到旧的v1版本去。

在Jenkins里运行rollback-prod这个build。
17.jpg

现在我们观察到了同样的事情,只不过是v2切换到了v1。
18.jpg

可以用下面的命令把集成环境中的v2回滚到v1。
# oc tag dev/v1:latest acceptance:latest -n int

总结

在这片文章中我们学到了如何在OpenShift中部署一个简单的应用程序并且和Jenkins集成去管理应用的发布。OpenShift有很多的功能值得你使用它,我们紧紧是用了其中的一小部分。使用Jenkins你可以创建一个非常复杂的build pipelines,它能让你不仅能够控制而且可以看到应用部署的过程。我们看到了一种典型的部署方式就是部署应用AB,但还有很多其他的方式比如blue-green或者canary。在以后的文章中我会演示OpenShift中其他的部署模式。请分享你的经验和成果。我希望这篇文章能够帮到你。

Happy OpenShifting!

原文链接:OpenShift v3: Basic Release Deployment Scenarios(翻译:王晓轩,校对:许小平)

原文发布时间为:2017-03-23

本文作者:王晓轩

本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。

原文标题:OpenShift V3 应用发布部署的简单场景演示

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
Kubernetes 网络协议 Cloud Native
Kubernetes网络问题排查分享两则(1)——calico特定场景下的网络性能问题
在对Kubernetes项目[kosmos](https://github.com/kosmos-io/kosmos)与Calico网络性能进行对比测试时,发现kosmos在跨集群容器网络的性能显著优于Calico的集群内网络(约6Gbit/s对比2.9Gbit/s)。物理机网络测试达到9.38Gbit/s,显示Calico有68%的性能损耗。问题定位到网卡的checksum/offload参数,尝试用`ethtool`调整后虽短暂提升,但随后恢复原状。转载自:https://mp.weixin.qq.com/s/XsQZCSqZAXJK46zqc7IpLw
|
SpringCloudAlibaba JavaScript Dubbo
【SpringCloud Alibaba系列】Dubbo dubbo-admin安装教程篇
本文介绍了 Dubbo-Admin 的安装和使用步骤。Dubbo-Admin 是一个前后端分离的项目,前端基于 Vue,后端基于 Spring Boot。安装前需确保开发环境(Windows 10)已安装 JDK、Maven 和 Node.js,并在 Linux CentOS 7 上部署 Zookeeper 作为注册中心。
3843 1
【SpringCloud Alibaba系列】Dubbo dubbo-admin安装教程篇
|
Java jenkins 持续交付
Jenkins全局工具配置(JDK、Maven、Maven插件)
Jenkins全局工具配置(JDK、Maven、Maven插件)
1381 0
|
监控 Java Linux
问题回顾:Unable to start web server; nested exception is org.springframework.boot.web.server.
解决“Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException”这一问题,关键在于细致的故障诊断和逻辑推理。从日志入手,逐步排查端口冲突、依赖问题、配置错误、资源限制、代码bug以及版本兼容性等多个方面,最终定位并解决根本原因。每一步操作都应谨慎且有针对性,确保修改一处后充分测试,避免引入新的问题。
4029 0
|
开发者
Elasticsearch7.15.2 安装ik7.15.2中文分词器报错解决方案
问题描述 下载 elasticsearch-7.15.2 及分词器 elasticsearch-analysis-ik-7.15.2 运行bin/elasticsearch 报以下错误 Exception in thread "main" java.nio.file.NotDirectoryException: /Users/lishuo/ElasticStack/elasticsearch-7.15.2/plugins/.DS_Store at java.base/sun.nio.fs.UnixFileSystemProvider.newDirectoryStream(UnixFileSy
idea没有Maven运行界面怎么办
idea没有Maven运行界面怎么办
Invalid bound statement (not found)错误【已解决】
Invalid bound statement (not found)错误【已解决】
2851 1
|
Arthas Kubernetes 调度
一次线上Xxl-Job定时任务调度失败的排查与解决
在XXL-JOB系统中,每分钟执行一次的任务出现调度异常:首次调度成功,第二次调度失败,但第三次调度显示的是第二次任务的执行时间。问题源于调度中心发送的心跳请求未得到执行器响应,导致连接被Envoy代理关闭。Envoy在等待心跳响应时,后续调度请求被阻塞,直至连接因超时关闭。调度中心收到503响应后也会关闭连接,从而影响第三次调度。解决方案是更新执行器以处理心跳请求或配置Istio Sidecar以绕过Envoy代理特定流量。
4097 1
|
Java
IDEA 启动服务报错:Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun 解决方案
IDEA 启动服务报错:Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun 解决方案
8314 2

热门文章

最新文章