spring cloud feign 加载流程
生活随笔
收集整理的這篇文章主要介紹了
spring cloud feign 加载流程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、如果只想加入feign,不要載入hystrix,則在引包時排除掉hystrix的包。
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-feign</artifactId><exclusions><exclusion><groupId>io.github.openfeign</groupId><artifactId>feign-hystrix</artifactId></exclusion></exclusions> </dependency>并且去掉//@EnableHystrix和
@FeignClient(name = "ACCOUNT-SERVICE"/*,fallback = AccountFeignClientHystrix.class*/) 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=2ribbon.ReadTimeout=30000 ribbon.ConnectTimeout=30000 <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.simplemall.micro.serv</groupId><artifactId>simplemall-proj</artifactId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.simplemall.micro.serv.page</groupId><artifactId>front-app</artifactId><name>frontPage</name><description>前端頁面及服務調用</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.7</java.version></properties><dependencies><!-- <dependency>--> <!-- <groupId>org.springframework.cloud</groupId>--> <!-- <artifactId>spring-cloud-starter-config</artifactId>--> <!-- </dependency>--><dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-client</artifactId><version>1.4.6</version></dependency><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><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zipkin</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!-- <dependency>--> <!-- <groupId>org.springframework.cloud</groupId>--> <!-- <artifactId>spring-cloud-starter-hystrix</artifactId>--> <!-- </dependency>--><!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-actuator</artifactId>--> <!-- </dependency>--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency> <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-devtools</artifactId>--> <!-- <optional>true</optional>--> <!-- </dependency>--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-joda</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.module</groupId><artifactId>jackson-module-parameter-names</artifactId></dependency><!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.6.1</version></dependency><!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.6.1</version></dependency><dependency><groupId>com.simplemall.micro.serv.common</groupId><artifactId>common-module</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- client request framework --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-feign</artifactId><exclusions><exclusion><groupId>io.github.openfeign</groupId><artifactId>feign-hystrix</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-ribbon</artifactId></dependency><!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.7.0</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.10</version></dependency><!-- <dependency>--> <!-- <groupId>org.springframework.cloud</groupId>--> <!-- <artifactId>spring-cloud-starter-bus-amqp</artifactId>--> <!-- </dependency>--><!-- <dependency>--> <!-- <groupId>org.springframework.cloud</groupId>--> <!-- <artifactId>spring-cloud-starter-netflix-turbine</artifactId>--> <!-- </dependency>--></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Camden.SR5</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>二、調試接口,查看代碼
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;/*** feign與@RequestParam配合使用時,一定要寫value值。* feign方法的@RequestMapping,務必與服務端方法保持一致,請求類型,請求參數,返回值等等* * TODO 可以從服務端定義一個接口層,服務實現層實現接口,調用方擴展此接口,即可完成接口定義的復用,而無須在此重新復制一次。* 但此舉會導致服務端接口變動后,調用方就會直接受影響,建議事先約定好規則* * @author guooo**/ @FeignClient(name = "ACCOUNT-SERVICE"/*,fallback = AccountFeignClientHystrix.class*/) public interface AccountFeignClient {/*** 登錄* * @param phone* @param password* @return*/@RequestMapping("/acc/login")public Account login(@RequestParam("phone") String phone, @RequestParam("password") String password);/*** 注冊* * @param phone* @param password* @return*/@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);/*** get address list* * @param accountTid* @return*/@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<AccAddress> 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;@Autowiredprivate AccountFeignClient accountFeignClient;@ApiOperation(value = "用戶登陸")@RequestMapping(value = "acc/login", method = { RequestMethod.POST,RequestMethod.GET })public RestAPIResult<String> login(@ApiParam(value = "手機號") @RequestParam(required = true) String phone,@ApiParam(value = "密碼") @RequestParam(required = true) String password, HttpSession session) {RestAPIResult<String> restAPIResult = new RestAPIResult<>();try{Account account = accountFeignClient.login(phone, password);log.info(" account:{}", JSONObject.toJSONString(account));if (StringUtils.isEmpty(account.getTid())) {restAPIResult = new RestAPIResult<String>("登陸失敗,用戶名或密碼不正確!");restAPIResult.setRespData("kkk");} else {if (account.getTid().equalsIgnoreCase("hystrix")){restAPIResult = new RestAPIResult<String>("hystrix!");restAPIResult.setRespData("觸發熔斷");}else{try {// 正常情況返回jwtJSONObject 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<String>("登陸異常!");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);LoadBalancerCommand<T> command = LoadBalancerCommand.<T>builder().withLoadBalancerContext(this).withRetryHandler(handler).withLoadBalancerURI(request.getUri()).build();try {return command.submit(new ServerOperation<T>() {@Overridepublic Observable<T> 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;/*** Submits HTTP {@link Request requests}. Implementations are expected to be thread-safe.*/ public interface Client {Response execute(Request request, Options options) throws IOException;public static class Default implements Client {@Overridepublic Response execute(Request request, Options options) throws IOException {HttpURLConnection connection = convertAndSend(request, options);return convertResponse(connection).toBuilder().request(request).build();}?執行堆棧?
?這里已經返回結果了
HttpResponse?
最后外層返回結果
?
總結
以上是生活随笔為你收集整理的spring cloud feign 加载流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springcloud ribbon r
- 下一篇: springcloud feign 加上