最近开始学习Spring Cloud,主要借助翟永超的《Spring Cloud微服务实战》,书中使用的版本是Spring Cloud为Brixton.SR5版本,Spring Boot 1.3.7。
当前Spring Cloud版本为Finchley RC1,Spring版本是2.1.0。很多依赖管理都发生了变化,看书的时候摸索了一点时间,所以记录下来。
一、版本说明
jdk使用1.8.0
Spring Cloud:Finchley RC1
Spring Boot:2.1.0
下面为整个搭建的结构:
二、服务注册和发现模块(项目名称:w-eureka,使用端口号:8761)
1.使用Spring Boot提供的快捷搭建方式。
选择Eureka Server模块
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.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.BUILD-SNAPSHOT</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>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
3.配置application.properties
server.port=8761
eureka.instance.hostname=localhost
#是否自动注册自己
eureka.client.register-with-eureka=false
#如果是单点服务器就设置成false
eureka.client.fetch-registry=false
#注册中心地址
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
#关闭自我保护机制
eureka.server.enableSelfPreservation=false
4.启动EurekaServer(加上@EnableEurekaServer注解)
@EnableEurekaServer
@SpringBootApplication
public class WEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(WEurekaApplication.class, args);
}
}
访问localhost:8761,界面显示:
此时没有instance avaliable
三.服务提供者(项目名称:w-eurekaclient,使用端口号:8762和8763)
1.创建方式和server相同,选择Eureka Discovery、Web模块
2.pom.xml文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.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.BUILD-SNAPSHOT</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
3.配置application.properties
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
server.port=8762
#服务的名称
spring.application.name=service01
4.创建一个请求接口用于测试
@RestController
public class HelloController {
@Value("${server.port}")
private String port;
@GetMapping("/hello")
public String hello(@RequestParam String name){
return "hello "+name+",i am from port:"+port;
}
}
4.启动Client,启动程序上加上@EnableEurekaClient注释
@EnableEurekaClient
@SpringBootApplication
@RestController
public class WEurekaclientApplication {
public static void main(String[] args) {
SpringApplication.run(WEurekaclientApplication.class, args);
}
}
此时server已经能够发现client上线的服务:service01
5.测试一下:
测试一下接口(http://localhost:8762/hi?name=sunwukong),
返回(hello suwukong,i am from port:8762),ok的话进入下一步。
四.服务消费者Feign(项目名称:w-feign,使用端口号:8764)
1.创建方式同上,选择Web,Feign,Eureka Discovery模块
2.pom.xml文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.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.BUILD-SNAPSHOT</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
3.配置application.properties
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
server.port=8764
spring.application.name=feign
4.创建Feign接口(“/hello”为service01服务的接口,value=name为service01服务接口参数的名称)
@FeignClient(value = "service01")
public interface SchedualServiceHello {
@RequestMapping(value="/hello",method = RequestMethod.GET)
String sayHiFromClientOne(@RequestParam (value="name") String name);
}
5.创建API接口
@RestController
public class HiController {
@Autowired
private SchedualServiceHello schedualServiceHello;
@RequestMapping(value="/hi",method= RequestMethod.GET)
public String sayHi(@RequestParam String name ){
return schedualServiceHello.sayHiFromClientOne(name);
}
}
6.将eurekaclient服务启动2次,端口分别为8762,8763,
方法是在启动配置的Program arguments参数上修改端口参数:--server.port=8763
7.启动应用,加入@EnableDiscoveryClient,
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class WFeignApplication {
public static void main(String[] args) {
SpringApplication.run(WFeignApplication.class, args);
}
}
8.测试结果
多次访问http://lcoalhost:8764/hi?name=sunwukong,浏览器交替显示
hi sunwokong,i am from port :8762
hi sunwokong,i am from port :8763
五.服务消费者Ribbon(项目名称:w-ribbon,使用端口号:8765)
1.创建方式同上,选择Web,Ribbon,Eureka Discovery模块
2.pom.xml文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.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.BUILD-SNAPSHOT</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
3.配置application.properties
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
server.port=8765
spring.application.name=ribbon
4.增加RestTemplate的BEAN到容器中,为了方便放在主函数中,主函数添加@EnableDiscoveryClient和@EnableEurekaClient注解
@EnableDiscoveryClient
@EnableEurekaClient
@SpringBootApplication
public class WRibbonApplication {
@Bean
@LoadBalanced
RestTemplate getRestTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(WRibbonApplication.class, args);
}
}
5.创建访问接口
@RestController
public class rHelloController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value="/hi",method = RequestMethod.GET)
public String rSayHello(@RequestParam String name){
return restTemplate.getForEntity("http://service01/hello?name="+name,String.class).getBody();
}
}
6.启动测试
多次访问http://lcoalhost:8765/hi?name=sunwukong,浏览器交替显示
hi sunwokong,i am from port :8762
hi sunwokong,i am from port :8763
六.Hystrix断路器
目的就是防止服务中发生雪崩,服务中某一个服务发生阻塞,引起其他服务等待的情况。如果多个服务发生阻塞,那么整个项目都会受到影响。
1.配置Hystrix,在前面创建的w-ribbon的pom.xml文件中,加入Hystrix依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.在测试接口上增加
@HystrixCommand(fallbackMethod = "hiError")注解,
其中hiError为阻塞后回滚的方法,定义回滚方法hiError。
@RestController
public class rHelloController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value="/hi",method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "hiError")
public String rSayHello(@RequestParam String name){
return restTemplate.getForEntity("http://service01/hello?name="+name,String.class).getBody();
}
public String hiError(String name){
return "hi,"+name+",sorry a ! error!";
}
}
5.在主函数上加上@EnableHystrix启动Hystrix组件
@EnableDiscoveryClient
@EnableEurekaClient
@SpringBootApplication
@EnableHystrix
public class WRibbonApplication {
@Bean
@LoadBalanced
RestTemplate getRestTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(WRibbonApplication.class, args);
}
}
6.测试。停止eurekaclient提供的8762,8763端口的服务。
访问http://lcoalhost:8765/hi?name=sunwukong,
测试通过。