一、环境准备

1、环境搭建,查看Spring Cloud专栏

2、提供服务方准备一个接口供该使用服务方(OpenFeign)使用

springcloud实现高可用 springcloud使用_ide

二、OpenFeign使用:调用提供方服务的接口就是直接调用提供方服务的Http请求,跟调用本地方法一样。

1、pom依赖

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

2、创建一个接口类,注意类上的注解“@FeignClient”和方法上的注解“@GetMapping”,类上注解“@FeignClient”的value值等于提供方注册到nacos中的名称,方法上的注解“@GetMapping”需要跟提供服务方一致和Url需要一致。

package com.cyun.security.oauth2.feign.server;

import com.cyun.core.vo.LoginUserVO;
import com.cyun.security.oauth2.feign.config.FeignSysUserConfiguration;
import com.cyun.security.oauth2.feign.config.FeignSysUserFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 系统服务 接口
 *
 * @author He PanFu
 * @date 2022-03-12 10:50:02
 */
@FeignClient(value = "sys-server")
public interface IFeignSysUserService {

    /**
     * 获取登录用户信息
     *
     * @param username 用户名
     * @param clientId 客户端标识
     * @return 登录用户信息
     */
    @GetMapping(value = "/sys_server/user/get/login/info")
    LoginUserVO getLoginUserInfo(@RequestParam String username,
                                 @RequestParam String clientId);
}

3、调用:直接调用IFeignSysUserService 服务的方法

springcloud实现高可用 springcloud使用_微服务_02

package com.cyun.security.oauth2.service.impl;

import com.cyun.core.vo.LoginUserVO;
import com.cyun.security.oauth2.exception.RetryException;
import com.cyun.security.oauth2.feign.server.IFeignSysUserService;
import com.cyun.security.oauth2.service.AccountUserDetailsService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

/**
 * 账号服务
 *
 * @author He PanFu
 * @date 2021-12-07 20:36:15
 */
@Service("accountDetailsServiceImpl")
@RequiredArgsConstructor
public class AccountDetailsServiceImpl implements AccountUserDetailsService {

    private final IFeignSysUserService sysUserService;

    /**
     * 获取用户信息
     *
     * @param username 用户名
     * @return 用户信息
     * @throws UsernameNotFoundException 用户不存在
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        final LoginUserVO loginUserVO = sysUserService.getLoginUserInfo(username, "test");
        return new User(loginUserVO.getUsername(), loginUserVO.getPassword(), AuthorityUtils.createAuthorityList(loginUserVO.getAuthorities()));
    }
}

三、服务降级处理:当提供方超时或者异常时,调用降级方法。

1、方式一:配置fallback

  • 新增FeignSysUserFallback类,实现IFeignSysUserService接口
package com.cyun.security.oauth2.feign.config;

import com.cyun.core.vo.LoginUserVO;
import com.cyun.security.oauth2.feign.server.IFeignSysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 系统服务 服务降级
 *
 * @author He PanFu
 * @date 2022-03-12 10:50:02
 */
@Component
@Slf4j
public class FeignSysUserFallback implements IFeignSysUserService {

    @Override
    public LoginUserVO getLoginUserInfo(String username, String clientId) {
        log.error("获取用户登录信息失败,用户名:{},客户端标识:{}", username, clientId);
        return null;
    }
}
  • @FeignClient注解上添加配置: fallbackspringcloud实现高可用 springcloud使用_spring_03
@FeignClient(value = "sys-server", fallback = FeignSysUserFallback.class)

2、方式二:配置fallbackFactory,可以获取异常报错信息

  • 新增FeignSysUserFallbackFactory类,实现FallbackFactory接口
    springcloud实现高可用 springcloud使用_ide_04
package com.cyun.security.oauth2.feign.config;

import com.cyun.core.vo.LoginUserVO;
import com.cyun.security.oauth2.feign.server.IFeignSysUserService;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 系统服务 服务降级(能得到错误信息)
 *
 * @author He PanFu
 * @date 2022-03-12 10:50:02
 */
@Component
@Slf4j
public class FeignSysUserFallbackFactory implements FallbackFactory<IFeignSysUserService> {

    @Override
    public IFeignSysUserService create(Throwable throwable) {
        log.error(throwable.getMessage(), throwable);

        return new IFeignSysUserService() {
            @Override
            public LoginUserVO getLoginUserInfo(String username, String clientId) {
                log.error("获取用户登录信息失败,用户名:{},客户端标识:{}", username, clientId);
                return LoginUserVO.builder().failedFlag(true).build();
            }
        };
    }
}
  • @FeignClient注解上添加配置: fallbackFactory
    springcloud实现高可用 springcloud使用_spring_05
@FeignClient(value = "sys-server", fallbackFactory = FeignSysUserFallbackFactory.class)

四、OpenFeign请求添加token,在请求头上添加内容

  • 创建FeignSysUserConfiguration类实现RequestInterceptor接口
    springcloud实现高可用 springcloud使用_ide_06
package com.cyun.security.oauth2.feign.config;

import com.cyun.tools.jwt.JwtUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 系统服务 请求添加token
 *
 * @author He PanFu
 * @date 2022-03-12 10:50:02
 */
@Configuration
public class FeignSysUserConfiguration implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //添加token
        requestTemplate.header("Authorization", request.getHeader("Authorization"));
    }

}
  • @FeignClient注解上添加配置: configuration
    springcloud实现高可用 springcloud使用_spring_07
@FeignClient(value = "sys-server", fallbackFactory = FeignSysUserFallbackFactory.class, configuration = FeignSysUserConfiguration.class)

五、问题总结

1、配置了(fallback)服务降级之后启动报错

解决方案:接口上不能添加@RequestMapper请求,去掉类上的@RequestMapper注解就能解决问题。参考链接

2、配置了(fallback)服务降级之后不生效

解决方案:查看依赖中是否依赖了Sentinel或Hystrix熔断框架,和是否配置了开启;
Sentinel:feign.sentinel.enabled=true
Hystrix:feign.hystrix.enabled=true