栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

22-07-20 西安 SpringCloud(01)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

22-07-20 西安 SpringCloud(01)

是的,你的行为实在不会给我什么好印象,你是个不折不扣的混蛋!米彩直言不讳到

“是吗... 可是你不知道,你眼中那个坏事做尽的混蛋,曾经心里也有过一座干净的城池!”

"我不太懂你在说些什么。"
“你不需要懂... ...因为今天这座城池已经从我的身边脱离,成为了一座我永远也触摸不到的天 空之城!”

我低头摸索着口袋,却已经没有一支烟供我燃烧掉惆怅,缝补我碎裂的灵魂。

                                                                                                        -------《我的26岁女房客》

微服务与分布式、集群

1.微服务理论

独立应用变成一套小服务,每一个都运行在自己的进程内(容器) 独立业务能力 独立部署 独立开发语言 独立的数据存储
应该有一个能管理这些服务的中心

2.分布式概念

分布式系统是若干独立计算机的集合(多台服务器),这些计算机对于用户来说就像单个相关系统

集群:集群指的是将几台服务器集中在一起,实现同一业务。
集群就是很多服务器跑同一个项目

分布式与集群
== 分布式中的每一个节点 ==,都可以做集群。而集群并不一定就是分布式的。


服务之间的交互可以用两种方式

  • RPC(Dubbo)

    • Socket包+自定义序列化
  • RestAPI (SpringCloud)

    • HTTP协议+JSON

RPC是什么

RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范,dubbo是其实现

网络传输要求二进制,要序列化,打包(socket包)


高并发
工具限制(本身性能):
Tomcat 默认配置的最大请求数是 150,也就是说同时支持 150 个并发。当某个应用拥有 250 个以上并发的时候,应考虑应用服务器的集群。

系统限制
Windows 每个进程中的线程数不允许超过 2000
Linux 每个进程中的线程数不允许超过 1000

高并发衡量指标

  1. 响应时间(RT) :请求做出响应的时间,即一个http请求返回所用的时间
  2. 吞吐量: 系统在单位时间内处理请求的数量
  3. QPS、 TPS:每秒查询(请求)数、每秒事务数
  4. Apache JMeter:  模拟高并发

高可用
服务集群部署,数据库双主机方式

主-备方式(Active-Standby方式)

主-备方式即指的是一台服务器处于某种业务的激活状态(即Active状态),另一台服务器处于该业务的备用状态(即Standby状态)。

双主机方式(Active-Active方式)

双主机方式即指两种不同业务分别在两台服务器上互为主备状态(即Active-Standby和Standby-Active状态)


版本选择

  • SpringBoot 2.3.6.RELEASE
  • SpringCloud   Hoxton.SR9
  • SpringCloud Alibaba  2.2.6.RELEASE

RestTemplate远程调用

创建工程啥的就直接省略了。因为要引入的依赖是在是多呀,大概做法是先创建一个父工程cloud-paraent,再在该父工程下创建其余的工程。

还要安装一些插件,比如lombok,mybatisX以及一些idea中settings中的配置都省略

 1、先保证cloud-consumer-order80 可以远程调用 cloud-provider-payment8001成功。

在消费端使用配置类配置bean对象RestTemplate

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

并在controller层注入使用RestTemplate,使用以下方法实现远程调用

RestTemplate提供了多种便捷访问远程Http服务的方法

  • restTemplate.getForObject()完成查询
  • restTemplate.postForObject()完成添加

远程调用方法需要的三个参数

   REST请求地址、请求参数、Http响应转换被转换成的对象类型。【其实看着都挺麻烦的,一会用OpenFeign替换】

@RestController
@Slf4j
public class OrderController {

    public static final String PAYMENT_URL =  "http://localhost:8001";

    @Resource
    private RestTemplate restTemplate;

    @PostMapping("/consumer/payment/create")
    public CommonResult   create(@RequestBody Payment payment){
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment, CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult getPayment(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

注意一个点,被远程调用的服务cloud-provider-payment8001的添加方法一定要使用@RequestBody,因为RESTAPI的风格就是http+json.


Eureka服务注册与发现(中心)

Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接

注册中心(存放服务地址相关信息(接口地址))

Eureka Server  提供服务注册服务

各个微服务节点通过配置启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息。

Eureka Client  通过注册中心进行访问

是一个Java客户端,用于简化Eureka Server的交互。

--------

单机Eureka的构建步骤

IDEA生成eurekaServer端服务注册中心,也就是工程: cloud-eureka-server7001

这个工程特殊的地在于

1、引入以下依赖


    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-server

2、同时在application.yml中做如下配置,一会浏览器访问    http://localhost:7001/

server:
  port: 7001 # eureka的服务端

eureka:
  instance:
    hostname: localhost  #注册中心所在的服务器地址

  client:
    register-with-eureka: false #因为我就是服务端,不需要注册到Eureka中
    fetchRegistry: false  #我就是服务端不需要从Eureka中获取信息
    service-url:
      defaultZone: http://localhost:7001/eureka    # 注册中心的访问地址

3、在主启动类上加注解 @EnableEurekaServer

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

此时,启动工程 cloud-eureka-server7001,在浏览器端访问   http://localhost:7001/


在服务的提供者cloud-provider-payment8001和服务的消费者cloud-consumer-order80 中 

都引入以下依赖,它俩都是Eurake的客户端


    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-client

在配置文件application.yml中加入以下配置

提供者 cloud-provider-payment8001配置如下:

eureka:
  client:
    register-with-eureka: true  #8001支付微服务 是客户端需要向注册中心注册信息
    fetchRegistry: true #8001支付微服务 是客户端需要从注册中心获取信息
    service-url:
      defaultZone: http://localhost:7001/eureka

消费者 cloud-consumer-order80配置如下:

eureka:
  client:
    register-with-eureka: true
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

分别在主启动类加上注解:@EnableEurekaClient

提供者 cloud-provider-payment8001主启动类如下:

@SpringBootApplication
@MapperScan(basePackages = "com.atguigu.springcloud.dao")
@EnableEurekaClient
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class,args);
    }
}

消费者 cloud-consumer-order80主启动类如下:

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

依次启动工程 7001,8001,80

访问:http://localhost:7001/


Ribbon负载均衡服务调用

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

Ribbon目前也进入维护模式,未来替换方案是Spring Cloud LoadBalancer

LB负载均衡

将用户的请求平均分配到多个服务器上,从而达到系统的HA(高可用)。

Ribbon的本地负载均衡客户端  VS Nginx服务端负载均衡区别:

  • Nginx是服务器负载均衡,客户端所有请求都会交给Nginx(http的服务器),然后由nginx实现转发请求到tomcat。即负载均衡是由服务器端完成的。
  • Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用。

集中式LB(如Nginx)

  • 即在服务的消费方和提供方之间使用独立的LB设施,由该设施负责把访问请求通过某种策略转发至服务的提供方;

进程内LB(如Ribbon)

  • 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。

Ribbon=负载均衡+RestTemplate调用

Ribbon在工作时分成两步:

第一步,先选择EurekaServer,它优先选择在同一个区域内负载较少的server。

第二步,再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略。比如:轮询、随机和根据响应时间加权。

总结:Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

Eureka客户端自带Ribbon的依赖,所以就没必要再引入下面的ribbon依赖


org.springframework.cloud
spring-cloud-starter-netflix-ribbon

----------
Ribbon核心组件IRule 

IRule 接口及实现类如下:

IRule:根据特定算法从服务列表中选取一个要访问的服务

  1. com.netflix.loadbalancer.RoundRobinRule 轮询,默认策略。
  2. com.netflix.loadbalancer.RandomRule  随机
  3. com.netflix.loadbalancer.RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
  4. WeightedResponseTimeRule  对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择(主动处理)
  5. BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
  6. AvailabilityFilteringRule 先过滤掉故障实例,再选择并发较小的实例
  7. ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器

如何配置负载均衡策略

新建一个配置类,要特别注意该配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化订制的目的了。

@SpringBootConfiguration
public class MySelfRule {
    @Bean
    public IRule myRule(){
        return new RoundRobinRule();
    }
}

主启动类添加@RibbonClient

 在RestTemplate配置类上加注解,@LoadBalanced

在controller层修改代码,url不再是 http://localhost:8001

复刻8001,再生成8002的服务

做到这些还不够,现在只有8001的提供者,我们再给他复刻出来一个8002的服务

8001(右键复制)

想要上面那样的效果,需要快速运行设置

vm options: -Dserver.port=8002

 意味着服务名一样,同一个服务多个实例

重启80服务,重新获取服务列表。

此时再测试就达到了负载均衡轮询的效果(很帅)

Ribbon负载均衡算法
rest接口第几次请求数%服务器集群总数量=实际调用服务器位置下标

每次服务重启动后rest接口计数从1开始。


OpenFeign服务接口调用

HttpMessageConverters消息转交器

Feign是一个声明式的web服务客户端,Feign旨在使用编写Java Http客户端变得更容易。

Feign内置了 Ribbon

1、利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡。

2、与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。

OpenFeign是Spring Cloud 在Feign的基础上支持了SpringMVC的注解,如@RequestMapping。

引入依赖



    org.springframework.cloud
    spring-cloud-starter-openfeign

在配置文件application.yml加入以下配置

server:
  port: 80
spring:
  application:
    name: cloud-consumer-feign-order80
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

在主启动类加一个注解 @EnableFeignClients,不加@EnableEurekaClient也可以吗?也可以的

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

之前使用Ribbon+RestTemplate,因为不符合编程习惯。咱还是喜欢三层架构,没有Service层浑身不爽啊,那就使用OpenFeign的方式

在Controller层,调用service层,接着啥也不管。就是这么任性,哼。让我想起了傲娇的央视六公主,在b站的简介,就一个字。哼~

@RestController
public class OrderFeignController {

    @Resource
    private PaymentFeignService paymentFeignService;  //调用远程的微服接口
    
    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id){
        //远程调用    
        return paymentFeignService.getPaymentById(id);
    }
}

实现方式:接口+@FeignClient

新建PaymentFeignService接口并新增注解@FeignClient

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE") //下载注册中心的服务信息
public interface PaymentFeignService {
    @PostMapping(value = "/payment/create")
    public CommonResult create(@RequestBody Payment payment);

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id);
}

启动服务7001,8001,8002,openFeign80 

浏览器测试

Feign自带负载均衡(轮询)配置项

OpenFeign超时控制

在服务提供者处故意暂停程序,模拟3秒的延迟

Feign说:我只等一秒(默认等待一秒),等不到就错误渲染

 那肯定1秒是太短了呀,就要设置Feign超时时间,在application.yml中加入以下配置(顶格)

ribbon:
  ReadTimeout:  4000 # 读取
  ConnectTimeout: 4000  # 连接

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1020058.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号