Spring-Cloud Note
组件
- Eureka
- Ribbon
- Feign
- Hystrix
- Zuul
@SpringCloudApplication注解
一个Spring Cloud标准应用包含服务发现以及断路器
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
- @SpringCloudApplication
- @SpringBootApplication
- @EnableDiscoveryClient
- @EnableCircuitBreaker
 
常用服务配置
spring:
  application:
    name: client                                #服务名称
server:
  port: 9070                                    #启动端口
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9090/eureka #定义服务注册中心地址
Eureka-服务注册/发现
配置
server:
  port: 9090
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
入口
package com.github.crazyjay97.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}
服务发现客户端可以在入口处加@EnableDiscoveryClient注解
可以打开 链接访问eurekaUI界面
接口服务
配置
server:
  port: 9080
spring:
  application:
    name: api
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9090/eureka
入口
package com.github.crazyjay97.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class ApiApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiApplication.class, args);
    }
}
接口控制器
package com.github.crazyjay97.api.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@RestController
public class Controller {
    @RequestMapping("hello")
    public String Hello() {
        System.out.println("请求处理");
        try {
            // 模拟任务处理,以及为熔断器做准备
            TimeUnit.SECONDS.sleep(new Random().nextInt(3));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "word";
    }
}
起多个
api服务为负载均衡做测试,可以在启动时加-Dserver.port=9081参数指定端口
ribbon-客户端负载均衡
配置
spring:
  application:
    name: client
server:
  port: 9000
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9090/eureka
package com.github.crazyjay97.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class ClientApplication {
    @Bean
    @LoadBalanced  //加载 restTemplate Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}
调用接口
package com.github.crazyjay97.client.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("client")
public class Controller {
    @Autowired
    private RestTemplate restTemplate;
    @RequestMapping("hello")
    public String hello() {
        //API 接口服务的名称,在eureka中以大写显示,这里写成大写
        String body = restTemplate.getForEntity("http://API/hello", String.class).getBody();
        return "hello" + body;
    }
}
hystrix-断路器
配置
spring:
  application:
    name: client
server:
  port: 9000
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9090/eureka
入口
package com.github.crazyjay97.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class ClientApplication {
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}
服务
package com.github.crazyjay97.client.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("client")
public class Controller {
    @Autowired
    private RestTemplate restTemplate;
    @RequestMapping("hello")
    @HystrixCommand(fallbackMethod = "errorFallback")
    public String hello() {
        String body = restTemplate.getForEntity("http://API/hello", String.class).getBody();
        return "hello" + body;
    }
    public String errorFallback() {
        return "error";
    }
}
可以关掉一个
api服务然后请求在不加断路器的情况下请求接口,当请求到已经关闭的api服务时,会出现500错误,当加断路器以后会出现处理之后的接口。当服务不可达、超时或故障的时候,触发断路器的fallback方法。
feign-声明式调用
配置
spring:
  application:
    name: feign-client
server:
  port: 9070
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9090/eureka
入口
package com.github.crazyjay97.feignclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients //需要开启feign
@EnableCircuitBreaker
public class FeignclientApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeignclientApplication.class, args);
    }
}
定义接口
package com.github.crazyjay97.feignclient.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient("api") //接口服务的名称
public interface ApiService {
    @RequestMapping("/hello")
    String hello();
}
服务
package com.github.crazyjay97.feignclient.controller;
import com.github.crazyjay97.feignclient.service.ApiService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
    @Autowired
    private ApiService apiService;
    @RequestMapping("hello")
    @HystrixCommand(fallbackMethod ="helloFallback")
    public String hello() {
        return "hello " + apiService.hello();
    }
    public String helloFallback() {
        return "error";
    }
}
zuul-网关服务
配置
zuul:
  routes:
    api-a-url:                      #自定义名称
      path: /api/**                 #前缀
      url: http://localhost:9070/   #转发的地址
入口
package com.github.crazyjay97;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}
config-配置中心
配置
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/crazyjay97/cloud.git #仓库地址
          searchPaths: config                          #文件于仓库路径
          username: root
          password: root
server:
  port: 9050
依赖
    
        org.springframework.cloud 
        spring-cloud-config-server 
        2.2.1.RELEASE 
     
 
入口
package com.github.crazyjay97;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
配置中心客户端
配置-bootstrap.yml
spring:
  application:
    name: config-client
  cloud:
    config:
      profile: base
      label: master
      uri: http://localhost:9050
server:
  port: 9040
依赖
    
        org.springframework.boot 
        spring-boot-starter-web 
     
    
        org.springframework.cloud 
        spring-cloud-starter-config 
        2.2.1.RELEASE 
     
 
入口
package com.github.crazyjay97;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConfigClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }
}
控制器
package com.github.crazyjay97.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
    @Value("${cloud-version}")
    private String version;
    @Autowired
    private Environment environment;
    @GetMapping("getConfig")
    public String getConfig() {
        return version + "-" + environment.getProperty("cloud-version");
    }
}