簡單使用SpringCloud的fegin和熔斷hystrix

SpringCloud中fegin的使用是很是優雅的,被大多數面向接口編程的程序員喜歡,並且熔斷(hystrix)則能在服務不可達時快速給客戶端一個默認響應。能夠說是很不錯的機制,今天咱們就來了解一下這兩個。java

1,準備

①,用idea創建一個空工程程序員

②,添加一個pom類型的父模塊web

③,給父工程添加子模塊便可spring

④,結構以下apache

⑤,eclipse就更簡單了,直接創建一個pom類型的父工程,右鍵父工程給其添加子模塊便可編程

2,父工程配置

①,pom.xmlapi

<?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>com.example</groupId>
    <artifactId>spc-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <!--這裏必定要是pom,否則公共的api模塊會沒法install-->
    <packaging>pom</packaging>

    <name>spc-parent</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <!-- 父類工程管理機制 -->
    <dependencyManagement>
        <dependencies>
            <!--springcloud 依賴-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--springboot依賴-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.5.12.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory><!-- 這個路徑下的文件運行訪問 -->
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <delimiters>
                        <delimit>$</delimit><!-- 訪問被$包圍的值 -->
                    </delimiters>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

3,api模塊

①,pom.xmlspringboot

<?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>

    <!--保留名字-->
    <artifactId>api</artifactId>
    <!--父工程-->
    <parent>
        <groupId>com.example</groupId>
        <artifactId>spc-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <dependencies><!-- 依賴fegin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.3.1.RELEASE</version>
        </dependency>
    </dependencies>
</project>

②,用到的pojo app

import java.util.Date;

public class Ticket {
    private Integer id;
    private String name;
    private Date buyDate;
}

③,定義接口eclipse

import com.example.api.bean.Ticket;
import com.example.api.factory.TickClientServiceFallbackFactory;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

//必須指定服務名,指定熔斷統一處理類
@FeignClient(value = "ticket-provider",fallbackFactory =TickClientServiceFallbackFactory.class)
public interface TicketService {
    //	如下爲暴露的服務,與提供者的映射路徑一致

    @RequestMapping(value = "/ticket/add", method = RequestMethod.POST)
    public boolean add(Ticket ticket);

    @RequestMapping(value = "/ticket/get/{id}", method = RequestMethod.GET)
    public Ticket get(@PathVariable("id") Long id);

    @RequestMapping(value = "/ticket/list", method = RequestMethod.GET)
    public List<Ticket> list();

}

④,熔斷處理類

import com.example.api.bean.Ticket;
import com.example.api.service.TicketService;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

//加入到ioc容器
@Component
public class TickClientServiceFallbackFactory implements FallbackFactory<TicketService> {

    @Override
    public TicketService create(Throwable cause) {
//        經過匿名內部類的方式,若是出錯默認結果
        return new TicketService() {
            @Override
            public boolean add(Ticket ticket) {
                System.out.println("添加失敗^_^");
                return false;
            }

            @Override
            public Ticket get(Long id) {
                Ticket ticket = new Ticket();
                ticket.setId(1);
                ticket.setBuyDate(new Date());
                ticket.setName("請稍後重試");
                return ticket;
            }

            @Override
            public List<Ticket> list() {
                return null;
            }
        };
    }
}

4,註冊模塊

①,pom.xml

<artifactId>eureka</artifactId>

    <parent>
        <groupId>com.example</groupId>
        <artifactId>spc-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <dependencies>
        <!--eureka-server服務端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
    </dependencies>

②,application.properties

#eueka 主機名
eureka.instance.hostname=eureka-service
#不註冊本身
eureka.client.register-with-eureka=false
#獲取服務
eureka.client.fetch-registry=false
#提供者和消費者的註冊地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

server.port=8761

③,主配置類

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
//開啓eureka
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {

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

5,消費者配置

①,pom.xml

<artifactId>customer</artifactId>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>spc-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <dependencies>
        <!-- hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>com.springcloud</groupId>
            <artifactId>microservicecloud-api</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- Feign相關 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <!-- eureka相關 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
    </dependencies>

②,application.properties

server.port=8201

spring.application.name=ticket-customer-fegin
eureka.instance.prefer-ip-address=true
#註冊地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
#開啓熔斷
feign.hystrix.enabled=true

③,主配置類

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
//註冊到eureka
@EnableEurekaClient
@SpringBootApplication
//指定fegin掃描的包,須要即掃描api工程中熔斷配置類
@EnableFeignClients(basePackages= {"com.example.api"})
//須要掃描api工程及本工程註冊的bean
@ComponentScan("com.example")
public class CustomerApplication {

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

④,controller層代碼編寫

import com.example.api.bean.Ticket;
import com.example.api.service.TicketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class CustomerController {

    @Autowired
    private TicketService ticketService;

    @RequestMapping(value = "/fegin/add")
    public boolean add(Ticket ticket) {
        return ticketService.add(ticket);
    }

    @RequestMapping(value = "/fegin/get/{id}")
    public Ticket get(@PathVariable("id") Long id) {
        return ticketService.get(id);
    }

    @RequestMapping(value = "/fegin/list")
    public List<Ticket> list() {
        return ticketService.list();
    }
}

6,提供者配置

①,pom.xml

<artifactId>provider</artifactId>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>spc-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <dependencies>
        <!-- 引入本身定義的api通用包,能夠使用Dept部門Entity -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>api</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- 將微服務provider側註冊進eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

②,application.properties

server.port=8002
#服務名
spring.application.name=ticket-provider
#使用ip進行註冊
eureka.instance.prefer-ip-address=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

③,主配置類

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableEurekaClient //啓動後註冊到eureka
@SpringBootApplication
public class ProviderApplication {

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

④,controller層代碼

import com.example.api.bean.Ticket;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.Date;
import java.util.List;

@RestController
public class TicketController {

    @RequestMapping(value = "/ticket/add", method = RequestMethod.POST)
    public boolean add(Ticket ticket) {
        System.out.println("添加成功");
        return true;
    }

    @RequestMapping(value = "/ticket/get/{id}", method = RequestMethod.GET)
    public Ticket get(@PathVariable("id")Long id) {
        Ticket ticket = new Ticket();
        ticket.setId(1);
        ticket.setBuyDate(new Date());
        ticket.setName("《男兒當自強》");
        return ticket;
    }

    @RequestMapping(value = "/ticket/list", method = RequestMethod.GET)
    public List<Ticket> list() {
        System.out.println("找到了好多數據。。。。");
        return Collections.emptyList();
    }
}

7,測試

①,啓動註冊工程(eureka)

②,啓動消費者工程,此時已經能夠看到效果

③,訪問消費者接口,看到以下信息,說明熔斷起效果了

④,啓動提供者工程,等幾秒後,便能正常訪問提供者

相關文章
相關標籤/搜索