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搭建微服务
参考
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; } }
测试接口1:http://localhost:8881/test/hello/leo,正常。
按照之前的操作进行项目打包、上传,具体过程可参考: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,确认服务正常启动。
测试多次,可以看到Zuul会将请求在多个微服务实例中做负载均衡,默认情况按照轮询算法分配请求。
请求转发到实例1处理:
请求转发到实例2处理:
请求转发到实例3处理:
向服务器上传小于1MB的文件,测试多次,也可以看到负载均衡的效果。
请求转发到实例1处理:
请求转发到实例2处理:
请求转发到实例3处理:
但是,当上传超过1MB大小的文件时,服务报错。
出现这个问题,想必大家都有疑问。同样的请求,为什么直接调用服务时正常,但是通过Zuul路由调用服务就会出错呢。如果你在上传文件的测试中,还遇到服务调用失败、中文乱码等诡异报错,那么说明你测得很全面。对于这些问题的解释和解决,请看下篇文章 。