导读

  之前写过一篇SpringCloud从入门到精通的点我直达,微服务基础知识点我直达,今天我们使用Spring Cloud模拟一个电商项目。分别有以下2个服务,商品、订单。下面我们开始叭

技术栈

  1. SpringBoot整合SpringCloud
  2. 通信方式:http restful
  3. 注册中心:eruka
  4. 断路器:hystrix
  5. 网关:zuul

商品服务

功能点

  • 商品列表
  • 商品详情

订单服务

功能点

  • 我的订单
  • 下单接口

搭建Eureka Server

创建项目

项目结构

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.18.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ybchen</groupId>
    <artifactId>eureka_server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka_server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR6</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>

</project>

启动类上加注解

application.properties

# 服务端口号
server.port=8761
# eureka主机名
eureka.instance.hostname=localhost
# 指定当前主机是否需要向注册中心注册(不用,因为当前主机是Server,不是Client)
eureka.client.register-with-eureka=false
# 指定当前主机是否需要获取注册信息(不用,因为当前主机是Server,不是Client)
eureka.client.fetch-registry=false
# 注册中心地址
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

启动服务并查看监控台

搭建Eureka Client商品服务

创建项目

项目结构

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.18.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ybchen</groupId>
    <artifactId>product_service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>product_service</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR6</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-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>

</project>

View Code

application.properties

# 服务端口号
server.port=8771
# 服务名称
spring.application.name=product_service
# 将服务注册到注册中心,eureka_service的地址
eureka.client.service-url.defaultZone:http://localhost:8761/eureka/

ProductController.java

package com.ybchen.product_service.controller;

import com.ybchen.product_service.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName:ProductController
 * @Description:商品
 * @Author:chenyb
 * @Date:2020/11/1 8:42 下午
 * @Versiion:1.0
 */
@RestController
@RequestMapping("/api/v1/product")
public class ProductController {
    @Autowired
    private ProductService productService;

    /**
     * 商品列表
     *
     * @return
     */
    @PostMapping("list")
    public Object list() {
        return productService.listProduct();
    }

    /**
     * 根据id查询商品
     *
     * @param id
     * @return
     */
    @GetMapping("findById")
    public Object findById(@RequestParam("id") int id) {
        return productService.findById(id);
    }
}

Product.java

package com.ybchen.product_service.domain;

import java.io.Serializable;

/**
 * @ClassName:Product
 * @Description:商品实体类
 * @Author:chenyb
 * @Date:2020/11/1 8:43 下午
 * @Versiion:1.0
 */
public class Product implements Serializable {
    /**
     * 内码
     */
    private String id;
    /**
     * 商品名称
     */
    private String name;
    /**
     * 价格,分为单位
     */
    private int price;
    /**
     * 库存
     */
    private int store;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public int getStore() {
        return store;
    }

    public void setStore(int store) {
        this.store = store;
    }

    public Product() {

    }

    public Product(String id, String name, int price, int store) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.store = store;
    }

    @Override
    public String toString() {
        return "product{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", store=" + store +
                '}';
    }
}

View Code

ProductService.java

package com.ybchen.product_service.service;

import com.ybchen.product_service.domain.Product;

import java.util.List;

/**
 * @ClassName:ProductService
 * @Description:商品service
 * @Author:chenyb
 * @Date:2020/11/1 8:45 下午
 * @Versiion:1.0
 */
public interface ProductService {
    /**
     * 商品列表
     * @return
     */
    List<Product> listProduct();

    /**
     * 根据id查询商品
     * @param id
     * @return
     */
    Product findById(int id);
}

ProductServiceImpl.java

package com.ybchen.product_service.service.impl;

import com.ybchen.product_service.domain.Product;
import com.ybchen.product_service.service.ProductService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @ClassName:ProductServiceImpl
 * @Description:ProductService实现类
 * @Author:chenyb
 * @Date:2020/11/1 8:47 下午
 * @Versiion:1.0
 */
@Service
public class ProductServiceImpl implements ProductService {
    //初始化内存商品数据。模拟数据库中存储的商品
    private static final Map<Integer, Product> daoMap = new HashMap<>();

    @Value("${server.port}")
    private String port;
    static {
        for (int i = 0; i < 5; i++) {
            daoMap.put(i, new Product(i + "", "iphone_" + i, 1000 * i, 10));
        }
    }

    @Override
    public List<Product> listProduct() {
        Collection<Product> values = daoMap.values();
        return new ArrayList<>(values);
    }

    @Override
    public Product findById(int id) {
        Product product = daoMap.get(id);
        product.setName(product.getName()+"_"+port);
        return product;
    }
}

ProductServiceApplication.java

package com.ybchen.product_service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ProductServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProductServiceApplication.class, args);
    }

}

启动并查看监控台

  启动2个服务,并查看监控台

搭建Eureka Client订单服务

创建项目

项目结构

 

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.18.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ybchen</groupId>
    <artifactId>order_service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>order_service</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR6</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-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</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>

</project>

application.properties

# 服务端口号
server.port=8781
# 服务名称
spring.application.name=order-service
# 将服务注册到注册中心,eureka_service的地址
eureka.client.service-url.defaultZone:http://localhost:8761/eureka/

OrderServiceApplication.java

  启动类添加Ribbon注解

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
package com.ybchen.order_service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class OrderServiceApplication {
    /**
     * 负载均衡Ribbon
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }

}

OrderController.java

package com.ybchen.order_service.controller;

import com.ybchen.order_service.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/order")
public class OrderController {
    @Autowired
    private ProductOrderService productOrderService;
    @RequestMapping("save")
    public Object save(@RequestParam("user_id")int userId,@RequestParam("product_id")int productId){
        return productOrderService.save(userId,productId);
    }
}

ProductOrder.java

package com.ybchen.order_service.domain;

import java.util.Date;

/**
 * 商品订单实体类
 */
public class ProductOrder {
    /**
     * 主键
     */
    private int id;
    /**
     * 商品名称
     */
    private String productName;
    /**
     * 订单流水号
     */
    private String tradeNo;
    /**
     * 价格,以分位单位
     */
    private int price;
    /**
     * 创建时间
     */
    private Date createTime;
    /**
     * 用户id
     */
    private String userId;
    /**
     * 用户名称
     */
    private String userName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getTradeNo() {
        return tradeNo;
    }

    public void setTradeNo(String tradeNo) {
        this.tradeNo = tradeNo;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Override
    public String toString() {
        return "ProductOrder{" +
                "id=" + id +
                ", productName='" + productName + '\'' +
                ", tradeNo='" + tradeNo + '\'' +
                ", price=" + price +
                ", createTime=" + createTime +
                ", userId='" + userId + '\'' +
                ", userName='" + userName + '\'' +
                '}';
    }
}

View Code

ProductOrderService.java

package com.ybchen.order_service.service;

import com.ybchen.order_service.domain.ProductOrder;

public interface ProductOrderService {
    ProductOrder save(int userId, int productId);
}

ProductOrderServiceImpl.java

package com.ybchen.order_service.service.impl;

import com.ybchen.order_service.domain.ProductOrder;
import com.ybchen.order_service.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @ClassName:ProductOrderServiceImpl
 * @Description:产品订单实现类
 * @Author:chenyb
 * @Date:2020/11/2 11:34 下午
 * @Versiion:1.0
 */
@Service
public class ProductOrderServiceImpl implements ProductOrderService {
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 下单接口
     * @param userId 用户id
     * @param productId 产品id
     * @return
     */
    @Override
    public ProductOrder save(int userId, int productId) {
        Object obj=productId;
        //get方式
        Object forObject = restTemplate.getForObject("http://product-service/api/v1/product/findById?id=" + productId, Object.class);
        //post方式
//        Map<String,String> map=new HashMap<>();
//        map.put("id","1");
//        String s = restTemplate.postForObject("http://product-service/api/v1/product/test", map, String.class);
//        System.out.println(s);
        System.out.println(forObject);
        //获取商品详情
        ProductOrder productOrder=new ProductOrder();
        productOrder.setTradeNo(UUID.randomUUID().toString());
        productOrder.setCreateTime(new Date());
        productOrder.setUserId(userId+"");
        return productOrder;
    }
}

测试负载均衡

feign实战

简介

  改造订单服务,调用商品服务获取商品信息

官网例子

点我直达

改造订单服务

添加feign依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.18.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ybchen</groupId>
    <artifactId>order_service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>order_service</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR6</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-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--openfeign依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </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>

</project>

启动类上添加注解

  启动类上添加:@EnableFeignClients

 

添加一个接口

 

ProductClient.java

package com.ybchen.order_service.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 商品服务客户端
 */
// name=商品服务的服务名==========》spring.application.name=product-service
@FeignClient(name = "product-service")
@RequestMapping("/api/v1/product")
public interface ProductClient {

    @GetMapping("findById")
    String findById(@RequestParam("id") int id);
}

修改ProductOrderServiceImpl.java

原先

package com.ybchen.order_service.service.impl;

import com.ybchen.order_service.domain.ProductOrder;
import com.ybchen.order_service.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @ClassName:ProductOrderServiceImpl
 * @Description:产品订单实现类
 * @Author:chenyb
 * @Date:2020/11/2 11:34 下午
 * @Versiion:1.0
 */
@Service
public class ProductOrderServiceImpl implements ProductOrderService {
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 下单接口
     * @param userId 用户id
     * @param productId 产品id
     * @return
     */
    @Override
    public ProductOrder save(int userId, int productId) {
        Object obj=productId;
        //get方式
        Object forObject = restTemplate.getForObject("http://product-service/api/v1/product/findById?id=" + productId, Object.class);
        //post方式
//        Map<String,String> map=new HashMap<>();
//        map.put("id","1");
//        String s = restTemplate.postForObject("http://product-service/api/v1/product/test", map, String.class);
//        System.out.println(s);
        System.out.println(forObject);
        //获取商品详情
        ProductOrder productOrder=new ProductOrder();
        productOrder.setTradeNo(UUID.randomUUID().toString());
        productOrder.setCreateTime(new Date());
        productOrder.setUserId(userId+"");
        return productOrder;
    }
}

修改为

 

package com.ybchen.order_service.service.impl;

import com.ybchen.order_service.domain.ProductOrder;
import com.ybchen.order_service.service.ProductClient;
import com.ybchen.order_service.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.UUID;

/**
 * @ClassName:ProductOrderServiceImpl
 * @Description:产品订单实现类
 * @Author:chenyb
 * @Date:2020/11/2 11:34 下午
 * @Versiion:1.0
 */
@Service
public class ProductOrderServiceImpl implements ProductOrderService {
    @Autowired
    private ProductClient productClient;

    /**
     * 下单接口
     *
     * @param userId    用户id
     * @param productId 产品id
     * @return
     */
    @Override
    public ProductOrder save(int userId, int productId) {
        //-----------调用商品服务开始------------
        String byId = productClient.findById(productId);
        System.out.println(byId);
        //-----------调用商品服务结束------------
        //获取商品详情
        ProductOrder productOrder = new ProductOrder();
        productOrder.setTradeNo(UUID.randomUUID().toString());
        productOrder.setCreateTime(new Date());
        productOrder.setUserId(userId + "");
        return productOrder;
    }
}

测试商品服务

补充(设置服务调用超时时间)

  默认连接10秒,读取60秒,但是由于hystrix默认是1秒超时

官网案例,点我直达

application.properties

# 设置连接和读取超时时间
feign.client.config.default.connect-timeout=5000
feign.client.config.default.read-timeout=1100

服务降级熔断(Hystrix)

为什么要用?

  在一个分布式系统里,一个服务依赖多个服务,可能存在某个服务调用失败,比如超时、异常等,如何能保证在一个依赖出问题的情况下,不会导致整体服务故障,可以通过Hystrix来解决。

官网例子

  点我直达

修改订单服务

添加依赖

        <!--hystrix依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.18.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ybchen</groupId>
    <artifactId>order_service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>order_service</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR6</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-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--openfeign依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--hystrix依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </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>

</project>

View Code

启动类加注解

  @EnableCircuitBreaker

修改控制层

  添加注解,@HystrixCommand,并定义回调方法,返回值、入参必须一致!!!!

入参、返回值,不一致会报错

feign结合Hystrix

修改订单服务

开启hystrix

 

# 开启hystrix
feign.hystrix.enabled=true

ProductClient.java

 

package com.ybchen.order_service.service;

import com.ybchen.order_service.fallback.ProductClientFallBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

/**
 * 商品服务客户端
 */
// name=商品服务的服务名==========》spring.application.name=product-service
@FeignClient(name = "product-service",fallback = ProductClientFallBack.class)
//@RequestMapping("/api/v1/product")
public interface ProductClient {

    @GetMapping("/api/v1/product/findById")
    String findById(@RequestParam("id") int id);
}

ProductClientFallBack.java

 

package com.ybchen.order_service.fallback;

import com.ybchen.order_service.service.ProductClient;
import org.springframework.stereotype.Component;

/**
 * 针对商品服务,做降级处理
 */
@Component
public class ProductClientFallBack implements ProductClient {
    @Override
    public String findById(int id) {
        System.out.println("商品服务被降级了~~~~~~~");
        return null;
    }
}

验证商品服务熔断

  为什么对商品服务做了熔断,还返回这个结果呢,那是因为service实现类,内部发生了错误

 

熔断降级服务报警通知(重要)

  下面写一些伪代码,比如:xxx微服务挂了,然后通过短信、邮件的方式,通知相应的开发人员,紧急处理事故等。

修改订单服务

修改hystrix超时时间

禁用超时时间(不推荐)

hystrix.command.default.execution.timeout.enabled=false

设置超时时间(推荐)

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=4000

源码位置讲解

  通过这种方法,还可以设置更多的hystrix默认值

断路器Dashboard监控仪表盘

修改订单服务

添加依赖

        <!--hystrix仪表盘-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.18.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ybchen</groupId>
    <artifactId>order_service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>order_service</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR6</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-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--openfeign依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--hystrix依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--hystrix仪表盘-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </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>

</project>

pom.xml

启动类上加注解

  添加:@EnableHystrixDashboard

 

修改配置文件

# 暴露全部的监控信息
management.endpoints.web.exposure.include=*

访问仪表盘

http://127.0.0.1:8781/hystrix

http://127.0.0.1:8781/actuator/hystrix.stream

  仪表盘实际工作中用处不大(仁者见仁智者见智),纯属学习用,具体参数,请自行百度,只要把微服务熔断/降级报警通知处理好,比啥都好

版权声明:本文为chenyanbin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/chenyanbin/p/13908389.html