将Spring Boot应用程序注册成为系统服务

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将Spring Boot应用程序注册成为系统服务相关的知识,希望对你有一定的参考价值。

参考技术A 将Spring Boot应用程序注册成为系统服务

在之前的文章中,我们提到了很多Spring Boot的技巧,那么当我们创建好了Spring Boot应用程序之后,怎么在生成环境中运行呢?如果只是以原始的java -jar 的方式来运行的话,不能保证程序的健壮性和稳定性,最好的办法是将程序注册成为服务来使用。

本文将会讲解如何将Spring Boot应用程序注册成为Linux和windows的服务。

首先我们需要将应用程序打包成为一个可执行的jar包,我们需要添加如下依赖:

这里的packaging我们需要选择jar。添加spring-boot-maven-plugin是为了将app打包成为可执行的jar包。

写好了应用程序,我们可以执行:

来打包应用程序,这里我们打包之后的jar包名字为:springboot-run-as-service-0.0.1-SNAPSHOT.jar。

在linux中,我们可以选择System V init script或者Systemd 配置文件,前者逐渐在被后者替代。

为了安全起见,我们需要创建一个运行用户,并给jar包赋予相应的权限:

创建一个文件链接到init.d目录,如下:

接下来我们就可以启动应用程序了:

service命令支持start, stop, restart 和 status。同时它还提供了如下的功能:

使用Systemd,我们需要在 /etc/systemd/system 创建一个your-app.service文件:

接下来我们可以使用systemctl start|stop|restart|status your-app来管理你的服务了。

Upstart是一个事件驱动的服务管理器,如果你使用Ubuntu,将会被默认安装。

我们来创建一个your-app.conf :

在windows中,我们也有很多方式,如下:

Windows Service Wrapper 又叫 winsw是一个开源软件,winsw需要和一个配置文件your-app.xml配合使用:

Java Service Wrapper 提供了非常强大的配置,他可以让你的应用程序在windows和Linux下面使用。有兴趣的同学可以自行去学习。

更多教程请参考 flydean的博客

Spring Boot + Spring Cloud 集成 Consul 服务注册发现

什么是 Consul ?

Consul is a service mesh solution。

Consul是开源的,用于实现分布式系统的服务发现与配置。Consul是分布式的、高可用的、 可横向扩展的。它具备以下特性:

服务发现: Consul提供了通过DNS或者HTTP接口的方式来注册服务和发现服务。一些外部的服务通过Consul很容易的找到它所依赖的服务。

健康检测: Consul的Client提供了健康检查的机制,可以通过用来避免流量被转发到有故障的服务上。

Key/Value存储: 应用程序可以根据自己的需要使用Consul提供的Key/Value存储。 Consul提供了简单易用的HTTP接口,结合其他工具可以实现动态配置、功能标记、领袖选举等等功能。

多数据中心: Consul支持开箱即用的多数据中心. 这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。

The key features of Consul are:

  • Service Discovery: Clients of Consul can register a service, such as api or mysql, and other clients can use Consul to discover providers of a given service. Using either DNS or HTTP, applications can easily find the services they depend upon.

  • Health Checking: Consul clients can provide any number of health checks, either associated with a given service ("is the webserver returning 200 OK"), or with the local node ("is memory utilization below 90%"). This information can be used by an operator to monitor cluster health, and it is used by the service discovery components to route traffic away from unhealthy hosts.

  • KV Store: Applications can make use of Consul's hierarchical key/value store for any number of purposes, including dynamic configuration, feature flagging, coordination, leader election, and more. The simple HTTP API makes it easy to use.

  • Secure Service Communication: Consul can generate and distribute TLS certificates for services to establish mutual TLS connections. Intentions can be used to define which services are allowed to communicate. Service segmentation can be easily managed with intentions that can be changed in real time instead of using complex network topologies and static firewall rules.

  • Multi Datacenter: Consul supports multiple datacenters out of the box. This means users of Consul do not have to worry about building additional layers of abstraction to grow to multiple regions.

Consul is designed to be friendly to both the DevOps community and application developers, making it perfect for modern, elastic infrastructures.

Consul 架构组成

安装 Consul

下载安装:https://www.consul.io/downloads
或者命令行安装:

brew tap hashicorp/tap
brew install hashicorp/tap/consul

本地启动 Consul

启动命令:

$consul agent -server -bootstrap-expect=1 -data-dir=consul_data -ui -bind=127.0.0.1

启动日志:

$consul agent -server -bootstrap-expect=1 -data-dir=consul_data -ui -bind=127.0.0.1 
==> Starting Consul agent...
           Version: '1.9.5'
           Node ID: 'bad6d61c-e87e-8415-f97d-9ba4b996655d'
         Node name: 'C02FJ0KMMD6V'
        Datacenter: 'dc1' (Segment: '<all>')
            Server: true (Bootstrap: true)
       Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600)
      Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false

==> Log data will now stream in as it occurs:

    2021-05-19T11:07:11.643+0800 [WARN]  agent: BootstrapExpect is set to 1; this is the same as Bootstrap mode.
    2021-05-19T11:07:11.643+0800 [WARN]  agent: bootstrap = true: do not enable unless necessary
    2021-05-19T11:07:11.646+0800 [WARN]  agent.auto_config: BootstrapExpect is set to 1; this is the same as Bootstrap mode.
    2021-05-19T11:07:11.647+0800 [WARN]  agent.auto_config: bootstrap = true: do not enable unless necessary
    2021-05-19T11:07:11.884+0800 [INFO]  agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:bad6d61c-e87e-8415-f97d-9ba4b996655d Address:127.0.0.1:8300}]"
    2021-05-19T11:07:11.885+0800 [INFO]  agent.server.raft: entering follower state: follower="Node at 127.0.0.1:8300 [Follower]" leader=
    2021-05-19T11:07:11.885+0800 [INFO]  agent.server.serf.wan: serf: EventMemberJoin: C02FJ0KMMD6V.dc1 127.0.0.1
    2021-05-19T11:07:11.886+0800 [INFO]  agent.server.serf.lan: serf: EventMemberJoin: C02FJ0KMMD6V 127.0.0.1
    2021-05-19T11:07:11.886+0800 [INFO]  agent.router: Initializing LAN area manager
    2021-05-19T11:07:11.886+0800 [INFO]  agent.server: Handled event for server in area: event=member-join server=C02FJ0KMMD6V.dc1 area=wan
    2021-05-19T11:07:11.886+0800 [INFO]  agent.server: Adding LAN server: server="C02FJ0KMMD6V (Addr: tcp/127.0.0.1:8300) (DC: dc1)"
    2021-05-19T11:07:11.886+0800 [INFO]  agent: Started DNS server: address=127.0.0.1:8600 network=tcp
    2021-05-19T11:07:11.886+0800 [INFO]  agent: Started DNS server: address=127.0.0.1:8600 network=udp
    2021-05-19T11:07:11.887+0800 [INFO]  agent: Starting server: address=127.0.0.1:8500 network=tcp protocol=http
    2021-05-19T11:07:11.887+0800 [WARN]  agent: DEPRECATED Backwards compatibility with pre-1.9 metrics enabled. These metrics will be removed in a future version of Consul. Set `telemetry { disable_compat_1.9 = true }` to disable them.
    2021-05-19T11:07:11.887+0800 [INFO]  agent: started state syncer
==> Consul agent running!
    2021-05-19T11:07:17.627+0800 [WARN]  agent.server.raft: heartbeat timeout reached, starting election: last-leader=
    2021-05-19T11:07:17.627+0800 [INFO]  agent.server.raft: entering candidate state: node="Node at 127.0.0.1:8300 [Candidate]" term=2
    2021-05-19T11:07:17.769+0800 [INFO]  agent.server.raft: election won: tally=1
    2021-05-19T11:07:17.769+0800 [INFO]  agent.server.raft: entering leader state: leader="Node at 127.0.0.1:8300 [Leader]"
    2021-05-19T11:07:17.769+0800 [INFO]  agent.server: cluster leadership acquired
    2021-05-19T11:07:17.770+0800 [INFO]  agent.server: New leader elected: payload=C02FJ0KMMD6V
    2021-05-19T11:07:17.914+0800 [INFO]  agent.leader: started routine: routine="federation state anti-entropy"
    2021-05-19T11:07:17.914+0800 [INFO]  agent.leader: started routine: routine="federation state pruning"
    2021-05-19T11:07:17.914+0800 [INFO]  agent.server: member joined, marking health alive: member=C02FJ0KMMD6V
    2021-05-19T11:07:17.961+0800 [INFO]  agent.server: federation state anti-entropy synced
    2021-05-19T11:07:18.075+0800 [INFO]  agent: Synced node info

Consul 命令参考:https://www.consul.io/commands

本地访问: http://localhost:8500/ui/dc1/services

创建 Spring Boot 工程

创建 Spring Boot 工程:

consul 核心依赖:

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

编写代码

ConsulSpringbootDemoApplication

package com.example.consulspringbootdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsulSpringbootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsulSpringbootDemoApplication.class, args);
    }

}

HelloController

package com.example.consulspringbootdemo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "hello,world!";
    }
}

配置 application.properties

application.properties

spring.application.name=consul-springboot-demo
server.port=8081
spring.cloud.consul.discovery.enabled=true
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

启动运行

/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -javaagent:/private/var/folders/7v/b654w_lx6jz8vw5hzp9qnzqm0000gn/T/AppTranslocation/608C9F51-7E28-4B2B-8497-A980BC72F942/d/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=51775:/private/var/folders/7v/b654w_lx6jz8vw5hzp9qnzqm0000gn/T/AppTranslocation/608C9F51-7E28-4B2B-8497-A980BC72F942/d/IntelliJ IDEA.app/Contents/bin -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtual..........1.7.30.jar:/Users/bytedance/.m2/repository/org/springframework/spring-core/5.3.6/spring-core-5.3.6.jar:/Users/bytedance/.m2/repository/org/springframework/spring-jcl/5.3.6/spring-jcl-5.3.6.jar com.example.consulspringbootdemo.ConsulSpringbootDemoApplication

  .   ____          _            __ _ _
 /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\
( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\
 \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.5)

2021-05-19 11:47:09.777  INFO 23711 --- [           main] c.e.c.ConsulSpringbootDemoApplication    : Starting ConsulSpringbootDemoApplication using Java 1.8.0_291 on C02FJ0KMMD6V with PID 23711 (/Users/bytedance/code/consul-springboot-demo/target/classes started by bytedance in /Users/bytedance/code/consul-springboot-demo)
2021-05-19 11:47:09.785  INFO 23711 --- [           main] c.e.c.ConsulSpringbootDemoApplication    : No active profile set, falling back to default profiles: default
2021-05-19 11:47:11.418  INFO 23711 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=db96fb34-10ee-37e3-ac5b-2af2e64eea46
2021-05-19 11:47:11.794  INFO 23711 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)
2021-05-19 11:47:11.805  INFO 23711 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-05-19 11:47:11.805  INFO 23711 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.45]
2021-05-19 11:47:11.904  INFO 23711 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-05-19 11:47:11.904  INFO 23711 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2032 ms
2021-05-19 11:47:12.181  INFO 23711 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-19 11:47:12.935  INFO 23711 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService 'catalogWatchTaskScheduler'
2021-05-19 11:47:12.942  WARN 23711 --- [           main] iguration$LoadBalancerCaffeineWarnLogger : Spring Cloud LoadBalancer is currently working with the default cache. You can switch to using Caffeine cache, by adding it and org.springframework.cache.caffeine.CaffeineCacheManager to the classpath.
2021-05-19 11:47:12.947  INFO 23711 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2021-05-19 11:47:13.013  INFO 23711 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path ''
2021-05-19 11:47:13.015  INFO 23711 --- [           main] o.s.c.c.s.ConsulServiceRegistry          : Registering service with consul: NewService{id='consul-springboot-demo-8081', name='consul-springboot-demo', tags=[], address='10.94.53.140', meta={secure=false}, port=8081, enableTagOverride=null, check=Check{script='null', dockerContainerID='null', shell='null', interval='10s', ttl='null', http='http://10.94.53.140:8081/actuator/health', method='null', header={}, tcp='null', timeout='null', deregisterCriticalServiceAfter='null', tlsSkipVerify=null, status='null', grpc='null', grpcUseTLS=null}, checks=null}
2021-05-19 11:47:13.151  INFO 23711 --- [           main] c.e.c.ConsulSpringbootDemoApplication    : Started ConsulSpringbootDemoApplication in 4.186 seconds (JVM running for 4.796)
2021-05-19 11:47:13.480  INFO 23711 --- [5)-10.94.53.140] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-05-19 11:47:13.480  INFO 23711 --- [5)-10.94.53.140] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-05-19 11:47:13.481  INFO 23711 --- [5)-10.94.53.140] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms

测试验证

Consul 后台管理页面

访问 http://localhost:8500/ui/dc1/services 可以看到新注册服务:

接口测试

GET http://127.0.0.1:8081/hello

HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 12
Date: Wed, 19 May 2021 03:51:36 GMT
Keep-Alive: timeout=60
Connection: keep-alive

hello,world!

Response code: 200; Time: 265ms; Content length: 12 bytes

参考资料

https://www.consul.io/

以上是关于将Spring Boot应用程序注册成为系统服务的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Boot 从另一个服务调用 Rest Service 以进行课程注册系统

Spring Boot 管理员:客户端无法通过 https 向管理服务器注册

SpringCloud微服务监控Spring Boot Admin

Spring Boot + Spring Cloud 集成 Consul 服务注册发现

Spring Boot项目生成jar包,并在windows服务器中注册成服务,开机启动

如何使用 Spring Boot jwt 将身份验证系统连接到 React.js