SpringBoot2.0 integrated fuse mechanism project combat ribbon +

Note: spring boot version is 2.0 or more, if it is 2.0 or less, certainly not, since you do, be sure to use the latest version.

1 Introduction

         Spring Cloud Ribbon is based on HTTP and TCP client load balancing tool, which implements based Netflix Ribbon. By Spring Cloud package, it allows us to easily service-oriented REST template automatically converted to service calls requesting client load balancing. Spring Cloud Ribbon although only a utility class framework, it is not like the service registry, distribution center, API gateway as the need to deploy independent, but it exists in almost every Spring Cloud Service and build micro-infrastructure. Because the calls between micro-services, API gateway forwards the request to other content, they are actually implemented by the Ribbon.

     1.1 client load balancing

         As business increasingly large user population using more and more, in addition to the operations carried out by external module splits, load balancing is a need to face the problem, load balancing can ensure that the system of HA, reduce server pressure, load balancing is divided into two, one is hardware load balancing, there is a software load balancing, the common market software load balancing software nginx, dubbo.

       nginx web page is mainly for project clusters, load balancing. It corresponds to the case of FIG nginx rabbon, equivalent Tomcat server (the server can be other), this shunt mainly request.

       dubbo, business logic can be used for load balancing, for example, a user in a shopping online under an order to my personal understanding, nginx first request for a diversion, a network load balancing tree structure in the business through dubbo, forming . Personal feeling zk + dubbo use is still quite simple, the only bad thing, because he uses a remote call rpc way, the bottom is used hession, first of all, the two projects docking interface parameters have to serialization, two package path of the project to be consistent. Le said some far, here we return to the topic.

 

2. Structure of the project

This project is the first project polymerization, polymerization do not understand the project, you can go to find out, but too much detail here.

Springcloud first create a project, and then were created four modules

(1)springcloud-eureka-server    8761

             eureka registration services, registration provides other servers. This is similar to the role of zookeeper, recommended more, taking into account individual service registration, it affects the whole system.

(2)springcloud-eureka-clienta   8762

   A service provider, similar to the role of producer dubbo which, for convenience, here abbreviated as A Service Provider

(3)springcloud-eureka-clientB   8763

   Service provider B, similar to the role of producer dubbo which, for convenience, here abbreviated as service provider B

(4)springcloud-ribbon-customer  8764

   Consumer services, similar to the role of consumers dubbo inside, for convenience, here abbreviated as consumers

  Service Provider A and Server B providers will offer a hello method, by polling algorithm consumers were calling server A and server provider B

2.1 Parent Project springcloud project

      Mainly dependent on the extraction of public  

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

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.fqyd</groupId>
    <artifactId>springcloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud</name>
    <packaging>pom</packaging>
    <description>Demo project for Spring Boot</description>

    <modules>
        <module>springcloud-eureka-server</module>
        <module>springcloud-eureka-clienta</module>
        <module>springcloud-eureka-clientb</module>
        <module>springcloud-ribbon-customer</module>
    </modules>

    <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.RELEASE</spring-cloud.version>
</properties>

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

    <!-- Spring Cloud 管理依赖 -->
    <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>

 2.2 springcloud-eureka-server project

Service registry, the recommended way to use the cluster, through multiple "," separate

2.2.1 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>com.fqyd</groupId>
    <artifactId>springcloud-eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-eureka-server</name>
    <packaging>jar</packaging>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>com.fqyd</groupId>
        <artifactId>springcloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
</project>

2.2.2 application.yml

server:
  port: 8761
spring:
  application:
    name: eurka-server
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    server:
      # 关闭自我保护
      enable-self-preservation: false
      # 清理服务器
      eviction-interval-timer-in-ms: 60000
  # 关闭程序
  endpoints:
    shutdown:
      enabled: true
      sensitive: true

Note: The port here is 8761 port, follow-up will be used, eureka.client.registerWithEureka = false eureka shows that they are not service providers do not need to register itself into the registry, or an error occurs. fetchRegistry indicate whether to obtain registration information from Eureka server, the default is true, because here is the server itself, does not need to acquire. defaultZone registered in the registration address information provided by the server. 

2.3.3 Server startup class

package com.fqyd;

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


@EnableEurekaServer
@SpringBootApplication
public class SpringcloudEurekaServerApplication {

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

}

2.3.4 Effect

http://localhost:8761/

Start the service registration via the following address, see the following figure.

 

2.3 springcloud-eureka-clienta项目

  主要是提供服务注册,注册到eureka-server上。

  2.3.1 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>
    <parent>
        <groupId>com.fqyd</groupId>
        <artifactId>springcloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <groupId>com.fqyd</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
</project>

这里只引入勒eureka-client的依赖,其他的依赖,父项目已导入。

2.3.2 application.yml

server:
  # 服务提供监听端口[eureka客户端],注意改端口不能与本机服务器端口冲突
  port: 8762
# 多环境通用部分[各个环境可以覆盖通用字段]
spring:
  application:
    # 通用名字,其他环境可以覆盖:为你的应用起个名字,该名字将注册到eureka注册中心
    name: client-service
eureka:
  client:
    # 是否将eureka自身作为应用注册到eureka注册中心,默认为true
    registerWithEureka: true
    serviceUrl:
      # 这里可以填写所有的eureka服务器地址并以','分离,当前面不能注册时候,自动选择后面的进行注册,排除单点故障问题
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

prefer-ip-address:true主要是为了解决注册到服务器上显示为主机名的问题,一般建议显示为ip,方便区分。


2.3.3 服务器启动类

package com.fqyd.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;

@EnableDiscoveryClient
@SpringBootApplication
@ComponentScan(basePackages={"com"})
public class DemoApplication {

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

}

2.3.4 暴露的接口

package com.fqyd.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class ServiceAController {

    @RequestMapping("/hello")
    public String testA() {
        return "Hello world AAAAAAAAAA!";
        }
}

2.3.5 效果

注意:先启动服务器注册的项目eureka-server的服务,再启动本服务,不然会报错。

http://localhost:8762/hello

2.4 springcloud-eureka-clientb项目 

    2.4.1 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>
    <parent>
        <groupId>com.fqyd</groupId>
        <artifactId>springcloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.fqyd</groupId>
    <artifactId>springcloud-eureka-clientb</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-eureka-clientb</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

    2.4.2 application.yml

server:
  # 服务提供监听端口[eureka客户端],注意改端口不能与本机服务器端口冲突
  port: 8763
# 多环境通用部分[各个环境可以覆盖通用字段]
spring:
  application:
    # 通用名字,其他环境可以覆盖:为你的应用起个名字,该名字将注册到eureka注册中心
    name: client-service
eureka:
  client:
    # 是否将eureka自身作为应用注册到eureka注册中心,默认为true
    registerWithEureka: true
    serviceUrl:
      # 这里可以填写所有的eureka服务器地址并以','分离,当前面不能注册时候,自动选择后面的进行注册,排除单点故障问题
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

 A和B服务的名称保持一致,后续,进行负载均衡调用的时候会用到该服务名。

2.4.3 controller类

package com.fqyd.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ServiceAController {

    @RequestMapping("/hello")
    public String testA() {
        return "Hello world BBBBBBBB!";
    }
}

2.4.4 启动类

package com.fqyd;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class SpringcloudEurekaClientbApplication {

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

}

2.4.5.效果 

http://localhost:8763/hello

 2.5 springcloud-ribbon-customer 消费者项目

 2.5.1 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>
    <parent>
        <groupId>com.fqyd</groupId>
        <artifactId>springcloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.fqyd</groupId>
    <artifactId>ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ribbon</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- spring cloud 客户注册 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!-- Ribbon依赖 -->
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-httpclient</artifactId>
        </dependency>
        <!-- 加入熔断机制依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>
</project>

2.5.2 application.yml

# 多环境通用部分[各个环境可以覆盖通用字段]
spring:
  application:
    # 通用名字,其他环境可以覆盖:为你的应用起个名字,该名字将注册到eureka注册中心
    name: ribbon-consumer
server:
  # 服务提供监听端口[eureka客户端],注意改端口不能与本机服务器端口冲突
  port: 8764
eureka:
  client:
    # 是否将eureka自身作为应用注册到eureka注册中心,默认为true
    registerWithEureka: true
    serviceUrl:
      # 这里可以填写所有的eureka服务器地址并以','分离,当前面不能注册时候,自动选择后面的进行注册,排除单点故障问题
      defaultZone: http://localhost:8761/eureka/
      # 这里可以填写所有的eureka服务器地址并以','分离,当前面不能注册时候,自动选择后面的进行注册,排除单点故障问题

2.5.3 controller

package com.fqyd.controller;

import com.fqyd.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CustomerController {
    
    @Autowired
    HelloService service;
    
    @RequestMapping("/hello")
    public String customer(){
        return service.helloService();
    }
}

2.5.4 service类

package com.fqyd.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@Service
public class HelloService {

    @Autowired
    RestTemplate restTemplate;            // 负载均衡ribbon对象

    // 熔断错误回调方法
    public String helloFallBack(){
        return "Error occurre熔断错误!";
    }

    /**
     * 调用Eureka系统中名都为test-service的ribbon_service_a或ribbon_service_b的方法/hello
     * @return
     */
    // 注解指定发生错误时的回调方法
    @HystrixCommand(fallbackMethod="helloFallBack")
    public String helloService(){
        // Get请求调用服务,restTemplate被@LoadBalanced注解标记,Get方法会自动进行负载均衡
        // restTemplate会交替调用service_a和service_b
        return restTemplate.getForObject("http://client-service/hello", String.class);
    }
}

注意:这里增加了熔断机制,如果直接调用helloService失败后,会直接调用fallbackMethod="helloFallBack"对应的方法。主要是解决,例如,服务提供者没有启动,先启动消费者,调用失败的问题。

2.5.5启动者

package com.fqyd;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;

@EnableCircuitBreaker         // 开启断路器功能,进行容错管理
@EnableDiscoveryClient        // 开启服务发现功能
@EnableEurekaClient
@SpringBootApplication
@ComponentScan(basePackages={"com"})
public class RibbonApplication {

    @Bean                     // 注册一个具有容错功能的RestTemplate
    @LoadBalanced
        // 开启负载均衡客户端
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

}

2.5.6效果

不启动服务提供者A或者B,启动服务注册者项目和消费者项目

启动服务提供者A或者B,启动服务注册者项目和消费者项目

一直刷新页面,发现AAAAA和BBBB是1:1轮询的,负载均衡默认就是1:1各自的比重一样。

 

项目代码地址:

链接:https://pan.baidu.com/s/1cNxgbzk2X_oe4sMCTjIZjQ 
提取码:ujnt 
复制这段内容后打开百度网盘手机App,操作更方便哦

 

如果你热衷技术,喜欢交流,欢迎加入我们! 

Guess you like

Origin blog.csdn.net/qq_16855077/article/details/93207884