spring cloud feign 加载流程

spring cloud feign 加载流程,第1张

spring cloud feign 加载流程

一、如果只想加入feign,不要载入hystrix,则在引包时排除掉hystrix的包。


   org.springframework.cloud
   spring-cloud-starter-feign
   
      
            io.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-proj
		0.0.1-SNAPSHOT
	
	com.simplemall.micro.serv.page
	front-app
	frontPage
	前端页面及服务调用


	
		UTF-8
		1.7
	

	






		
			de.codecentric
			spring-boot-admin-starter-client
			1.4.6
		
		
			org.springframework.cloud
			spring-cloud-starter-eureka
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		

		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.cloud
			spring-cloud-starter-zipkin
		

		
			org.springframework.boot
			spring-boot-starter-aop
		
		
			org.springframework.boot
			spring-boot-starter-freemarker
		











		
			org.springframework.boot
			spring-boot-starter-test
		






		
			com.fasterxml.jackson.core
			jackson-core
		
		
			com.fasterxml.jackson.core
			jackson-databind
		
		
			com.fasterxml.jackson.datatype
			jackson-datatype-joda
		
		
			com.fasterxml.jackson.module
			jackson-module-parameter-names
		

		
		
			io.springfox
			springfox-swagger2
			2.6.1
		

		
		
			io.springfox
			springfox-swagger-ui
			2.6.1
		

		
			com.simplemall.micro.serv.common
			common-module
			0.0.1-SNAPSHOT
		
		
		
			org.springframework.cloud
			spring-cloud-starter-feign
			
				
						io.github.openfeign
						feign-hystrix
				
			
		
		
			org.springframework.cloud
			spring-cloud-starter-ribbon
		
		
		
			io.jsonwebtoken
			jjwt
			0.7.0
		

		
			commons-codec
			commons-codec
			1.10
		











	

	
		
			
				org.springframework.cloud
				spring-cloud-dependencies
				Camden.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 RestAPIResult login(@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);
        LoadBalancerCommand command = 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 

最后外层返回结果

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5671951.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存