SpringCloud笔记

可以参考:https://blog.csdn.net/zajiayouzai/article/details/80612729

项目的构建:

1.父工程:pom

<?xml version="1.0" encoding="UTF-8"?>

<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>

 

    <groupId>com.itmuch.cloud</groupId>

    <artifactId>microservice-spring-cloud</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <packaging>pom</packaging>

 

    <modules>

        <module>microservice-provider-user</module>

        <module>microservice-discovery-eureka</module>

    </modules>

   

    <properties>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <java.version>1.8</java.version>

    </properties>

 

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.4.1.RELEASE</version>

    </parent>

    <dependencyManagement>

        <dependencies>

            <dependency>

                <groupId>org.springframework.cloud</groupId>

                <artifactId>spring-cloud-dependencies</artifactId>

                <version>Camden.SR1</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>

 

 

 

2.子工程:Eureka:discovery:

Eureka

2.1服务端:

依赖:

    <dependency>

           <groupId>org.springframework.cloud</groupId>

           <artifactId>spring-cloud-starter-eureka-server</artifactId>

       </dependency>

       <dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-security</artifactId>

       </dependency>

 

 

 

配置:(yml

security:    #需要导入spring-boot-starter-security

  basic:

    enabled: true

  user:

    name: user

    password: password123 #为Euraka server 添加一个认证,当访问localhost:8761会要求验证

server:

  port: 8761   //Euraeka 默认端口

eureka:

  client:

    register-with-eureka: false   //目前只是单机,所以false,表示不把自己当客户端使用

    fetch-registry: false    //目前只是单机,所以false 

    service-url:

      defaultZone: http://user:password123@localhost:8761/eureka

通过:http://user:password123@localhost:8761/eureka 可以查看注册情况

使用:

@SpringBootApplication

@EnableEurekaServer

public class EurekaApplication {

  public static void main(String[] args) {

    SpringApplication.run(EurekaApplication.class, args);

  }

}

 

 

2.2服务客户端(注册):

依赖:

<dependency>

           <groupId>org.springframework.cloud</groupId>

           <artifactId>spring-cloud-starter-eureka</artifactId>

       </dependency>

 

 

 

配置:

eureka:

  client:

    healthcheck:

      enabled: true  #心跳检测

    serviceUrl:

      defaultZone: http://user:password123@localhost:8761/eureka

  instance:

prefer-ip-address: true  #默认注册后会用机器名:此处让它显示ip

instance-id: #自定义显示${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}

  

 

使用:

@SpringBootApplication

@EnableEurekaClient

public class MicroserviceSimpleConsumerMovieApplication {

  @Bean

  public RestTemplate restTemplate() {

    return new RestTemplate();

  }

  public static void main(String[] args) { SpringApplication.run(MicroserviceSimpleConsumerMovieApplication.class, args);

  }

}

 

2.3健康检查heath checks:

  

<dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-actuator</artifactId>

</dependency>

配置yml

eureka:

  client:

    healthcheck:

      enabled: true

2.4.使用EurekaClient

  @Autowired

  private UserRepository userRepository;

 

  @Autowired

  private EurekaClient eurekaClient;

 

  @Autowired

  private DiscoveryClient discoveryClient;

 

  @GetMapping("/eureka-instance")

  public String serviceUrl() {

    InstanceInfo instance = this.eurekaClient.getNextServerFromEureka("MICROSERVICE-PROVIDER-USER", false);

    return instance.getHomePageUrl();

  }

 

  @GetMapping("/instance-info")

  public ServiceInstance showInfo() {

    ServiceInstance localServiceInstance = this.discoveryClient.getLocalServiceInstance();

    return localServiceInstance;

  }

2.5使用RestTemplate

配置:

@SpringBootApplication

@EnableEurekaClient

public class ConsumerMovieRibbonApplication {

 

  @Bean //注入一个RestTemplate

    public RestTemplate restTemplate() {

    return new RestTemplate();

  }

 

  public static void main(String[] args) {

    SpringApplication.run(ConsumerMovieRibbonApplication.class, args);

  }

}

使用:

@RestController

public class MovieController {

  @Autowired

  private RestTemplate restTemplate;

  @Autowired

  private LoadBalancerClient loadBalancerClient;

 

  @GetMapping("/movie/{id}")

  public User findById(@PathVariable Long id) {

    return this.restTemplate.getForObject("http://localhost:8900/simple/

" + id, User.class);

  }

  }

 

 

 

2.6 Robbon(客户端负载均衡)

依赖:(Euraka server中包含;可以不导入)

<dependency>

<groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-netflix</artifactId>

        <version>2.0.1.RELEASE</version>

</dependency>

配置:(在RestTemplate上加注解@LoadBalanced

@SpringBootApplication

@EnableEurekaClient

public class ConsumerRibbonApplication {

 

  @Bean

  @LoadBalanced

  public RestTemplate restTemplate() {

    return new RestTemplate();

  }

 

  public static void main(String[] args) {

    SpringApplication.run(ConsumerRibbonApplication.class, args);

  }

}

使用:

public class MovieController {

  @Autowired

  private RestTemplate restTemplate;

  @Autowired

  private LoadBalancerClient loadBalancerClient;

 

  @GetMapping("/movie/{id}")

  public User findById(@PathVariable Long id) {

   //使用spring.application.name  及使用Vip virtual ip

    return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);

  }

 

 

 

 

2.7 Robbon 的其他均衡方式,与自定义

(暂时先不管)

2.8 Feign

依赖:

  <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-feign</artifactId>

  </dependency>

使用:1.在主类上加上@EnableFeignClients

@SpringBootApplication

@EnableDiscoveryClient

@EnableFeignClients

public class FeignApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(FeignApplication.class, args);

    }

 

}

 

2. 定义服务接口类

使用@FeignClient("User-service-0")注解来绑定该接口对应biz-service-0服务

提示:1.必须使用@RequestMapping  不支持:@GgetMapping ,@PostMapping 

       2. rest 路径参数名字,必须指定,如:/user/{id}    public User getuserinfo(@Pathvaluele(“id”) String id); 

 

@FeignClient("User-service-0")  //参数为对应的服务 server.application.name

public interface UserClient { 

    @RequestMapping(method = RequestMethod.GET, value ="/getuser")

    public User getuserinfo();     

    @RequestMapping(method = RequestMethod.GET, value = "/getuser")

    public String getuserinfostr();     

    @RequestMapping(method = RequestMethod.GET, value = "/info")

    public  String  info();

 }

3.调用接口:

在web层中调用上面定义的UserController,具体如下

@RestController

public class UserController {

 

    @Autowired

    UserClient userClient;

 

    @RequestMapping(value = "/getuserinfo", method = RequestMethod.GET)

    public User getuserinfo() {

        return userClient.getuserinfo();

    }

     

}

 

2.9 Feign的自定义配置https://blog.csdn.net/shunhua19881987/article/details/75491971

 

(1)自定义配置:

如果Eureka添加了安全验证,则需要配置上面的用户名、密码.

(2)在feignClient类中修改@FeignClient注解,在注解中添加新定义的Feign配置configuration的值:

注意:服务提供者的接口参数必须写在请求路径中,否则请求无效

不使用自定义的feignClint配置

(4)Feign日志打印配置

在configuration文件中添加feign日志配置:

在application配置文件中添加feign日志配置:

logging:

  level:

    com.itmuch.cloud.feign.UserFeignClient: DEBUG  //需要学全类名

(5)FeignClient第一次请求报TimeOut问题解决方案:

参考1

延长hystix的连接超时时间,默认时间是1

在application配置文件中添加如下配置:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:5000

禁用hystix的超时时间

在application配置文件中添加如下配置:

hystrix.command.default.execution.timeout.enabled: false

禁用hystix

在application配置文件添加如下配置信息:

feign.hystrix.enabled: false

参考网址:

超时的issue

        https://github.com/spring-cloud/spring-cloud-netflix/issues/768

超时的解决方案:

        https://stackoverflow.com/questions/27375557/hystrix-command-fails-with-timed-out-and-no-fallback-available

 

 

或者参考2(application.yml

 

# 解决第一次请求报超时异常的方案:

# hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

# 或者:

# hystrix.command.default.execution.timeout.enabled: false

# 或者:

feign.hystrix.enabled: false ## 索性禁用feign的hystrix

 

# 超时的issue:https://github.com/spring-cloud/spring-cloud-netflix/issues/768

# 超时的解决方案: http://stackoverflow.com/questions/27375557/hystrix-command-fails-with-timed-out-and-no-fallback-available

# hystrix配置: https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.thread.timeoutInMilliseconds

 

 

 

 

 

 

 

3.0 Hystrix (断路器)

依赖:

<dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-hystrix</artifactId>

        </dependency>

 

 

 

 

使用:在主类上加: @EnableCircuitBreaker

 

 

@SpringBootApplication

@EnableEurekaClient

@EnableCircuitBreaker

public class ConsumerMovieRibbonApplication {

 

  @Bean

  @LoadBalanced

  public RestTemplate restTemplate() {

    return new RestTemplate();

  }

  public static void main(String[] args) {

    SpringApplication.run(ConsumerMovieRibbonApplication.class, args);

  }

}

 

 

 

 

 

 

简单使用:

@RestController

public class MovieController {

  @Autowired

  private RestTemplate restTemplate;

 

  @GetMapping("/movie/{id}")

  @HystrixCommand(fallbackMethod = "findByIdFallback")   //指定(备胎)方法名

  public User findById(@PathVariable Long id) {

    return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);

  }

/** 如果上面方法短路,则会默认是用下面这个方法,返回固定值(备胎)*/

public User findByIdFallback(Long id) {

    User user = new User();

    user.setId(0L);

    return user;

  }

}

 

 

 

增强:参考:https://blog.csdn.net/qq_24504315/article/details/79120450

提示:配置了,commandProperties 后, @HystrixCommand HystrixCommand作用的方法是一个线程,否则@HystrixCommand 是一个隔离的线程

@RestController

@SessionScope   //正常情况不配置,如果运行时报找不到上下文时,就配置

public class OrderController {

          @Autowired

           private RestTemplate restTemplate;

           /**

            * SEMAPHORE 信号量隔离只是限制了总的并发数,服务使用主线程进行同步调用,即没有线程池。因此,如果只是想限制某个服务的总并发调用量或者调用的服务不涉及远程调用的话,可以使用轻量级的信号量来实现。

            * @param id

            * @return

            */

@GetMapping("/order/{id}")  @HystrixCommand(fallbackMethod="findByIdFallback",commandProperties={@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")})//信号量隔离

           public User findById(@PathVariable Long id) {

             // http://localhost:7900/user/

             // VIP virtual IP(http://localhost:7900/user/表示虚拟ip)

             // HAProxy Heartbeat

             return this.restTemplate.getForObject("http://spring-cloud-user/user/" + id, User.class);//直接写服务提供者的spring.application.name,这样方便于动态IP

           }

                     /**

            * 若是出现调用findById方法时出现错误或超时时,则调用此方法

            * @param id

            * @return

            */

           public User findByIdFallback(Long id){

                     User user = new User();

                     user.setId(0L);

                     return user;

           }

}

 

 

 

Feign支持hystrix

在接口@FeignClient中指定fallback

@FeignClient(name = "microservice-provider-user", fallback = HystrixClientFallback.class)

public interface UserFeignClient {

  @RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)

  public User findById(@PathVariable("id") Long id);

}

HystrixClientFallback.class:

@Component

public class HystrixClientFallback implements UserFeignClient {

@Override

  public User findById(Long id) {

    User user = new User();

    user.setId(0L);

    return user;

 

 

 

原文地址:https://www.cnblogs.com/lshan/p/9658305.html