SpringCloud从入门到进阶——使用SpringBoot搭建微服务

Posted 比脚更长的路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud从入门到进阶——使用SpringBoot搭建微服务相关的知识,希望对你有一定的参考价值。

内容

  SpringBoot整合SpringCloud的Eureka、Zuul等组件,快速实现简单易懂且具有服务熔断、负载均衡的分布式架构1.0,体验微服务的魅力。

版本

  IDE:IDEA 2017.2.2 x64

  JDK:1.8.0_171

  manve:3.3.3

  SpringBoot:1.5.9.RELEASE

  SpringCloud:Dalston.SR1

适合人群

  ​Java开发人员

说明

  转载请说明出处:SpringCloud从入门到进阶(六)——使用SpringBoot搭建微服务

  GitHub仓库地址: https://github.com/leo-zz/SpringCloudDemo/tree/master/MicroServiceDemo

参考

       Linux入门实践笔记(二)--Jar包运行与关闭

       SpringCloud从入门到进阶(二)——注册中心Eureka的伪分布式部署

项目目录

pom.xml

  在原有SpringBoot项目的基础上引入SpringCloud的默认依赖,以及eureka client的依赖

<?xml version="1.0" encoding="UTF-8"?>
<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>com.leo</groupId>
    <artifactId>service</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 通过继承的方式引入spring boot  -->
    <!--parent标签用于指定父pom-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

    <!--properties标签用于声明一些常量,例如源码编码为UTF-8,输出代码也为UTF-8,Java版本为1.8-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <!--添加1:在dependencyManagement标签中声明默认依赖的SpringCloud的版本,
    所有的SpringCloud组件的依赖都将使用该版本SpringCloud中规定的版本号 -->
    <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>

    <dependencies>
        <!--添加2:SpringCloud-Eureka相关依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <!-- SpringBoot相关等其他依赖省略 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!-- Spring Boot的Maven插件,使用Maven插件的方式来启动Spring Boot工程
如果不添加该插件在使用mvn命令打包的jar有问题,执行时会报错:xxx.jar中没有主清单属性-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
yaml

  在原有项目的基础上增加eurekaSever的连接信息、微服务的应用名称、多profiles的配置。为了演示负载均衡的效果,本示例添加三个profiles。

spring:
  #添加3:设置springboot项目的应用名称,并默认启动peer1
  application:
    name: application-serviceA    #注意:此处的名称一定要个路由接入服务器中的配置名一致 
  profiles: 
      active: peer1
  http:
    multipart:
      #上传文件总的最大值为30MB
      max-request-size: 30MB
      #单个文件的最大值为10MB
      max-file-size: 10MB
    #省略原有Springboot项目的数据源、redis、mybatis、分页等配置
    
#添加4:eurekaSever的连接信息
eureka:
  instance: 
    #要求Client通过ip的方式进行注册
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://172.26.125.114:7001/eureka,http://172.26.125.115:7001/eureka,http://172.26.125.118:7001/eureka
  
#日志输出,指明日志存放位置;同时需要在资源路径下引入配置文件
logging:
  file: logs/application-idleGoodService-${server.port}.logs

#添加5:增加peer1和peer2、peer3多个profiles的配置
---
spring:
  profiles: peer1
server:
  port: 8881

#Eureka实例名的配置
eureka:
  instance:
    instance-id: application-serviceA-A2-8881

#actuator的配置
management:
  port: 8811
  security:
    enabled: false

---
spring:
  profiles: peer2
server:
  port: 8882

#Eureka实例名的配置
eureka:
  instance:
    instance-id: application-serviceA-A2-8882

#actuator的配置
management:
  port: 8812
  security:
    enabled: false
---
spring:
  profiles: peer3
server:
  port: 8883

#Eureka实例名的配置
eureka:
  instance:
    instance-id: application-serviceA-A2-8883

#actuator的配置
management:
  port: 8813
  security:
    enabled: false
SpringApplication

  在主程序类中增加@EurekaClient,开启eureka服务。

//开启EurekaClient
@EnableEurekaClient
@SpringBootApplication
//包扫描、Swagger、事务的配置省略
public class IdlegoodApplication {
​
    //一些bean的注入和创建省略public static void main(String[] args) {
        SpringApplication.run(IdlegoodApplication.class, args);
    }
}
Controller

  SpringBoot项目改造成微服务时,业务逻辑只要保证无状态即可,不要进行额外配置。本示例为了演示功能,在Controller中写两个服务,一个是普通POST接口处理,一个是文件上传的接口。

@RequestMapping("/test")
@RestController
public class DemoController {
    //从配置文件中读取实例名称
    @Value("${eureka.instance.instance-id}")
    String instanceID;

    @PostMapping("/hello/{name}")
    public String sayHello(@PathVariable(value = "name") String name,
                           @RequestParam(value = "from") String user){
        return "Hello "+name+",this is DemoTest.From "+user+"@:"+instanceID+".";
    }
    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file){
        String str="file名称:"+file.getOriginalFilename()+",file大小:"+file.getSize()+"From "+instanceID+".";
        System.out.println(str);
        return str;
    }
}

本地测试

  在本地以默认的profiles启动项目,然后使用postman请求这两个接口,确保项目代码编写正常。

  ​测试接口1:http://localhost:8881/test/hello/leo,正常。

  测试接口2:http://localhost:8881/test/upload,向服务器上传大于1MB的文件,正常。

直接调用微服务测试

  按照之前的操作进行项目打包、上传,具体过程可参考:SpringCloud从入门到进阶(二)——注册中心Eureka的伪分布式部署

​   先启动Eureka集群和路由Zuul,然后在同一个局域网内的主机上,分别执行下列命令启动微服务的三个实例。启动后可以通过jps命令可以看到相应的进程:

[user@Serverjars]$java -Dspring.profiles.active=peer1 -jar service-1.0-SNAPSHOT.jar & #服务器A
[user@Serverjars]$java -Dspring.profiles.active=peer2 -jar service-1.0-SNAPSHOT.jar & #服务器B
[user@Serverjars]$java -Dspring.profiles.active=peer3 -jar service-1.0-SNAPSHOT.jar & #服务器B
#通过jps命令可以看到相应的进程,-v选型表示打印jvm参数。
[user@Serverjars]$ jps -v
29410 jar -Dspring.profiles.active=peer1
29366 jar -Dspring.profiles.active=peer2
29321 jar -Dspring.profiles.active=peer3

  访问EurekaSever,确认服务正常启动。

  与本地测试一样,直接调用微服务的接口地址,进行测试。假如主机的IP为172.26.125.10,那么分别请求http://172.26.125.10:8881/test/hello/leohttp://172.26.125.10:8882/test/hello/leohttp://172.26.125.10:8883/test/hello/leo等地址,以确保微服务部署正确。

通过路由调用微服务测试

  确保微服务部署正确无误后再使用Postman请求路由接入服务器的接口。假如路由Zuul所在主机的IP为172.26.125.20,那么请求接口1http://172.26.125.20:7081/v1/routea/test/hello/leo和接口2http://172.26.125.20:7081/v1/routea/test/upload。Zuul在接收到该url的请求时,会根据路由规则的设定,将"/v1/routea/**"的请求转发给application-serviceA处理。

测试接口1

  ​测试多次,可以看到Zuul会将请求在多个微服务实例中做负载均衡,默认情况按照轮询算法分配请求。

  请求转发到实例1处理:

  请求转发到实例2处理:

  请求转发到实例3处理:

测试接口2

​  向服务器上传小于1MB的文件,测试多次,也可以看到负载均衡的效果。

  请求转发到实例1处理:

  请求转发到实例2处理:

  请求转发到实例3处理:

   但是,当上传超过1MB大小的文件时,服务报错。

  出现这个问题,想必大家都有疑问。同样的请求,为什么直接调用服务时正常,但是通过Zuul路由调用服务就会出错呢。如果你在上传文件的测试中,还遇到服务调用失败、中文乱码等诡异报错,那么说明你测得很全面。对于这些问题的解释和解决,请看下篇文章[SpringCloud从入门到进阶(七)——踩坑实战之Zuul服务调用失败与文件上传问题](https://www.cnblogs.com/lonelyJay/p/9994246.html)

补充:使用Zipkin监控路由Zuul的请求处理。

  为了监控请求处理的耗时情况,会在路由端和微服务端增加链路追踪组件Zipkin,具体配置请参考后续章节。

以上是关于SpringCloud从入门到进阶——使用SpringBoot搭建微服务的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud从入门到进阶——源码探究Eureka集群之replicas的unavailable故障

Spring Cloud Alibaba从入门到进阶

SpringCloud从入门到进阶——生产环境下Eureka的完全分布式部署

Jenkins持续集成入门到精通(进阶篇)

spring boot入门与进阶

汇总汇总-Spring&Cloud&Alibaba&源码剖析&分布式锁/事务-从入门到进阶到源码-学完保证吊打面试官