最近开始学习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,
测试通过。