springcloud


title: spring cloud
date: 2020-12-01 16:57:13
tags:

概念

  1. springcloud是一套完备的构建微服务系统的集合开发包,整合了市面上各种主流技术,并且使用了springboot的风格进行封装。
  2. 组件构成
  • 服务治理发现:服务发现是服务节点向服务治理中心发送消息,服务治理就是服务治理中心对单个服务节点进行治理。主要技术是Netflix Eureka
  • 配置中心:
  • 消息总线:
  • 客户端负载均衡:一个微服务有多个节点提供服务,当有大量请求发送时,就要依靠负载均衡来向服务消费者提供可用节点,同样,当节点故障时,可以提供新的可用节点,主要技术时ribbon,restTemplate。
  • 短路器:当出现网络延迟或者故障时,用户不停发送大量请求导致挤压,短路器就会发挥作用,常见的做法就是断路,降级,线程和信号隔离,请求缓存或者合并。主要技术是Netflix Hystrix
  • 数据监控:
  • 声明服务调用:使用restTemplate进行服务调用会比较繁琐,使用声明服务调用可以向使用本地java接口一样调用服务接口,简化开发流程,主要技术是feign
  • API网关:主要将用户请求的地址映射为真实服务器的地址,比如用户请求localhost/user/1,实际上由两个服务器8001和8002都可以提供这个服务,网关就可以依据不同情况,分配到不同的服务节点上去,另一个作用是过滤请求,可以过滤一些非法的恶意的请求,主要技术是zuul。也可以说是服务端的负载均衡

服务治理中心Eureka

  1. Eureka的作用是注册和发现各个springboot微服务,并对其进行监控和管理。服务发现分为客户端服务发现和服务端服务发现,客户端服务有eureka和zookeeper,服务端有consol+nginx
  2. 首先导入相关依赖
<!--这里只写cloud相关的依赖,其他的依赖你懂的-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR9</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>    
<!--这里需要使用依赖管理器来对eureka进行版本管理,注意cloud的版本需要和是springboot的版本进行兼容,详情见我下面写的踩坑注意-->
  1. 使用eureka只要在启动类上加注解@EnableEurekaServer
  2. 配置yml
spring:
  application:
    name: server

server:
  port: 7001

eureka:
  instance:
    hostname: localhost #Eureka注册的服务器名称
  client:
    register-with-eureka: false #是否注册给注册中心,这个就是注册中心,因此不注册注册中心
    fetch-registry: false #是否检索服务
    service-url:
      defaultZone: http://localhost:7001/eureka/ #治理客户端访问域  
#application.name是一个微服务的共同标识,如果另一个节点也将这个配置为server,那么Eureka就会认为这个节点也是这个server微服务的一个节点
#defaultZone用来代表服务中心的域,提供给别的微服务进行注册,

服务发现

  1. 完成服务治理中心之后,就要使用服务发现将服务节点注册到服务治理中心去。服务发现要在当前服务节点(即客户端将自己注册到服务治理中心去)。
  2. 首先还是引入相关的依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR9</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement> 

引入依赖之后,在旧版的cloud中要在启动类上加@EnableDiscoveryClient,但是在新版中只要引入clien依赖就可以注册,
3. 表明要注册之后,就要在配置文件中具体配置要注册到哪个服务治理中心。

server: #服务器端口
  port: 9001

spring:
  application: #spring应用名
    name: product
eureka:
  client:
    service-url: # 治理客户端服务域
      default-zone: http://localhost:7000/eureka/

两个服务治理中新相互注册

  1. 服务治理中心也可以看作是一个服务节点,为保证高可用和高并发,也要注册多个节点
  2. 不需要建立新的工程,只需修改yml配置文件就可以
#只需要修改两个属性,一个是port,另一个是default-zone,将两个相互注册就是7001端口的服务注册到defaul-zone为7002的服务治理中心,在将端口修改为7002,注册到default-zone为7001的服务治理中心。

服务之间通信(ribbon/feign)

  1. 服务之间的通信基于restAPI,可以使用之前的restTemplate进行通信,这里先简单介绍一下,详情可以看这里

restTemplate

  1. 对GET请求的封装,有两个放过getForObject和getForEntity,两者的区别就是Object返回的仅仅是相应消息,而entity还封装了一些响应头,响应时间等消息。
//有三种重载方法,
getForObject(String url, Class<T> responseType, Map<String,?> uriVariables)
getForObject(String url, Class<T> responseType, Object... uriVariables)
getForObject(URI url, Class<T> responseType)
//其中参数的含义,response Type是返回的数据类型,用T.class,uriVariable是uri中的变量值,可以直接传入,也可以使用map传入,使用map传入时uri中的占位符就是map的key,直接传入时就随便写个占位符就可以。
//ex getForObject("http://localhost:8000/user/{1}",user.class,id)
//Map map = new Map("id","fada");
//getForObject("http://localhost:8000/user/{id}",user.class,map);
//当uri中有许多参数需要传入的时候,就可以使用map将这些全部存储,提高可读性。
  1. 对post请求的封装
//也是三种方法
postForEntity(String url,Object request)
//剩下两种和上面的一样
postForEntity...返回的是entity类型
postForLocation...返回的是uri,即新资源的位置

//另外一种常用的就是通过json来传递对象
HttpHeaders headers = new HttpHeaders();//新建一个请求头
heders.setContentType(MediaType.APPLICATION_JSON_UTF8);//设置请求体的类型
HttpEntity<UserVo> request = new HttpEntity<>(new userVo(),headers);//将数据封装到请求实体中。
RestTemplate template = new RestTemplate();
template.postForObject("....",requset,userVo.class);
  1. delete等其他内容较为简单且不常用,因此不在此赘述。

ribbon客户端负载均衡

  1. 首先我们想要使用服务就要先找到服务,这里用到DiscoveryClient,发现客户端,可以通过服务ID来发现服务节点。
private DiscoveryClient discoveryClient = null;
ServericeInstance instance = dicoveryClient.getInstances("USER");//这个方法会返回一个list,list中封装的是UESR服务的所有节点。
instance.getServiceId();//获取服务id
instance.getHost();//获取服务器名称
instance.getPort();//获取端口号
其中USER是服务id,实在yml中通过application.name属性来确定的
  1. 添加ribbon依赖
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-srarter-netflix-ribbon</artifactId>
</dependency>
  1. 要使用restTemplate,就要将其放入IOC容器中.可以在启动类中用@Bean将其注入,或者在配置类中注入.注意在restTemplate上加@LoadBalanced注解,就可以实现客户端负载均衡

自定义ribbon

Feign声明式调用

  1. 适用feign,需要引入maven依赖
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 在启动文件上加@EnableFeignClients,注意前面几个启动类注解,
@EnableDiscoveryClients //允许服务发现,用于客户端将自己注册到服务治理中心,新版已经不需要加注解,只要引入依赖且在配置文件中指定defaultZone就可以
@EnableEurekaServer//表明将当前工程作为服务治理中心。
  1. 可以看出,feign适用大量的springMVC的注解,降低学习成本,上手简单
@PostMapping("/feignTest")
public Map<String,Object> addUser(@RequestBody UserPo user);
postMapping表明是post方法,map是返回数据类型,user是参数
//feign 实质上就是对RestTemplate的封装,
比如上面的就是PostForObject("http://localhost:8080/feignTest",Map<String,Object>.class,userPo);
  1. feign是声明式编程,就是只写一个接口,和dao工厂差不多,适用代理模式。

断路器

  1. 当一个微服务产生故障时,如果另一个微服务任然在大量调用这个发生故障的微服务,那么这个完好的微服务也会故障,接下来就是下一个,向网似的一个个传递下去,最终使得整个微服务系统瘫痪。
  2. cloud适用的断路器是Netflix的Hystrix,断路器处理的逻辑有很多种,常见的有降级,限流,缓存等,这里先介绍降级,所谓降级就是当超时或发生故障之后,就会用自己所配置的方法去执行,有点像spring里的异常通知。
  3. 还是首先引入Hystrxi的依赖
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  1. 启动和前面的一样,在启动类上加@EnableCircuitBreaker
  2. 在要进行断路的方法上面加@HystrixCommand注解,指定发生错误时调用的方法
@Hystrix(fallBackMethod = "error")
public void test(){

}

public void error(){
  sout("熔断");
}
  1. 另外也可以设置超时时间,通过注解的属性设置
@Hstrix(fallBackMethod="error",commandProperties={@HystrixProperty
  (name="execution.isolation.thread.timeoutInMiliseconds",
  value="3000")
})

Hystrix的监控

  1. 先等会,看了springboot的监控再说

zuul网关

  1. 网关有三大作用
  • 域名映射,将SerivceID转化为真实的服务器地址,保护服务器
  • 进行服务器端负载均衡
  • 使用过滤器,过滤无效请求
  1. 引入相关依赖
<!--cloud客户端,即服务提供者-->
<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
  1. 启用也和前面的一样,在启动类上加@EnableZuulProxy
  2. 开启网关之后,我们就不再直接向微服务的地址发送请求了,而是向网关发送请求,网关会自动转发请求,比如之前的请求地址是http://localhost:8081/user/findusr,开启网关之后就是http://localhost/user/finduser,不在需要知道具体的端口号,而是直接向网关请求就可以。
  3. 网关也可以配置请求路径和真实路径,感觉这点和servlet差不多。
#有两种映射方式,一种是传统的网关配置方式,另一种是面向服务的配置

zuul: 
  routes:
    user-service: 
      path: /u/** #这就是请求路径
      url: http://localhost:8001/ #转发到这个端口上的服务
    product-service: 
      path: /p/**
      serviceId: product #这是面向服务类型

#上面两种的区别就是传统方式是将请求转发到具体的端口上,但是这样就必须知道这个微服务的所哟端口,而面向服务的就是,只写服务id,这样在注册到服务治理中心之后就可以获得服务id所对应的具体端口号。

过滤器

  1. 过滤器的机制也是类似于spring中的通知,zuul中提供了过滤器的抽象类,想要使用自定义的过滤器就要继承抽象类就可以。
  2. 抽象类继承IZuulFilter接口,且自定义了两个抽象方法,当我们的自定义过滤器继承了抽象类之后,总共实现4个方法,分别是shouleFilter,run,filterType,filterOeder
    其中作用分别是shouldFilter表示是否启用过滤器,run是核心功能,即使过滤器的业务逻辑,filterType有4种类型,包括pre(请求执行之前filter),route(处理请求,进行filter),post(请求处理完成后执行的filter),error(出现错误时执行的filter),filterOrder表明过滤器执行的优先顺序级别,数字越小执行级别越优先。

springcloudappcation注解

  1. 由于上面介绍的每个组件都要在启动类上加注解,于是就把这些组件集成在了springcloudapplicaiton注解中,但是cloudapp注解没有配置扫描包这个选项,因此需要componentScan注解来配置扫描包,并且也没有feign的@EnableFeignClients这个注解,要加上

踩坑

  1. spring的属性eureka.client.serviceUrl.defaultZone=http://localhost:7001/eureka/,在yml中的写法变为
eureka: 
    client: 
        service-url: 
            defaultZone: http://localhost:7001/eureka/
#serviceUrl在yml中要用连接符连接,但是会发现没有defaultZone的智能提示,这是因为service-url是map结构,defaultZone是map的键,后面的连接是值。
  1. 注意springcloud的版本要和springboot的版本进行匹配,具体的匹配版本可以看官网,我使用的是springboot2.4版本,这个版本的创建配置类bean的方式发生了改变,使用2.3版本

  2. @EnableDiscoveryClient和@EnableEurekaClient的区别,详细看博客,简单点说就是@EnableDiscoveryClient适用于任何的服务发现组件(zookeeper和其他的等),如果只用了eureka的话,还是推荐使用@EnableDiscoveryClient。

  3. 但是在新版的cloud中,不需要在在启动类上写@EnableDiscoveryClient注解,而是引入依赖并且配置一下就可以,具体的看博客

  4. eureka使用的时候会依赖starter-web包中的内容,如果没有引入web依赖的内容就会报错,详情看博客

  5. ribbon是客户端的负载均衡,即应该由客户端(即服务提供者来引入pom文件).

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值