SpringBoot 实战 之 优雅终止服务的方法
由于 SpringBoot 是一个微服务框架,其生产部署的方式也需要尽可能的简单,与常规的 Web 应用有着一个巨大的不同之处,它可以内嵌一个 Web 容器,如:Tomcat、Jetty等,不再需要将应用打包成容器规定的特定形式。
对于 SpringBoot 来说,打包成一个简单的 Jar 包直接使用 java -jar即可启动,这是一种非常优雅的方式,但同时也带来了一定的问题,如:应用如何停止?在过去,应用程序是部署在特定的容器中的,使用容器提供的脚本可以优雅停服,但现在容器被内嵌了,脚本没有了,怎么办?直接 kill 是一种方式,但未免显得太过粗鲁,而且可能带来许多意想不到的问题。
既然我们能想到问题,框架的制定者也会想到,那么他们有没有为我们准备好解决方案呢?答案是有的,下面我介绍下我了解到的几种方案。
1. 使用 Endpoints
在 SpringBoot 官方文档的第4部分中介绍了为应用发布生产准备的各种特性,其中,通过 Actuator 的 HTTP Endpoint,开发人员可以方便地对应用的监控与管理。
引入指定的 starter 包:
"org.springframework.boot:spring-boot-starter-actuator:${springbootVersion}"
在 application.yml 中打开如下两个配置,即可实现通过 Http 请求停止应用
management: security: enabled: false endpoints: shutdown: enabled: true
操作命令如下:
curl -X POST http://host:port/shutdown
但这种方式有一个非常严重的问题,那就是任意人都可以控制应用的停止,这对于一个生产应用无疑是不可接受的。有些人可能会想,现在的链接地址太简单了,非维护人员也可以轻易地猜出来,如果使用一个非常复杂的地址是否可以避免这个问题。很好,这个提议不错,那我们再看看 SpringBoot 为我们提供的相关配置。
endpoints: shutdown: enabled: true path: /xxx
配置完成后,上面的命令就不可用了,需更新命令为:
curl -X POST http://host:port/xxx
其中的/xxx当然只是我随手设置的一个,你可以设置任意的地址。虽然安全性高了那么一点,但这样的安全级别仍然是无法应用到生产环境的。那是否还有其它的防护手段呢?有,除了修改shutdown的路径外,我们还可以给所有的管理操作加上一个统一的上下文,配置独立的端口,并限制指定IP访问(一般限定为本机),配置如下:
management: security: enabled: false port: 9001 address: 127.0.0.1 context-path: /admin
变更后的停服命令为:
curl -X POST http://127.0.0.1:9001/admin/xxx
这样其实已经足够安全了,为了进一步的保证系统的安全,再给其加上一层 HTTP Basic Auth。
增加 Security 依赖:
"org.springframework.boot:spring-boot-starter-security:${springbootVersion}"
修改配置文件如下:
endpoints: shutdown: enabled: true path: /xxx management: security: enabled: true port: 9001 address: 127.0.0.1 context-path: /admin security: basic: enabled: true path: /admin user: name: root password: 123456
配置完成后,最终的停服命令为:
curl -X POST -u root:123456 http://127.0.0.1:9001/admin/xxx
2. 注册为系统服务
除了使用 java -jar 运行 SpringBoot 应用程序外,还可以轻松地用 init.d 或 systemd 注册成 Linux/Unix 系统服务,这使得在生产环境中,安装和管理 SpringBoot 应用程序变得非常简单。
在Maven工程里面,为了创建一个“完全可执行”的 jar,需要引入如下插件:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.5.2.RELEASE</version> <configuration> <executable>true</executable> </configuration> </plugin>
在 Gradle 工程里面,等效配置如下:
plugins { id 'org.springframework.boot' version '1.5.2.RELEASE' } springBoot { executable = true }
配置完成后,即可以通过 ./application-name.jar 运行构建好的应用程序。
最后,我们需要将打包好的应用程序安装成一个init.d 服务,这样就可以很方便地使用 Unix/Linux 进行管理了。操作方式很简单,只需要将应用程序简单的链接到 init.d 即可(其中funda为我自己的应用名,自己实验时需要视情况替换)。
ln -s /app/funda/funda.jar /etc/init.d/funda
检查链接是否建立成功
ls -l /etc/init.d/funda
启动服务,应用日志可查看文件 /var/log/funda.log
service funda start
其它常用命令
# 查看应用运行状态 service funda status # 停止应用 service funda stop
问题汇总:
在链接成功后,应用启动时,无法成功启动,提示Unable to find Java,使用如下命令将Jdk的java命令链接到/sbin/java即可。
ln -s /usr/local/jdk1.8.0_131/bin/java /sbin/java
参考链接:
Endpoints
Monitoring and management over HTTP
Unix/Linux services
Unable to find Java #5690
项目链接:
Github : https://github.com/qchery/funda
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
- Spring Boot Actuator监控页面报错解决
- Spring Cloud中如何优雅的使用Feign调用接口
- Spring Cloud Eureka 集群高可用
- Spring Cloud Eureka 增加权限认证
- Spring Cloud Eureka 初探
- 房价网是怎么使用分布式作业框架elastic-job
- Spring Cloud Sleuth Zipkin 展示追踪数据
- Spring cloud Zuul Filter 使用小经验
- Spring Cloud Eureka REST 接口
- Spring Cloud Eureka 控制台快速查看Swagger API文档
- Spring Cloud Feign 启动UnsatisfiedDependencyException
- Spring Cloud Zuul结合Smconf配置中心动态进行IP黑名单限制
- 高性能NIO框架Netty入门篇
- Spring Boot Web 静态文件缓存处理
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Python老司机手把手带你写爬虫,整站下载妹子图,一次爽个够!
- 教你用云开发打造一个双端自动发布的博客体系(下)
- 国科大&中科院提出CANet:用于图像复原的拼接注意力网络
- 【Kubernetes】Octant部署
- 使用注意力机制来做医学图像分割的解释和Pytorch实现
- 用Python写个爬虫小程序,给女朋友每日定时推送睡前小故事
- 数据量大的表建立索引或者修改表结构太慢的解决办法
- Activiti7入门Demo
- mybatis 中#与$的区别
- Spring中的FactoryBean和BeanFactory
- MybatisPlus分页插件无效解决方案
- springboot+mybatis打印sql
- jquery插件与扩展
- CNN一定需要池化层吗?
- RabbitMQ入门Demo,基于springboot