一、如果只想加入feign,不要载入hystrix,则在引包时排除掉hystrix的包。
org.springframework.cloud spring-cloud-starter-feignio.github.openfeign feign-hystrix
并且去掉//@EnableHystrix和
@FeignClient(name = "ACCOUNT-SERVICE") public interface AccountFeignClient {
的配置,以及application中的hystrix配置
feign.hystrix.enabled=false #任务执行超时时间 #hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=400 # #hystrix.command.default.circuitBreaker.requestVolumeThreshold=2 # ##设置统计的时间窗口值的毫秒值 #hystrix.command.default.metrics.rollingStats.timeInMilliseconds=5000 # #hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000 # #hystrix.command.default.circuitBreaker.enabled=true # ## 错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50 #hystrix.command.default.circuitBreaker.errorThresholdPercentage=50 # ## 线程池大小 #hystrix.threadpool.default.coreSize=3 ## 缓冲区大小, 如果为-1,则不缓冲,直接进行降级 fallback #hystrix.threadpool.default.maxQueueSize=5 ## 缓冲区大小超限的阈值,超限就直接降级 #hystrix.threadpool.default.queueSizeRejectionThreshold=2 # ## fallback执行并发量 #hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests=2 ribbon.ReadTimeout=30000 ribbon.ConnectTimeout=30000
4.0.0 com.simplemall.micro.serv simplemall-proj0.0.1-SNAPSHOT com.simplemall.micro.serv.page front-appfrontPage 前端页面及服务调用 UTF-8 1.7 de.codecentric spring-boot-admin-starter-client1.4.6 org.springframework.cloud spring-cloud-starter-eurekaorg.springframework.boot spring-boot-starter-testtest org.springframework.boot spring-boot-starter-weborg.springframework.cloud spring-cloud-starter-zipkinorg.springframework.boot spring-boot-starter-aoporg.springframework.boot spring-boot-starter-freemarkerorg.springframework.boot spring-boot-starter-testcom.fasterxml.jackson.core jackson-corecom.fasterxml.jackson.core jackson-databindcom.fasterxml.jackson.datatype jackson-datatype-jodacom.fasterxml.jackson.module jackson-module-parameter-namesio.springfox springfox-swagger22.6.1 io.springfox springfox-swagger-ui2.6.1 com.simplemall.micro.serv.common common-module0.0.1-SNAPSHOT org.springframework.cloud spring-cloud-starter-feignio.github.openfeign feign-hystrixorg.springframework.cloud spring-cloud-starter-ribbonio.jsonwebtoken jjwt0.7.0 commons-codec commons-codec1.10 org.springframework.cloud spring-cloud-dependenciesCamden.SR5 pom import org.springframework.boot spring-boot-maven-plugin
二、调试接口,查看代码
package com.simplemall.micro.serv.page.client; import java.util.List; //import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; //import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; //import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager; import com.simplemall.micro.serv.page.client.hystrix.AccountFeignClientHystrix; 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.RequestParam; import com.simplemall.micro.serv.common.bean.account.AccAddress; import com.simplemall.micro.serv.common.bean.account.Account; @FeignClient(name = "ACCOUNT-SERVICE") public interface AccountFeignClient { @RequestMapping("/acc/login") public Account login(@RequestParam("phone") String phone, @RequestParam("password") String password); @RequestMapping("/acc/signup") // @HystrixCommand(groupKey="test-thread-quarantine", // commandKey = "testThreadQuarantine", // threadPoolKey="test-thread-quarantine", // threadPoolProperties = { // @HystrixProperty(name="coreSize", value="30"), // @HystrixProperty(name="maxQueueSize", value="100"), // @HystrixProperty(name="keepAliveTimeMinutes", value="2"), // @HystrixProperty(name="queueSizeRejectionThreshold", value="15") // }, // fallbackMethod = "threadQuarantineFallback") public String signup(@RequestParam("phone") String phone, @RequestParam("password") String password); @RequestMapping("/address/list/{accountTid}") // @HystrixCommand(fallbackMethod="semaphoreQuarantineFallback", // commandProperties={ // @HystrixProperty( // name= HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, // value="SEMAPHORE"), // 信号量隔离 // @HystrixProperty( // name=HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, // value="100") // 信号量最大并发数 // }) public List getList( @RequestParam(value = "accountTid", required = true) @PathVariable("accountTid") String accountTid); }
@Slf4j @Api(value = "用户服务", tags = "用户服务接口") @RestController @RefreshScope // 使用该注解的类,会在接到SpringCloud配置中心配置刷新的时候,自动将新的配置更新到该类对应的字段中。需要重新触发加载动作可以使用POST方式请求/refresh接口,该接口位于spring-boot-starter-actuator依赖,调用前需添加否则404。 public class APIAccountController { private Logger logger = LoggerFactory.getLogger(APIAccountController.class); // @Value("${switch.sms}") private boolean switchSMS = true; @Autowired private AccountFeignClient accountFeignClient; @ApiOperation(value = "用户登陆") @RequestMapping(value = "acc/login", method = { RequestMethod.POST,RequestMethod.GET }) public RestAPIResultlogin(@ApiParam(value = "手机号") @RequestParam(required = true) String phone, @ApiParam(value = "密码") @RequestParam(required = true) String password, HttpSession session) { RestAPIResult restAPIResult = new RestAPIResult<>(); try{ Account account = accountFeignClient.login(phone, password); log.info(" account:{}", JSONObject.toJSonString(account)); if (StringUtils.isEmpty(account.getTid())) { restAPIResult = new RestAPIResult ("登陆失败,用户名或密码不正确!"); restAPIResult.setRespData("kkk"); } else { if (account.getTid().equalsIgnoreCase("hystrix")){ restAPIResult = new RestAPIResult ("hystrix!"); restAPIResult.setRespData("触发熔断"); }else{ try { // 正常情况返回jwt JSonObject subject = new JSonObject(true); subject.put("tid", account.getTid()); // token此处定义12小时有效,据实际应用场景确定有效性,也可以定义刷新机制,保持用户token的使用时限 String accessToken = JWTUtils.createJWT(UUIDUtils.getUUID(), subject.toJSonString(), 12 * 60 * 60 * 1000); restAPIResult.setRespData(accessToken); } catch (Exception e) { logger.error("生成jwt异常{}", e); } } } logger.info("login result = {}", restAPIResult.getRespData()); }catch (Exception e){ restAPIResult = new RestAPIResult ("登陆异常!"); restAPIResult.setRespData(e.getMessage()); } return restAPIResult; }
查看调用堆栈,我们可以看到feignClient的代理对象为FeignInvocationHandler,真正的处理类为
SynchronousMethodHandler
然后client为LoadBalancerFeignClient, 这里通过LoadBalancerContext获取负载均衡器的健康实例
ILoadBalancer lb = getLoadBalancer(); Server svc = lb.chooseServer(loadBalancerKey);
然后在AbstractLoadBalancerAwareClient.executeWithLoadBalancer进行URL中的HOST服务名替换为真实IP端口。
public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException { RequestSpecificRetryHandler handler = getRequestSpecificRetryHandler(request, requestConfig); LoadBalancerCommandcommand = LoadBalancerCommand. builder() .withLoadBalancerContext(this) .withRetryHandler(handler) .withLoadBalancerURI(request.getUri()) .build(); try { return command.submit( new ServerOperation () { @Override public Observable call(Server server) { URI finalUri = reconstructURIWithServer(server, request.getUri()); S requestForServer = (S) request.replaceUri(finalUri); try { return Observable.just(AbstractLoadBalancerAwareClient.this.execute(requestForServer, requestConfig)); } catch (Exception e) { return Observable.error(e); } } }) .toBlocking() .single(); } catch (Exception e) { Throwable t = e.getCause(); if (t instanceof ClientException) { throw (ClientException) t; } else { throw new ClientException(e); } } }
替换完是这样
接着跳到FeignLoadBalancer.execute
这里配置超时,就是ribbon的超时,然后通过RetryTemplate进行一个重试框架的调用
。
现在进到真正的client调用
这里有一个TraceFeignClient,用来做链路追踪的。
最终调用这个代理client对象真正完成HTTP请求。
Response response = this.delegate.execute(modifiedRequest, options);
代理对象源码
package feign; public interface Client { Response execute(Request request, Options options) throws IOException; public static class Default implements Client { @Override public Response execute(Request request, Options options) throws IOException { HttpURLConnection connection = convertAndSend(request, options); return convertResponse(connection).toBuilder().request(request).build(); }
执行堆栈
这里已经返回结果了
HttpResponse
最后外层返回结果
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)