最近在搭建SpringCloud+Consul的项目,在网上查看blog找了很久,花了差不多2天时间才解决SpringCloud的服务无法注册到Consul的方法。主要原因是SpringCloud的服务在Springboot项目中没有启动。这个是问题的根源。接下我们开始填坑吧。
我的Springboot版本为:2.0.3.RELEASE,SpringCloud版本为Finchley.RELEASE。网上其他blog说springboot的版本为2.1.3.RELEASE也是可以的。如果version为2.1.3.RELEASE, spring-cloud.version也要为Finchley.SR1。tomcat版本为8.5.38和9.0.29都可以运行项目打成的war包。
一、安装consul
1.1、访问 Consul 官网 ,根据操作系统类型,选择下载 Consul 的最新版本。我这里选择windows版本。
下载下来是一个zip压缩包,解压之后,是一个exe可执行文件。
1.2、制作一个启动文件:consul_start.bat,内容如下:
title consul
echo start..............................
d:
cd D:\appsoftware\consul_1.6.2_windows_amd64
consul agent -dev
echo end.......................
pause
1.3、双击consul_start.bat启动后,访问地址:http://localhost:8500/ui/dc1/services,如下图片:
二、Consul 服务提供者
服务注册发现中心有了,现在我们来开发服务提供者。
2.1、新建项目 spring-cloud-consul-producer,项目结构如下:
2.1.1、创建项目的启动类ConsulProducerApplication.java
package jypay.com.springcloud.consul.producer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
@EnableDiscoveryClient
@EnableAutoConfiguration
@ComponentScan({"jypay.com.springcloud.consul.controller","jypay.com.springcloud.consul.util"})/*注意要把controller扫描进项目的路径,不然不能加载你的controller*/
@SpringBootApplication
public class ConsulProducerApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(ConsulProducerApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ConsulProducerApplication.class, args);
}
}
注意:要把util包下面的SpringCloud注册类(ConsulEventLinsiner.java)加载到项目中,不然,你的项目服务不会注册到Consul中。
2.1.2、创建一个HelloController.java
package jypay.com.springcloud.consul.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "hello consul.";
}
}
2.1.3、创建Springcloud服务类注册到Consul,ConsulEventLinsiner.java
package jypay.com.springcloud.consul.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistration;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class ConsulEventLinsiner implements ApplicationListener<ContextRefreshedEvent>{
@Autowired
ConsulAutoServiceRegistration consulAutoServiceRegistration;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
consulAutoServiceRegistration.start();
}
}
2.2、pom.xml文件内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jypay.com</groupId>
<artifactId>spring-cloud-consul-producer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging><!--改为war方式-->
<name>spring-cloud-consul-producer</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<!-- <relativePath/> --> <!-- 如果version为2.1.3.RELEASE, spring-cloud.version也要为Finchley.SR1。 lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId><!-- 健康检查依赖于此包 -->
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId><!-- Spring Cloud Consul 的支持。 -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 排除内置tomcat容器,导出成war包可以让外部容器运行spring-boot项目-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!-- provided表明该包只在编译和测试的时候用 -->
<scope>provided</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<!-- 修改war包名称 -->
<finalName>springCloudConsulProducer</finalName>
<plugins>
<!-- 在打jar包时,用来指定主类的插件,打war包将其注释掉 -->
<!-- <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin> -->
</plugins>
</build>
</project>
2.3、application.yml的配置如下:
spring:
application:
name: springCloudConsulProducer
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
healthCheckPath: /springCloudConsulProducer/actuator/health
healthCheckInterval: 1s
hostname: 127.0.0.1
port: 8080
server:
port: 8511
注意坑:server.port为服务提供者的端口号,spring.cloud.port为consul的默认访问端口号。注意Consul的健康检测地址参数healthCheckPath值为项目路径,discovery.hostname和discovery.port为你的项目部署的Ip和tomcat端口号。ip和port必须写,不然Consul获取不到服务的链接情况。
三、项目打war包
在eclipse中安装有maven的插件,具体方法自行到网上搜索解决。
方式一:
项目右键--->run as--->maven install 完成打包如下图:
方式二:
项目右键--->run as--->maven build 弹出如下图:
按标红1、2、3操作可完成打包。
其他打包方式
比如使用mvn的命令可自行搜下就知道了。
四、部署
把第2步打成war文件放到tomcat8.5版本(以上)的webapps目录下,如果在windows下面启动startup.bat。如在linux则时行tomcat的bin目录输入./startup.sh。注意:如果tomcat版本为6.x或7.x是运行不起来的。我已实测了,如果大家想看具体的报错请自测了解下。
4.1、访问controller
在浏览器访问:http://localhost:8080/war包名/@RequestMapping.value
我的为例子:http://localhost:8180/springCloudConsulProducer/hello
4.2、在Consul中查看启动的springcloud服务
总结:在以上步骤中,最容易出问题点如下:
1)、ConsulProducerApplication.java中没有把SpringCloud的服务注册到Consul,没有用
@ComponentScan({"jypay.com.springcloud.consul.controller","jypay.com.springcloud.consul.util"});
2)、Springboot和SpringCloud的版本号选定,建议用Springboot版本2.0.3.RELEASE或2.1.3.RELEASE,SpringCloud版本号:Finchley.RELEASE或Finchley.SR1。如果你要选用其他版本也可以的,只不过要花一些时间去测试填坑而已;
3)、application.yml的配置内容,特别是spring.cloud.discovery的4个参数(healthCheckPath、healthCheckInterval、hostname、port)的值要根据自己的实际情况填写正确,不然,自己掉这坑里面好久都爬不出来。这个参数的正确验证方法,你访问路径:http://localhost:8080/springCloudConsulProducer/actuator/health是否有返回参数:
{"status":"UP"}
则证明在yml文件配置的地址参数是正确的。反之,你的项目中检测服务提供者的地址不对,Consul会有如下错误:
No connection could be made because the target machine actively refused it.如下图片: