最近在搭建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版本。

springcloud war包 springcloud war包部署_springcloud war包

下载下来是一个zip压缩包,解压之后,是一个exe可执行文件。

springcloud war包 springcloud war包部署_springcloud war包_02

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,项目结构如下:

springcloud war包 springcloud war包部署_spring_03

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   完成打包如下图:

springcloud war包 springcloud war包部署_Cloud_04

方式二:

项目右键--->run as--->maven build   弹出如下图:

springcloud war包 springcloud war包部署_spring_05

按标红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

springcloud war包 springcloud war包部署_springcloud war包_06

4.2、在Consul中查看启动的springcloud服务

springcloud war包 springcloud war包部署_spring_07

总结:在以上步骤中,最容易出问题点如下:

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.如下图片:

springcloud war包 springcloud war包部署_spring_08