創建maven聚合項目
pom.xml 配置
<?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>cloud-test</groupId>
<artifactId>cloud-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>父工程</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.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.SR2</spring-cloud.version>
<mybatis.starter.version>1.3.2</mybatis.starter.version>
<mapper.starter.version>2.0.2</mapper.starter.version>
<druid.starter.version>1.1.9</druid.starter.version>
<mysql.version>5.1.32</mysql.version>
<pageHelper.starter.version>1.2.3</pageHelper.starter.version>
<leyou.latest.version>1.0.0-SNAPSHOT</leyou.latest.version>
<fastDFS.client.version>1.26.1-RELEASE</fastDFS.client.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- mybatis啓動器 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.starter.version}</version>
</dependency>
<!-- 通用Mapper啓動器 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${mapper.starter.version}</version>
</dependency>
<!-- 分頁助手啓動器 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pageHelper.starter.version}</version>
</dependency>
<!-- mysql驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--FastDFS客戶端-->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>${fastDFS.client.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
創建Eureka服務註冊模塊
pom.xml 配置
<?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">
<parent>
<artifactId>cloud-test</artifactId>
<groupId>cloud-test</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>eureka註冊中心</name>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
application.yml配置
server:
port: 8761
eureka:
instance:
hostname: localhost # 設置當前實例的主機名稱
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
啓動類配置
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class);
}
}
效果測試
成功但是還沒有實例註冊到eureka
創建生產者微服務
pom.xml配置文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 熱部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- eureka客戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
application.yml配置文件
server:
port: 1000
spring:
application:
name: provider-1000
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
啓動類配置
@SpringBootApplication
@EnableDiscoveryClient
public class Provider1000 {
public static void main(String[] args) {
SpringApplication.run(Provider1000.class);
}
}
測試效果
生產者微服務成功註冊進了Eureka服務中
Ribbon 負載均衡
創建消費者微服務
pom.xml配置文件
<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.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
application.yml配置文件
server:
port: 2000
spring:
application:
name: consumer-ribbon-2000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
啓動類配置
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class);
}
@Bean
@LoadBalanced /*添加負載均衡,默認會輪詢調用提供者*/
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
消費者微服務 Controller 層
@RestController
public class ConsumerController {
@Resource
RestTemplate restTemplate;
@RequestMapping("/helloRibbon")
public Map helloRibbon() {
return restTemplate.getForObject("http://PROVIDER/hello", Map.class);
}
}
兩個生產者微服務application.yml配置文件
爲了測試負載均衡將生產者的服務名改成相同的。
spring:
application:
name: provider
效果如下:
兩個生產者微服務的 Controller 層
@RestController
public class ProviderController {
@RequestMapping("/hello")
public Map<String, Object> hello() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "provider-1001");
return map;
}
}
@RestController
public class ProviderController {
@RequestMapping("/hello")
public Map<String, Object> hello() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "provider-1002");
return map;
}
}
測試效果
默認以輪詢的方式訪問生產者。
Feign 負載均衡
創建消費者微服務
pom.xml配置文件
<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.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
</dependencies>
application.yml配置文件
server:
port: 2000
spring:
application:
name: consumer-ribbon-2000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
啓動類配置
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class);
}
}
Controller
@RestController
public class ConsumerController {
@Resource
IService iService;
@GetMapping("/helloFeign")
public Map helloFeign() {
return iService.helloFeign();
}
}
接口
@FeignClient(value = "PROVIDER")/**通過value綁定微服務的名字來指定調用哪個服務*/
public interface IService {
@GetMapping("/hello")/**調用PROVIDER微服務的@GetMapping("/toProvider/hello")*/
public Map<String,Object> hello();
}
測試效果
和Ribbon 一樣以輪詢的方式實現了負載均衡。
Hystrix 熔斷器
Netflix 熔斷器是安裝在服務消費者上的。所以我們需要做的就是在服務消費者上開啓熔斷器並配置。
Ribbon + Hystrix
pom.xml配置文件
<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.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
application.yml配置文件
server:
port: 2000
spring:
application:
name: consumer-ribbon-2000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
啓動類
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class);
}
控制層
//斷路器配置,當無法調用如下方法時,就會調用自定義的errorMethod方法
@HystrixCommand(fallbackMethod = "errorMethod")
@RequestMapping("/toRibbonHystrix/hello")
public Map helloRibbonHystrix() {
// 故意寫錯訪問路徑
return restTemplate.getForObject("http://PROVIDER1/hello", Map.class);
}
public Map<String, Object> errorMethod() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("ribon", "ribon出錯啦");
return map;
}
測試效果
Feign + Hystrix
pom.xml配置文件
Feign中已經引入了Hystrix 所以不需要依賴了。
<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.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
</dependencies>
application.yml配置文件
server:
port: 2000
spring:
application:
name: consumer-ribbon-2000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
feign:
hystrix:
enabled: true # 開啓hystrix熔斷器
控制層
@Resource
IServiceHystrix iServiceHystrix;
@GetMapping("/toFeignHystrix/hello")
public Map helloFeignHystrix() {
return iServiceHystrix.helloFeignHystrix();
}
接口
/**故意寫錯訪問路徑*/
@FeignClient(value = "PROVIDER1",fallback = IServiceHystrixImpl.class)
public interface IServiceHystrix {
@GetMapping("/hello")/**調用PROVIDER微服務的@GetMapping("/toProvider/hello")*/
public Map<String,Object> helloFeignHystrix();
}
實現類
@Service
public class IServiceHystrixImpl implements IServiceHystrix {
@Override
public Map<String, Object> helloFeignHystrix() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("feign", "feign出錯啦");
return map;
}
}
啓動類
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceFeignApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceFeignApplication .class);
}
}
測試效果
zuul路由網關配置
pom.xml配置文件
<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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
application.yml配置文件
server:
port: 6001
#服務的名稱
spring:
application:
name: zuul-gateway
#指定註冊中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
啓動類
@EnableZuulProxy //開啓網關路由
@EnableDiscoveryClient //Eureka客戶端
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
首先在消費者微服務(端口號2000)中添加一個接口:
@GetMapping("/login")
public String login(){
return "hello zuul";
}
啓動網關微服務(端口號6001)
訪問 http://localhost:6001/consumer-ribbon-2000/login
注意: 默認路由規則 = 域名 + 端口 + 對應服務名(spring.application.name) + 接口地址
訪問成功,證明網關微服務已啓動成功。
自定義路由規則
#自定義路由映射
zuul:
routes:
my-route: # 標識 代表一組 路由名稱 隨便起一個就好了 沒有任何意義,如果沒有配置 和service-id是一樣的
service-id: consumer-ribbon-2000 # 微服務的名字 要被路由的微服務
path: /zuuls/** # url地址
訪問自定義路由規則路徑:http://localhost:6001/zuuls/login
通過網關路由,在瀏覽器網址中訪問網關項目的域名+端口號+路由規則,即可訪問到不同域名+端口號下的各個微服務了。