java电商项目搭建-------openfeign的服务调用(熔断机制和负载均衡)

人之所以痛苦,那是因为你在成长。--------magic_guo

在微服务项目中,各个服务都部署在不同的服务器上,业务线上服务之间相互调用;话说回来,现在流行的几个服务调用工具openfeign、RPC、dubbo;

RPC—Remote Produce Call(远程过程调用),主要是通过自定义通信规则,自定义数据格式来实现通信。其实这要求通信两端都需要统一通信规则,必须约定好数据传输格式;

在我看来最流行的是:zookeeper+dubbo和eureka+openfeign两种注册中心和服务调用;
dubbo:暴露接口;
openfeign:暴露url path;是一个声明式的restful客户端,底层是httpClient,在这个基础上进行了封装使得结构更加清晰,调用方式更加简单;并且feign中集成了Hystrix(熔断降级)和Ribbon(负载均衡),保证了系统的高可用;

熔断降级:
发生情况:系统负载过高,突发流量 或者网络异常等
熔断:
微服务相互调用时,某个服务突然挂掉,会标记该服务为不可用并暂时停止调用,之后会尝试调用,如果正常运行则调用,否则则继续停用;

降级:
主动抛弃一些非必要的数据;

相同点:
1、从可用性和可靠性出发,防止系统崩溃
2、最终让用户体验到的事某些功能暂时不能用
不同点:
熔断一般是由下游服务故障导致的,而服务降级一般是从整体系统负荷考虑,由调用方控制

我使用的是feign的服务调用:
服务调用方:shop-back
服务提供方:shop-user、shop-user1;(但是这两个服务名字都是shop-user)
中间层:shop-feign

此模块可以是一个maven工程,也可使一个spring服务工程;两种搭建方式我都是用了;感觉还是maven模块搭建比较好,是用模块搭建,部署的时候使用jar包的形式引入,不用担心调用服务出现问题;(推荐将feign搭建成一个maven模块)
本文是将feign搭建成一个web服务,和maven模块搭建一样,不同的是多了一个web依赖:

shop-feign服务搭建:
依赖解释:config客户端、eureka客户端、shop-entity公共模块、web模块、feign的依赖、熔断机制的依赖;
pom文件:

<?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>com.guo</groupId>
        <artifactId>shop-pom</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <groupId>com.guo</groupId>
    <artifactId>shop-feign</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>shop-feign</name>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>

        <dependency>
            <groupId>com.guo</groupId>
            <artifactId>shop-entity</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-openfeign</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</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>

</project>

目录结构:
在这里插入图片描述
IUserService是feign调用服务的接口:
将shop-user的所有controller层的接口拿过来,将后面的中括号去掉;可以在接口上添加@RequestMapping也可以在方法上写@RequestMapping;

// value是调用的服务的模块名称;fallback是如果调用失败,则回调本地的服务;
@FeignClient(value = "shop-user", fallback = UserServiceImpl.class)
@Component
public interface IUserService {

    @RequestMapping("/user/addUser")
    public ResultEntity addUser(@RequestBody User user);
}

UserServiceImpl:

// 如果远程调用失败,则熔断调用本地的方法;
@Component
public class UserServiceImpl implements IUserService {

    private ResultEntity getMessage() {
        return ResultEntity.error("系统正在维护, 请联系管理员.......");
    }
    @Override
    public ResultEntity addUser(User user) {
        return getMessage();
    }
}

启动类:

@SpringBootApplication(scanBasePackages = "com.guo", exclude = DataSourceAutoConfiguration.class)
@EnableEurekaClient
public class ShopFeignApplication {

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

配置:
在config配置中心添加feign的配置:

feign:
  hystrix:
    enabled: true

hystrix:
  shareSecurityContext: true
  command:
    default:
      circuitBreaker:
        requestVolumeThreshold: 1
        sleepWindowInMilliseconds: 15000
        forceOpen: false
        forceClosed: false
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000

ribbon:
  ConnectTimeout: 4000
  ReadTimeout: 4000

bootstrap.yml配置:

server:
  port: 8004
spring:
  application:
    name: shop-feign
  cloud:
    config:
      profile: shop-feign, log, eureka-client
      name: application
      uri: http://localhost:9999

shop-back构建:
pom文件:

<?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>com.guo</groupId>
        <artifactId>shop-pom</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <groupId>com.guo</groupId>
    <artifactId>shop-back</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>shop-back</name>

    <properties>
        <java.version>1.8</java.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-config</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>

        <dependency>
            <groupId>com.guo</groupId>
            <artifactId>shop-feign</artifactId>
        </dependency>

        <dependency>
            <groupId>com.guo</groupId>
            <artifactId>shop-entity</artifactId>
        </dependency>

    </dependencies>

</project>

目录结构:
在这里插入图片描述
UserController:
shop-back的接口,注入feign的IUserService,然后feign再根据接口,来调用真实的shop-user应用的服务:

@RestController
@Slf4j
@RequestMapping("/userController")
public class UserController {

//    @Autowired
    @Resource
    IUserService userService;

    @RequestMapping("/addUser")
    public ResultEntity addUser(User user) {
        return ResultEntity.success(userService.addUser(user));
    }
}

启动类:
以为此模块不连接数据库,同时又有了数据源的依赖和配置,因此将此配置去除,否则服务启动不起来;
@EnableFeignClients注解:需要声明此注解是服务消费方(即调用方),,并且标识调用的feign接口位置;

@SpringBootApplication(scanBasePackages = "com.guo", exclude = DataSourceAutoConfiguration.class)
@EnableEurekaClient
@EnableFeignClients("com.guo.api")
public class ShopBackApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShopBackApplication.class, args);
    }
}

bootstrap.yml:

spring:
  cloud:
    config:
      name: application
      profile: shop-back, log, eureka-client, shop-feign
      uri: http://localhost:9999

shop-user、shop-user1服务提供方构建:
在真实的线上环境,这两个服务application name是一样的,可能部署在不同的服务器上,可以利用负载均衡,来降低服务器压力;平时访问两个服务,如果一个有问题,不至于此服务停止;目的还是保持应用的高可用;

这两个模块是一样的,只不过端口不一样,在eureka注册中心,会显示两个shop-user的服务提供者,此模块在上一篇已经搭建完成:shop-user搭建
不同点:
shop-user的配置:

server:
  port: 8001
spring:
  application:
    name: shop-user

shop-user1的配置:

server:
  port: 8002
spring:
  application:
    name: shop-user

搭建完成后,启动相关模块和这几个模块;纠错原则:
端口是否正确、启动过程中有没有错误、eureka注册中心是否都已注册上、调试接口是否返回数据正确;
在这里插入图片描述
eureka注册中心:
在这里插入图片描述
调试接口:
在两个服务提供方都正常启动的情况下:
负载均衡:
Ribbon的的负载均衡策略有很多,可以在配置中心进行修改;我使用的是默认的轮训策略;

调用8001端口的服务:
在这里插入图片描述
调用8002端口的服务:
在这里插入图片描述
只有一个服务提供方:
关闭其中一个服务,则会一直调用启动的服务;

关闭掉全部的服务提供方:
则会调用配置的回调ServiceImpl:
在这里插入图片描述


本文章教学视频来自:https://www.bilibili.com/video/BV1tb4y1Q74E?p=3&t=125


静下心,慢慢来,会很快!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值