Spring Cloud 2日間の速学学習記録


基礎知識の補充
オブジェクトのコピー
	    Product product = productService.findById(id);
        Product result = new Product();
        BeanUtils.copyProperties(product,result);

スレッドスリープ
        TimeUnit.SECONDS.sleep(1);

Spring Boot Redisの使用
  • 依存
  • 
                org.springframework.boot
                spring-boot-starter-data-redis
            
    
  • プロファイル(Spring下)
  • redis:
    	    database: 0
    	    host: 127.0.0.1
    	    port: 6379
    	    timeout: 2000
    
  • ログ印刷
  • private final Logger logger = LoggerFactory.getLogger(getClass);
    logger.info("test");
    

    プロジェクトの使用については、章を溶断するを参照してください.
    Eurekaの作成時にideaが依存をチェックします.
    消費者を作成するときにideaが依存をチェックします.
    消費者Ribbon
    Ribbonの作成時にideaが依存をチェックします.
  • web > web
  • clouding discovery > eureka discovery
  • clouding routing > ribbon

  • クラスの参加を開始
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    

    呼び出し方法1(MapはJsonデータを受け入れることができる)
    	Map<String,Object> productMap = restTemplate.getForObject("http://product-service/api/v1/product/find?id="+productId, Map.class);
    

    呼び出し方法2
        @Autowired
        private LoadBalancerClient loadBalancer;
        
        ServiceInstance instance = loadBalancer.choose("product-service");
        String url = String.format("http://%s:%s/api/v1/product/find?id="+productId, instance.getHost(),instance.getPort());
        RestTemplate restTemplate = new RestTemplate();
        Map<String,Object> productMap = restTemplate.getForObject(url, Map.class);
    

    カスタムロードバランシング
    product-service:
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    

    消費者feign
    に頼る
     		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-openfeign</artifactId>
    	    </dependency>
    

    クラスの追加を開始
    	@EnableFeignClients
    

    インタフェースを追加
    	@FeignClient(name = "product-service")
    public interface ProductClient {
        @GetMapping("/api/v1/product/find")
        String findById(@RequestParam(value = "id") int id);
    }
    

    よびだし
     	@Autowired
     	private ProductClient productClient;
    	String response = productClient.findById(productId);
    

    タイムアウトコールの変更
    feign:
      client:
        config:
          default:
            connectTimeout: 2000
            readTimeout: 2000
    

    Feignにはribbenが含まれています.カスタムロードの均等化
    Hystrix溶断
    使用方法1
  • 加入依存
           
              org.springframework.cloud
              spring-cloud-starter-netflix-hystrix
          
    
  • 起動クラス注釈
  • を加える
    @EnableCircuitBreaker
    
  • メソッドに注釈
  • を加える
    @RequestMapping("save")
        @HystrixCommand(fallbackMethod = "saveOrderFail")
        public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId){
    
            Map<String, Object> data = new HashMap<>();
            data.put("code", 0);
            data.put("data", productOrderService.save(userId, productId));
            return  data;
        }
    
    
        //  ,         api    
        private Object saveOrderFail(int userId, int productId){
    
            Map<String, Object> msg = new HashMap<>();
            msg.put("code", -1);
            msg.put("msg", "      ,      ,    ");
            return msg;
        }
    

    方法2 Feignがhystrixを開く
  • プロファイル
  • feign:
      hystrix:
        enabled: true
    
  • Clientにこのメソッドを追加して、戻りクラス
  • をカスタマイズします.
    @FeignClient(name = "product-service", fallback = ProductClientFallback.class)
    
  • コード例
  • /**
     *       ,     
     */
    @Component
    public class ProductClientFallback implements ProductClient {
        @Override
        public String findById(int id) {
    
            System.out.println("feign   product-service findbyid   ");
    
            return null;
        }
    }
    
    

    ヒューズダウングレードアラーム
  • Redis注釈
  • を使用
        @Autowired
        private StringRedisTemplate redisTemplate;
        /**
          key-value   
        **/
        String sendValue = redisTemplate.opsForValue().get(saveOrderKye);
    
  • コード例
  • //    
            String saveOrderKye = "save-order";
    
            String sendValue = redisTemplate.opsForValue().get(saveOrderKye);
            final String ip = request.getRemoteAddr();
            new Thread( ()->{
                if (StringUtils.isBlank(sendValue)) {
                    System.out.println("    ,      ,       ,ip   ="+ip);
                    //    http  ,       TODO
                    redisTemplate.opsForValue().set(saveOrderKye, "save-order-fail", 20, TimeUnit.SECONDS);
    
                }else{
                    System.out.println("       ,20       ");
                }
    
            }).start();
    
    
            Map<String, Object> msg = new HashMap<>();
            msg.put("code", -1);
            msg.put("msg", "      ,      ,    ");
            return msg;
    

    ヒューズタイムアウト処理
    	hystrix:
    	  command:
    	    default:
    	      execution:
    	        isolation:
    	          thread:
    	            timeoutInMilliseconds: 4000
    
    

    遮断器ダッシュボード実戦監視
  • 加入依存
  •        
                org.springframework.cloud
                spring-cloud-starter-netflix-hystrix-dashboard
            
    
            
                org.springframework.boot
                spring-boot-starter-actuator
            
    
  • 起動クラス追加注記
  • @EnableHystrixDashboard
    
  • プロファイルendpoint
  • を追加
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
  • 4、アクセスポートhttp://localhost:8781/hystrix Hystrix Dashboard入力:http://localhost:8781/actuator/hystrix.stream

  • マイクロサービスゲートウェイzul
  • 選択依存Cloud Discovery"Eureka Discovery Cloud Routing"Zuul
  • を作成
  • 起動クラス注釈
  • を加える
    	@EnableZuulProxy
    

    デフォルトのアクセス規則http://gateway:port/service-id/**
    			  :   /order-service/api/v1/order/save?user_id=2&product_id=1
    				     /xdclass_order/api/v1/order/save?user_id=2&product_id=1
    
    	       :
    		zuul:
    		 routes:
    		 	order-service: /apigateway/**
    
    
    	      :
    		   :              
    			/order-service/api/v1/order/save
    
    		  :
    		zuul: 
    			ignored-patterns:
    				- /*-service/api/v1/order/save
    

    Zuul常用問題分析
    1、        
    	          
    
    2、Http       
    
    3、          ,    order   ,    
    
    
    4、  RequestContext,     
    

    カスタムZuulフィルタでログイン認証実戦を実現
      :   Zuul           
    
    1、    filter 
    
    2、     ,  ZuulFilter,       
    
    3、       ,@Component, Spring  
    
    package net.xdclass.apigateway.filter;
    
    
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    
    import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
    
    /**
     *      
     */
    @Component
    public class LoginFilter  extends ZuulFilter {
    
        /**
         *      ,     
         * @return
         */
        @Override
        public String filterType() {
            return PRE_TYPE;
        }
    
        /**
         *      ,      
         * @return
         */
        @Override
        public int filterOrder() {
    
            return 4;
        }
    
    
        /**
         *        
         * @return
         */
        @Override
        public boolean shouldFilter() {
    
            RequestContext requestContext = RequestContext.getCurrentContext();
            HttpServletRequest  request = requestContext.getRequest();
    
           //System.out.println(request.getRequestURI()); ///apigateway/product/api/v1/product/list
            //System.out.println(request.getRequestURL()); //http://localhost:9000/apigateway/product/api/v1/product/list
    
            //ACL
    
            if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())){
                return true;
            }else if ("/apigateway/order/api/v1/order/list".equalsIgnoreCase(request.getRequestURI())){
                return true;
            }else if ("/apigateway/order/api/v1/order/find".equalsIgnoreCase(request.getRequestURI())){
                return true;
            }
    
            return false;
        }
    
        /**
         *     
         * @return
         * @throws ZuulException
         */
        @Override
        public Object run() throws ZuulException {
    
            //JWT
            RequestContext requestContext =  RequestContext.getCurrentContext();
            HttpServletRequest  request = requestContext.getRequest();
    
            //token  
            String token = request.getHeader("token");
    
            if(StringUtils.isBlank((token))){
                token  = request.getParameter("token");
            }
    
    
            //                  JWT
            if (StringUtils.isBlank(token)) {
                    requestContext.setSendZuulResponse(false);
                    requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            }
            return null;
        }
    }
    
    

    Google guava限流
    package net.xdclass.apigateway.filter;
    
    import com.google.common.util.concurrent.RateLimiter;
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    
    import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
    
    /**
     *     
     */
    @Component
    public class OrderRateLimiterFilter extends ZuulFilter {
    
    
        //    1000   
        private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000);
    
        @Override
        public String filterType() {
            return PRE_TYPE;
        }
    
        @Override
        public int filterOrder() {
            return -4;
        }
    
    
    
        @Override
        public boolean shouldFilter() {
    
    
            RequestContext requestContext = RequestContext.getCurrentContext();
            HttpServletRequest request = requestContext.getRequest();
    
            //        
            if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())){
                return true;
            }
    
            return false;
        }
    
        @Override
        public Object run() throws ZuulException {
            RequestContext requestContext = RequestContext.getCurrentContext();
            if(!RATE_LIMITER.tryAcquire()){
                requestContext.setSendZuulResponse(false);
                requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
            }
            return null;
        }
    
    
    
    }
    

    学習対象
  • ランブダ式
  • スレッドプール
  • の構成方法