Spring Cloud是一个类似于dobbo的服务治理框架,将一个大项目拆分成N多个模块(也叫服务)开发部署,然后注册到Spring Cloud Eureka Server里面来,由Spring Cloud Eureka Server注册中心统一进行管理,所以局部的崩溃不会引起整个项目的使用,Spring Cloud项目具有高可用,负载均衡的好处,因此深受许多公司的喜爱。
下面小编将来介绍一下Spring Cloud客户端与服务器端集群的示例,让大家体会一下Spring Cloud的好处,下图介绍的是:
当一个用户通过浏览器或APP访问后端的时候,首先通过的是Ribbon负载均衡模块从Spring Cloud Eureka Server服务端中获取Spring Cloud Eureka Client的数据,Spring Cloud Eureka Client客户端的作用主要就是从数据库中获取一些数据,或者将数据存储到数据库中,里面定义的是一些接口。
为什么Ribbon可以从Server服务端中获取到Client客户端中的数据呢?
因为Spring Cloud Ribbon与Spring Cloud Eureka Client都注册到了Server服务端中了,所以他们就可以通过Server查找到Client中的接口,并进行调用。
Server注册中心与Client做集群有什么好处呢?
好处就是,当任何一个server或者client客户端崩溃了或网络断掉,由于Ribbon的负载均衡作用,能自主选择剩余能运行的服务,用户或APP就能继续正常的访问网页,而不至于断掉。
如图所示:
下面来开始实现Spring Cloud客户端与服务器端集群,并通过Ribbon来调用Client中定义的接口,在此之前,小编创建了5个项目,两个Client客户端,它们的代码一模一样;两个Server服务端,代码也一模一样;一个Ribbon消费端,用于调用client端接口,创建的都是JAVA应用,而不是WEB应用,如图。
一、引入JAR包
这5个项目引入的jar包都是一样的,因为他们包含了所有Spring Cloud所需要的jar包,后面步骤中将不再介绍引入jar包的事情,方法是:在pom.xml文件的<project>标签内部引入cloud相关的maven jar包,代码如下:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <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>Finchley.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</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> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
二、创建两个Spring Cloud Eureka Server服务注册中心的Java Maven项目
这两个项目的java Main方法代码是一样的,它们需要相互注册到对方的服务注册中心去(上图有画出),唯一不一样的就是application.properties中的配置不太一样,比如端口,以及“defaultZone”指向的注册地址,端口号分别为:8760与8761。
2.1 Server 1,服务注册中心(一)的代码及配置
一:Java类的Main方法,代码如下:
package com.tpyyes; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaServerOneApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerOneApplication.class, args); } }
二:application.properties的配置文件代码如下:
# Server 1端口 server.port=8760 # Server 1的应用名称 spring.application.name=eureka # 关闭自我保护机制,并5秒钟检查一次服务列表,如果client服务关闭,则从列表中清理掉 eureka.server.enable-self-preservation=false eureka.server.eviction-interval-timer-in-ms=5000 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false # 注册到Server 2中 eureka.client.serviceUrl.defaultZone: http://localhost:8761/eureka/
2.2 Server 2,服务注册中心(二)的代码及配置
一:Java类的Main方法,代码如下:
package com.tpyyes; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaServerTwoApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerTwoApplication.class, args); } }
二:application.properties的配置文件代码如下:
# Server 2端口 server.port=8761 # Server 2的应用名称 spring.application.name=eureka # 关闭自我保护机制,并5秒钟检查一次服务列表,如果client服务关闭,则从列表中清理掉 eureka.server.enable-self-preservation=false eureka.server.eviction-interval-timer-in-ms=5000 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false # 注册到Server 1中 eureka.client.serviceUrl.defaultZone: http://localhost:8760/eureka/
2.3 运行两个Server服务注册中心
分别运行Server 1与Server 2,效果如图所示,可以相互看到对方的注册中心链接:
三、创建两个Spring Cloud Eureka Client客户端
这两个项目的客户端的Java代码一样,就是properties配置不一样,这两个客户端都需要分别注册到上面两个Server注册中心中去,小编用的端口分别为:8888与9999。
3.1 Client 1,客户端(一)的代码及配置
一:客户端Java类的Main方法,启动之后访问接口会输出String字符串,代码如下:
package com.tpyyes; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @EnableEurekaClient @SpringBootApplication public class EurekaClientOneApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientOneApplication.class, args); } } @RestController class ServiceInstanceRestController { @RequestMapping("/api/hello") public String welcome() { return "hello world spring cloud client"; } }
二:客户端application.properties的配置文件代码如下:
# 客户端1端口 server.port=8888 # 客户端1应用名称,要与客户端2名称一致 spring.application.name=eureka-client eureka.instance.preferIpAddress=true # 开启健康检查(需要spring-boot-starter-actuator依赖,本项目已经有了),10秒向Server汇报一次 eureka.client.healthcheck.enabled = true eureka.instance.lease-renewal-interval-in-seconds =10 eureka.instance.lease-expiration-duration-in-seconds =30 # client 1分别注册到两个Server注册中心中 eureka.client.serviceUrl.defaultZone: http://localhost:8760/eureka/,http://localhost:8761/eureka/
3.2 Client 2,客户端(二)的代码及配置
一:客户端Java类的Main方法,启动之后访问接口会输出String字符串,代码如下:
package com.tpyyes; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @EnableEurekaClient @SpringBootApplication public class EurekaClientTwoApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientTwoApplication.class, args); } } @RestController class ServiceInstanceRestController { @RequestMapping("/api/hello") public String welcome() { return "hello world spring cloud client"; } }
二:客户端application.properties的配置文件代码如下:
# 客户端2端口 server.port=9999 # 客户端2应用名称,要与客户端1名称一致 spring.application.name=eureka-client eureka.instance.preferIpAddress=true # 开启健康检查(需要spring-boot-starter-actuator依赖,本项目已经有了),10秒向Server汇报一次 eureka.client.healthcheck.enabled = true eureka.instance.lease-renewal-interval-in-seconds =10 eureka.instance.lease-expiration-duration-in-seconds =30 # client 2分别注册到两个Server注册中心中 eureka.client.serviceUrl.defaultZone: http://localhost:8760/eureka/,http://localhost:8761/eureka/
3.3 运行两个客户端
分别运行客户端1与客户端2的main方法,可以在server 1与server 2中分别都能看到两个客户端注册进来的地址,如图:
最后,当我们访问“http://localhost:8888/api/hello”或“http://localhost:9999/api/hello”,两个都能输出如下的“hello world spring cloud client”字符串信息:
备注说明:
经过上方的三个步骤,可以说明我们的两个Client客户端都已经成功的注册到了两个注册中心中,这两个Server注册中心之间也形成了相互注册,此时还需要使用Ribbon进行负载均衡,也就是说你随意关闭两个Server注册中心或Client客户端中的一个,我们在访问接口的时候,依然能输出“hello world spring cloud client”字符串。
四、使用Spring Cloud Eureka Ribbon负载均衡
我们还需要写一个Ribbon应用,实现Spring Cloud负载均衡,当我们访问接口时,不仅能均匀分配客户端的访问压力,还能在客户端出问题时应用依然能正常运行,因此小编将该应用的端口设置为8080,Ribbon也需要注册到两个Server服务注册中心里面去。
4.1 Ribbon应用的代码及配置
一:Ribbon的Java代码如下,“@LoadBalanced”为负载均衡注解,:
package com.tpyyes; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @EnableEurekaClient @SpringBootApplication public class EurekaRibbonApplication { public static void main(String[] args) { SpringApplication.run(EurekaRibbonApplication.class, args); } @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } } @RestController class ServiceInstanceRestController { @Autowired private RestTemplate getRestTemplate; @RequestMapping("/api/getInfo") public String welcome() { // 客户端应用名称 String serviceId = "eureka-client"; String res = getRestTemplate.getForObject("http://"+serviceId+"/api/hello", String.class); return "Client客户端返回的结果是:"+res; } }
二:Ribbon应用application.properties的配置文件代码如下:
# Ribbon应用端口 server.port=8080 # Ribbon应用名称 spring.application.name=eureka-ribbon-api eureka.instance.preferIpAddress=false ping-server.ribbon.eureka.enabled=false # 注册到服务注册中心列表中 ping-server.ribbon.eureka.listOfServers=http://localhost:8760/eureka/,http://localhost:8761/eureka/ ping-server.ribbon.eureka.ServerListRefreshInterval=3600
4.2 运行Ribbon应用
运行Ribbon应用之后,可以分别在两个Server注册中心中看到Ribbon的应用已经被注册了,如图:
当我们访问“http://localhost:8080/api/getInfo”时,就能均衡调用两个Client客户端应用,并输出Client里面获取的字符串信息了,如图:
集群整合完毕!