Spring Cloud

spring cloud

gitee:链接: sc-demo.

什么是微服务?

来自百度百科
https://baike.baidu.com/item/微服务/18758759?fr=aladdin

维基上对其定义为:
一种软件开发技术- 面向服务的体系结构(SOA)架构样式的一种变体,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够独立地部署到生产环境、类生产环境等。另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据上下文,选择合适的语言、工具对其进行构建。

结构

springcloud、cloud Alibaba

spring cloud 结构
其中Eureka、Hystrix、Config、Bus现已不在更新、阿里基于springcloud整合其中组件
推出nacos代替Eureka、Config、Bus
Sentienl代替Hystrix

客户端和服务端

 服务端   ---  eureka、nacos 	客户端  client --- 调用服务中心(消费者、提供者)
eureka(CAP — AP )
由Netflix开源,并被Pivatal集成到SpringCloud体系中,它是基于 RestfulAPI 风格开发的服务注册与发现组件。

CAP定理又称CAP原则,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),最多只能同时三个特性中的两个,三者不可兼得。

P:分区容错性:分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务(一定的要满足的)

C:数据一致性:all nodes see the same data at the same time

A:高可用:Reads and writes always succeed
简单使用
注意:Jdk9之后,在父工程的pom文件中手动引入jaxb的jar,因为Jdk9之后默认没有加载该模块,Eureka Server使用到,所以需要手动导入,否则Eureka Server服务无法启动

导入maven依赖

父工程
spring boot 版本 2.2.5.RELEASE

<spring.cloud-version>Hoxton.SR8</spring.cloud-version>

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-dependencies</artifactId>
		<version>${spring.cloud-version}</version>
		<type>pom</type>
		<scope>import</scope>
	</dependency>

Eureka模块

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

创建启动类 EurekaApplication 加上@EnableEurekaServer开启服务

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

修改 application.yml文件

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:7001/eureka/
      #      是否在服务中心注册(不注册)
    register-with-eureka: false 
    #    就是服务需要从Eureka Server获取服务信息,默认为true,设置为false
    fetch-registry: false
  instance:
    hostname: localhost
spring:
  application:
   # 应用名称,会在Eureka中作为服务的id标识(serviceId)
    name: sc-eureka
server:
  port: 7001

访问localhost:7001 点击
在这里插入图片描述

集群

创建eureka2模块,重复上面的操作

eureka2的application.yml文件
eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/
    register-with-eureka: false
    fetch-registry: false
  instance:
    hostname: eureka2
spring:
  application:
    name: sc-eureka1
server:
  port: 7002

修改 eureka模块的application.yml文件
eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/
    register-with-eureka: false
#    #就是服务需要从Eureka Server获取服务信息,默认为true,置为false
    fetch-registry: false
  instance:
    hostname: eureka1
#      非集群
#    hostname: localhost
spring:
  application:
    name: sc-eureka
server:
  port: 7001

访问localhost:7001 点击
在这里插入图片描述

消费者、提供者

在这里插入图片描述

provider—提供者
在eureka服务中心注册,供消费者使用
简单使用
创建 provider模块,导入maven依赖
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
创建启动类ProviderApplication
@SpringBootApplication
@EnableEurekaClient
public class ProviderApplication{
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

创建controller
@RestController
@RequestMapping("/provider")
public class ProviderController {

    @Value("${server.port}")
    private String port;
    
    @GetMapping("/port")
    public String getPort() {
        return "来自provider的端口号 : "+port;
    }
}

访问localhost:7001 点击
provider

consumer—消费者
简单使用
和上面的provider一样,创建完模块,其yml文件
eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/
    register-with-eureka: false
  instance:
    prefer-ip-address: true
spring:
  application:
    name: consumer
server:
  port: 9001

创建config	
@SpringBootConfiguration
public class RestTemplateConfig {
//    @Bean
//    public RestTemplate restTemplate(RestTemplate restTemplate){
//        return new RestTemplate();
//    }
//
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(RestTemplateBuilder builder){
        return builder.build();
    }
}

其controller

@RestController
@RequestMapping("/consumer")
public class ConsumerController {
    private final RestTemplate restTemplate;
    private final DiscoveryClient discoveryClient;

    public ConsumerController(DiscoveryClient discoveryClient, RestTemplate restTemplate) {
        this.discoveryClient = discoveryClient;
        this.restTemplate = restTemplate;
    }


    @GetMapping("/port")
    public String getPort() {
//        ServiceInstance consumer = discoveryClient.getInstances("PROVIDER").get(0);
//        System.out.println("provider = " + consumer.getUri());
//        String url= consumer.getUri() + "/provider/port/";
        return restTemplate.getForObject("http://provider/provider/port",String.class);
    }
}

访问 consumer/port: 点击
在这里插入图片描述

ribbon和openfeign

什么是 — ribbon

Ribbon是Netflix发布的负载均衡器。Eureka一般配合Ribbon进行使用,Ribbon利用从Eureka中读取到服务信息,在调用服务提供者提供的服务时,会根据一定的算法进行负载

负载均衡一般分为服务器端负载均衡和客户端负载均衡

所谓服务器端负载均衡,比如Nginx、F5这些,请求到达服务器之后由这些负载均衡器根据一定的算法将请求路由到目标服务器处理。

​ 所谓客户端负载均衡,比如我们要说的Ribbon,服务消费者客户端会有一个服务器地址列表,调用方在请求前通过一定的负载均衡算法选择一个服务器进行访问,负载均衡算法的执行是在请求客户端进行。

为什么

分摊压力
在这里插入图片描述

简单使用

在消费者模块中添加规则


public class MyselfRule {
    @Bean
    public IRule myRule(){
        //把默认的轮询策略改为随机策略。
        return new RandomRule();
    }
}

消费者ConsumerApplication添加注解
@RibbonClient(name = "provider",configuration = MyselfRule.class)

新建一个提供者,只改变端口,或者在idea,中将providerController
在这里插入图片描述
设置中选择
在这里插入图片描述
改动provider中的yml文件的端口

server:
  port: 8002

即可模拟多个模块

访问 consumer/port: 点击
请添加图片描述

什么是openfeign
远程调用组件

本质:封装了Http调用流程,更符合面向接口化的编程习惯,类似于Dubbo的服务调用

简单使用

新建consumer-openfeign模块或者在consumer中添加maven依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OpenFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignApplication.class,args);
    }
}

application.yml文件

server:
  port: 9001
eureka:
  client:
    # eureka服务端的路劲
    service-url:
      defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/
    # 如果不想将改服务注册进注册中心,一定要写成false
    register-with-eureka: false
spring:
  application:
    name: consumer-openfeign

#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  #指的是建立连接后从服务器读取到可用资源所用的时间
  ReadTimeout: 5000
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ConnectTimeout: 5000

#针对的被调用方微服务名称(serviceId),不加就是全局生效
#provider:
#  ribbon:
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule    #随机策略
接口
@FeignClient("provider") // 参数 serviceId
public interface ProviderService {
    @GetMapping("/provider/port")
    String getPort();

    @GetMapping("/provider/feign/timeout")
    String providerFeignTimeOut();
}

在provider模块的Controller中添加

    @GetMapping("/feign/timeout")
    public String providerFeignTimeOut() {
        try {
            // 休眠3秒
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return port;
    }
实现
@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    private final ProviderService providerService;

    public ConsumerController(ProviderService providerService) {
        this.providerService = providerService;
    }

    @GetMapping("/port")
    public String getPort() {
        return providerService.getPort();
    }

    @GetMapping("/feign/timeout")
    public String providerFeignTimeOut() {
        System.out.println("providerFeignTimeOut--------------->");
        return providerService.providerFeignTimeOut();
    }

}

Hystrix

什么是Hystrix
属于一种容错机制

[来自官网]Hystrix(豪猪),宣言“defend your application”是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。

为什么

当山坡积雪内部的内聚力抗拒不了它所受到的重力拉引时,便向下滑动,引起大量雪体崩塌,人们把这种自然现象称作雪崩。

​ 微服务中,一个请求可能需要多个微服务接口才能实现,会形成复杂的调用链路。

服务雪崩效应是一种因“服务提供者的不可用”(原因)导致“服务调用者不可用”(结果),并将不可用逐渐放大的现象。

简单使用
新建consumer-hystrix模块

较之前的consumer模块添加maven依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class ConsumerHystrixApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerHystrixApplication.class,args);
    }
}

application.yml文件
server:
  port: 9001
eureka:
  client:
    # eureka服务端的路劲
    service-url:
      defaultZone: http://localhost:7001/eureka/
    # 如果不想将改服务注册进注册中心,一定要写成false
    register-with-eureka: true
spring:
  application:
    name: consumer-hystrix

#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  #指的是建立连接后从服务器读取到可用资源所用的时间
  ReadTimeout: 5000
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ConnectTimeout: 5000


#针对的被调用方微服务名称(serviceId),不加就是全局生效
#provider:
#  ribbon:
feign:
  hystrix:
    enabled: true
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule    #随机策略

#设置最大请求时间为5秒
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000
熔断,降级
在provider上使用
启动类添加  @EnableHystrix

在controller层 添加方法,来模拟实现熔断,再进行降级

    public String providerHystrixTimeOutHandler(){
        return "当前服务器忙,请稍后再试 /(T o T)/~";
    }


    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
    })
    @GetMapping("/hystrix/timeout")
    public String providerFeignTimeOut() {
        int time=3;
//        int a=10/0;
        try {
            // 休眠3秒
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return  Thread.currentThread().getName()+"  --  out --  providerHystrixTimeOut  耗时  ==  " +time;
    }



在consumer-hystrix消费者模块中

添加降级创建ProviderHystrixServiceFactory 类

@Component
public class ProviderHystrixServiceFactory  implements FallbackFactory<ProviderService> {

    @Override
    public ProviderService create(Throwable throwable) {
        return new ProviderService() {
            String msg="系统异常";
            @Override
            public String getHystrixOK() {
                return msg;
            }

            @Override
            public String providerHystrixTimeOut() {
                return msg;
            }

            @Override
            public String providerOrder(Long id) {
                return msg;
            }
        };
    }
}

添加service接口

@FeignClient(value = "provider-hystrix",fallbackFactory = ProviderHystrixServiceFactory.class) // 参数 serviceId
//@FeignClient(value = "provider-hystrix",fallback = ProviderHystrixService.class) // 参数 serviceId
public interface ProviderService {
    @GetMapping("/provider/port")
    String getHystrixOK();

    @GetMapping("/provider/hystrix/timeout")
    String providerHystrixTimeOut();
}

也可以这样

取消上面操作,保证纯洁性
在controller中添加

    @HystrixCommand(fallbackMethod ="global_FallbackMethod",commandProperties = {
            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "10000"),
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "30000"),
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50")
    })
    @GetMapping("hystrix/order/{id}")
    public String providerOrder(@PathVariable Long id){
        return providerService.providerOrder(id);
    }


    public String global_FallbackMethod(Long id){
        return "Global全局降级";
    }

了解更多参数可以访问: link.

gateway

什么是gateway 网关

Spring Cloud GateWay不仅提供统一的路由方式(反向代理)并且基于 Filter(定义过滤器对请求过滤,完成一些功能) 链的方式提供了网关基本的功能,例如:鉴权、流量控制、熔断、路径重写、日志监控等。

网关在架构中的位置
在这里插入图片描述

工作流程

在这里插入图片描述
Spring 官方介绍:

​ 客户端向Spring Cloud GateWay发出请求,然后在GateWay Handler Mapping中找到与请求相匹配的路由,将其发送到GateWay Web Handler;Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或者之后(post)执行业务逻辑。

​ Filter在“pre”类型过滤器中可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改、日志的输出、流量监控等。

简单使用
注意不能有web依赖,有冲突
    <dependencies>
        <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-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
    </dependencies>
启动类
@SpringBootApplication
@EnableDiscoveryClient
public class GateWayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GateWayApplication.class,args);
    }
}

application.yml文件
server:
  port: 9527
eureka:
  client:
    serviceUrl: # eureka server的路径
      defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/
    fetch-registry: true
    register-with-eureka: true
  instance:
    prefer-ip-address: true
#    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
spring:
  application:
    name: gateway
  #网关的配置
  cloud:
    gateway:
      routes: #配置路由
        - id: provider
#          uri: http://localhost:8001
#          uri: http://provider
          uri: lb://provider
          predicates: #当断言成功后,交给某一个微服务处理时使用的是转发
            - Before=2023-01-20T17:42:47.789-07:00[America/Denver]
#        - id: provider
#          uri: http://127.0.0.1:8001
#          predicates:
#            - Path=/product/**
#          filters:
#            # http://127.0.0.1:9300/product/service/port  -->  /service/port --> 商品微服务
#            - StripPrefix=1  #去掉uri中的第一部分,所以就要求我们通过网关访问的时候,把uri的第一部分设置为product,从uri的第二部分开始才是真正的uri
黑名单
@Component
public class BlackListFilter implements GlobalFilter, Ordered {

    private static List<String > blackList=new ArrayList<>();

    static {
        blackList.add("0:0:0:0:0:0:0:1");  // 模拟本机地址
        blackList.add("127.0.0.1");
    }

    /**
     * 过滤器核心方法
     * @param exchange 封装了request和response对象的上下文
     * @param chain 网关过滤器链(包含全局过滤器和单路由过滤器)
     * @return
     */
//    @Order(1)
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String clientIp = request.getRemoteAddress().getHostString();

        response.getHeaders().add("Content-Type","application/json;charset=UTF-8");

        if(blackList.contains(clientIp)){
            //todo
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            String data="Request be denied 请求拒绝";
            System.out.println("data = " + data);
            DataBuffer wrap = response.bufferFactory().wrap(data.getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(wrap));
        }
        return chain.filter(exchange);
    }

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

config和bus

spring config
单体应用架构

配置信息的管理、维护并不会显得特别麻烦,手动操作就可以,因为就一个工程

微服务架构

根据各个微服务的负载情况,动态调整数据源连接池大小,我们希望配置内容发生变化的时候,微服务可以自动更新

应用场景

对配置文件进行 集中式管理

  • ​集中配置管理,一个微服务架构中可能有成百上千个微服务,所以集中配置管理是很重要的(一次修改、到处生效)
  • 不同环境不同配置,比如数据源配置在不同环境(开发dev,测试test,生产prod)中是不同的
  • 运行期间可动态调整。例如,可根据各个微服务的负载情况,动态调整数据源连接池大小等配置修改后可自动更新
  • 如配置内容发生变化,微服务可以自动更新配置
spring cloud config 简介

在这里插入图片描述

  • Server 端:提供配置文件的存储、以接口的形式将配置文件的内容提供出去,通过使用@EnableConfigServer注解在 Spring boot 应用中非常简单的嵌入
  • Client 端:通过接口获取配置数据并初始化自己的应用
Config分布式配置应用
Config Server是集中式的配置服务,用于集中管理应用程序各个环境下的配置,使用gitee(git)管理

eg:对“静态化微服务或者商品微服务”的application.yml进行管理(区分开发环境(dev)、测试环境(test)、生产环境(prod))

创建一个新的仓库,在新仓库里上传application-dev.yml ( eg: {}-{}.yml )

自动更新简单使用

导入依赖

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

创建bootstrap.yml

server:
  port: 9500 # 后期该微服务多实例,端口从9100递增(10个以内)

Spring:
  application:
    name: config-client
  rabbitmq:
    host: 39.106.35.116
    port: 5672
    username: guest
    password: guest
#  datasource:
#    driver-class-name: com.mysql.jdbc.Driver
#    url: jdbc:mysql://localhost:3306/demodb?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
#    username: root
#    password: root
  cloud:
    config:
      #config客户端配置,和ConfigServer通信,并告知ConfigServer希望获取的配置信息在哪个文件中
      name: config  #前缀 eg:application-dev (application是前缀,dev是后缀)
      profile: test   #后缀名称
      label: master  #分支名称
      uri: http://localhost:9400   #ConfigServer配置中心地址

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:7001/eureka/
    register-with-eureka: false
  instance:
    prefer-ip-address: true

#management:
#  endpoint:
#    refresh:
#      enabled: true
management:
  endpoints:
    web:
      exposure:
        include: refresh

创建配置的服务端config-server

其application.yml

eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/
    register-with-eureka: true
  instance:
    prefer-ip-address: true
spring:
  application:
    name: config-server
#    下载rabbitmq,这里在linux中docker下载,官网下载 rabbitmq.com
  rabbitmq:
    host: 39.106.35.116
    port: 5672
    username: guest
    password: guest
  cloud:
    config:
      server:
        git:
          uri: ###地址
          username: ###用户名
          password: ###密码
#          search-paths:
#            - config
      label: master
server:
  port: 9400

management:
  endpoints:
    web:
      exposure:
        include: "*"

启动类

@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值