SpringCloud

SpringCloud核心

基于HTTP协议,这是它和Dubbo的最本质区别。Dubbo的核心是基于RPC。

Eureka:注册中心

Ribbon:客户端负载均衡

Feign:远程接口的声明式调用

Hystrix:服务的熔断、降级、监控

Zuul:网关

一、环境搭建 

java 12 + SpringBoot 2.1.6.RELEASE + SpringCloud Greenwich.SR2

 1. SpringCloud必须与SpringBoot配合使用。创建父工程,集中管理依赖,不必每个项目都重新导依赖。

 

<dependencies>
    <!-- 导入 SpringCloud 需要使用的依赖信息 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Greenwich.SR2</version>
        <type>pom</type> <!-- import 依赖范围表示将 spring-cloud-dependencies 包中的依赖信息导入 -->
        <scope>import</scope>
    </dependency>
    <!-- 导入 SpringBoot 需要使用的依赖信息 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.1.6.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
</dependencies>

2. 创建provider项目(导入SpringBoot Web、配置端口号)

handler方法

@RestController
public class EmployeeHandler {

    @RequestMapping("/provider/get/employee/remote")
    public Employee getEmployeeRemote() {
        return new Employee(555, "tom555", 555.55);
    }
}

3. 创建consumer项目(导入SpringBoot Web、配置端口号)

编写配置类,注入RestTemplate类。

@Configuration
public class SpringCloudConfig {

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

编写handler,远程调用方法。

@RestController
public class HumanResourceHandler {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/get/employee")
    public Employee getEmployeeRemote(){
        // 1.远程调用主机地址
        String host="http://localhost:1000";
        // 2.远程调用具体地址
        String url="/provider/get/employee/remote";
        // 3.调用远程方法
        return restTemplate.getForObject(host+url,Employee.class);
    }

}

4. 启动 provider 和 consumer 项目,测试。

5. 创建Eureka项目

导入Eureka依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

在SpringBoot启动类上,开启EurekaServer注解。

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class);
    }
}

配置application.yml

server:
  port: 5000

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false   #自己就是注册中心,不需要注册自己
    fetch-registry: false   #自己就是注册中心,不需要“从注册中心取回信息”
    service-url:   #客户端访问Eureka的地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

6. 启动Eureka项目,出现注册界面,配置成功。

如果出现启动错误 Type javax.xml.bind.JAXBContext not present

错误原因:java9+版本以后,JAXB默认没有加载

手动导入依赖。

<dependency>
   <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>

7. 将微服务注册到Eureka

1)provider服务

在需要注册的客户端项目添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置application.yml

spring:
  application:
    name: crowdfunding-provider    #指定当前项目作为微服务的名称

eureka:
  client:
    service-url:    #配置当前微服务作为Eureka客户端访问Eureka服务端时使用的地址
      defaultZone: http://localhost:5000/eureka/

启动项目,访问Eureka注册页面

2)consumer服务

在需要订阅的客户端项目添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置application.yml

spring:
  application:
    name: crowdfunding-consumer

eureka:
  client:
    service-url:
      defaultZone: http://localhost:5000/eureka/

在配置类RestTemplate上添加负载均衡注解 @LoadBalanced ,将访问地址用微服务名称代替。String host = "http://springcloud-provider";

启动项目,可以看到两个服务均已被注册,并且访问成功。

8. 以集群的方式启动provider服务

修改handler方法,方便查看

@RequestMapping("/provider/get/employee/remote")
public Employee getEmployeeRemote(HttpServletRequest request) {
    int port = request.getServerPort();

    return new Employee(555, "tom555 "+port, 555.55);
}

修改端口号,分别以1000,2000,3000启动三个服务,注意:服务名必须一样

9. 使用 Feign 实现远程方法声明式调用

common工程加入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

编写接口方法

// 当前接口和一个provider对应,value指定调用微服务的名称
@FeignClient(value = "crowdfunding-provider")
public interface EmployeeRemoteService {

    @RequestMapping("/provider/get/employee/remote")
    public Employee getEmployeeRemote();
}

Feign-consumer 工程,导入依赖

<dependency>
    <groupId>com.spring.cloud</groupId>
    <artifactId>springcloud-common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

启动类上开启 @EnableFeignClients 注解,配置application.yml,内容同consumer,端口号改为7000,编写handler方法。

6000端口号被系统占用

@RestController
public class HumanResourceHandler {

    //自动导入,直接使用
    @Autowired
    private EmployeeRemoteService employeeRemoteService;

    @RequestMapping("/feign/consumer/get/employee")
    public Employee getEmployeeRemote(){
        return employeeRemoteService.getEmployeeRemote();
    }

}

对于需要参数传递的方法,最好加上 @RequestParam@RequestBody 等参数注解,特别是传递对象参数时。

二、Hystrix和Zuul

1. Hystrix

Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix 能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

1)熔断 ——服务端

provider项目导入Hystrix依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

在启动类上开启断路器功能  @EnableCircuitBreaker ,编写handler方法

// 指定断路备用方法
@HystrixCommand(fallbackMethod = "getEmployeeBreakBackUp")
@RequestMapping("/provider/get/employee/circuit")
public ResultEntity getEmployeeBreak(){   //  ResultEntity自定义返回类
    int i=10/0;    // 抛出异常
    return ResultEntity.successWithData(new Employee(666,"tom666",66.00));
}

// 备用方法
public ResultEntity getEmployeeBreakBackUp(){
    return ResultEntity.failed("运行错误!");
}

2)降级——客户端

common工程导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

实现 FallbackFactory 接口,在 create 方法中返回自定义的备用方案

@FeignClient 中指定备用方案

@FeignClient(value="springcloud-provider", fallbackFactory=MyFallBackFactory.class)

在application.yml中加入

feign:
  hystrix:
    enabled: true

3)监控

在需要被监控的项目provider加入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

配置application.yml

management.endpoints.web.exposure.include: hystrix.stream

创建监控工程,导入依赖,在启动类上添加 @EnableHystrixDashboard 注解,启用 Hystrix 仪表盘功能,配置端口号和服务名

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

访问hystrix监控页面(http://localhost:8000/hystrix),输入监控工程地址(http://localhost:1000/actuator/hystrix.stream

2. Zuul

创建springcloud-zuul工程,导入依赖,在主启动类上添加 @EnableZuulProxy 注解,开启Zuul代理功能

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

配置application.yml

server:
  port: 9000

spring:
  application:
    name: springcloud-zuul

eureka:
  client:
    service-url:
      defaultZone: http://localhost:5000/eureka/

zuul:
  routes:    #自定义路由规则的名称,以map形式存放
    employee:    #key
      serviceId: springcloud-feign-consumer   #微服务名称
      path: /zuul-emp/**    #代替微服务路径
  #ignored-services: '*'    #忽略自定义的服务器名称,让用户不能通过服务器名称访问,数据类型为数组,'*'表示忽略所有
  #prefix: /cloud    #给访问路径添加统一前缀

通过统一网关和别名访问

ZullFilter

自定义过滤器类,继承 ZuulFilter

@Component
public class MyZuulFilter extends ZuulFilter {

    @Override
    public String filterType() {
        // 返回当前过滤器类型
        // 可选类型包括:pre、route、post、static
        String type="pre";
        return type;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        // 获取request对象
        RequestContext context=RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        // 获取请求路径
        String path = request.getServletPath();
        System.out.println(path);

        // true:表示应该过滤,下面继续执行 run()方法
        // false:表示不过滤,直接放行
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        System.out.println("执行run方法");
        return null;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值