分布式|微服务,看这一篇就够了

发布于:2022-11-15 ⋅ 阅读:(934) ⋅ 点赞:(0)

分布式,微服务的概念

 

        微服务主要是面对现在技术发展后,业务复杂度提升、用户量激增,单体项目很难再在这种高并发的场景下发挥作用。且业务的复杂度的提升,代码量几何倍数增长,在一个系统,一个项目下放置所有代码,对于代码的维护与解耦,都是很大的挑战。所以我们使用微服务的架构,将一个大的项目,拆分成多个独立的的系统,使用网络通信来让他们相互协调与合作,达到形如一个系统的效果。

        当然,微服务架构在解决问题的同时,也会出现很多单体项目下不会出现的新的挑战,在开发模式、使用的技术上,都会有很大的不同,并且在面对网络通信不稳定的情况下,又会有新的复杂性出现。

        

        下面我们来看看分布式系统常用的工具

        Spring-Cloud:Spring Cloud为开发人员提供工具,以快速构建分布式系统中的一些常见模式 (例如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)。分布式系统的协调存在一些通用的模式,使用Spring Cloud开发人员可以快速支持实现这些模式的服务和应用程序。它们将在任何分布式环境中运行良好,包括开发人员自己的笔记本电脑、裸机数据中心以及云铸造等托管平台。

        Spring-cloud下面有很多实用的工具,包括Spring-Cloud官方的gateway 、loadbalancer 、openfeign 等;阿里的nacos、dubbo、sentinel等;netflix的ribbon、hyxtrix等。

        我们这里的项目,采用nacos作为服务发现、配置管理的选项,sentinel-服务容错,seata-分布式事务、gateway-服务网关、openfeign-服务调用、ribbon-负载均衡;

        服务发现:

        每个服务因为是相对独立的系统,他们直接需要通信只有通过网络,服务发现就是找到服务实例的地址的过程,我们这里使用nacos;

        1.导入依赖

         <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
         </dependency>

        2.修改配置

spring:
  application:
    name: website
  cloud:
    nacos:
      config:
        server-addr: localhost:8848

        3.添加注解

@EnableDiscoveryClient

        4.启动服务器

Nacos 快速开始 下载服务器并启动。

服务发现的过程:

  1. 生产者启动时进行服务注册
  2. 消费者拉取服务列表
  3. 服务注册表对生产者进行健康检测
  4. 如果发生变更,服务注册表则通知消费者
  5. 消费者重新拉取服务列表

做完操作后,查看 Nacos Discovery 注册中心

(账号名/密码为 nacos/nacos)打开Nacos 控制台:

         负载均衡:

        这里我们采用netflix-ribbon作为负载均衡服务,由nacos-discovery引入。

ribbon的内置策略

策略名

策略声明

策略描述

实现说明

BestAvailableRule

最小并发数

public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule

选择一个最小的并发请求的server

逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server

AvailabilityFilteringRule

public class AvailabilityFilteringRule extends PredicateBasedRule

过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)

使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态

WeightedResponseTimeRule

响应时间加权

public class WeightedResponseTimeRule extends RoundRobinRule

根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。

一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。

RetryRule

public class RetryRule extends AbstractLoadBalancerRule

对选定的负载均衡策略机上重试机制。

在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server

RoundRobinRule

轮询

public class RoundRobinRule extends AbstractLoadBalancerRule

roundRobin方式轮询选择server

轮询index,选择index对应位置的server

RandomRule

随机

public class RandomRule extends AbstractLoadBalancerRule

随机选择一个server

在index上随机,选择index对应位置的server

ZoneAvoidanceRule

public class ZoneAvoidanceRule extends PredicateBasedRule

复合判断server所在区域的性能和server的可用性选择server

使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

策略1:

 /**
     * 全局替换成随机规则
     * @return
     */
    @Bean
    public IRule loadBalanceRule(){
        return new RandomRule();
    }

策略2:

# 为某一个服务指定负载均衡规则
user1:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

        服务调用

        这里我们采用spring-cloud-openfeign,声明式服务调用组件

        1.引入maven依赖

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


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


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

        2.加注解

@SpringBootApplication
@EnableFeignClients("com.woniuxy.cloud.order1.client")
public class Order1Application {

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

}


@FeignClient("user1")
public interface UserClient {

    @GetMapping("mallUser/getUser")
     String getUser(@RequestParam(value = "uid") Integer uid);

    @PostMapping("mallUser/putUser")
    String putUser(@RequestBody MallUserUpdateParam form);

    @DeleteMapping("mallUser/deleteUser")
    String deleteUser(@RequestParam(value = "uid") Integer uid);

    @PostMapping("mallUser/register")
    String register(@RequestBody MallUserParam form);
}

        3.进行调用

 @Resource
    private MallUserClient userClient;

 @GetMapping("/deleteUser")
    public String deleteUser(@RequestParam(value = "uid") Integer uid) {
        return userClient.deleteUser(uid);
    }

        接口共享

        将项目的接口和实现类,拆分开,项目的接口单独打包成模块,在另外一个项目中通过导入依赖的形式,使接口能够共享

        如我们这个项目的分层使用一下分类

将接口放在client层,另外一个项目需要使用时,在infra层调用。

        分布式事务

        我们这里使用seata提供的AT模式来进行分布式事务处理:

AT执行分布式事务主要是通过两个阶段的操作来实现:

        阶段1:预备阶段

        执行业务,在此时seata会代理数据源,获取所有的sql操作,并且获取到数据库sql操作的前后镜像,并且存入undo_log表,和sql的操作一些进行事务的提交

        阶段2:提交阶段

        如果是正常操作则删除undo_log表的数据,如果是失败操作,则获取undo_log表中的数据,进行反存回数据库的操作

AT模式实际操作

        1.导入依赖

 <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  </dependency>

        2.建立undo_log表

CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8

        3.加注解@GlobalTransactional

        4.配置yml

        5.启动seata-server作为TC

AT模式操作流程图

        服务网关

        我们这里采用gateway作为网关:

服务网关是作为系统唯一的一个入口,肩负一些通用的公共功能,比如黑白名单,动态路由,认证,授权等操作。

        搭建网关:

新建网关项目,导入依赖,写入配置:

        单点登录

        我们这里采用基于redis共享+cookie的方式 sa-token作为单点登录的选择。

        单点登录主要是实现在一个服务中登录后,其他服务也能共享登录的状态,我们一般会单独创建一个专门登录的服务器,由它来判断用户登录的逻辑和判断用户是否登录的状态。

        sa-token是通过cookies来保存token,每次请求的时候,携带token访问不同的服务时,都能通过token来获取登录的状态。

 

        服务容错

        我们这里采用Sentinel来作为服务容错的选择。官网: home

        sentinel提供流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

        启动sentinel控制台后,可以通过控制台来操作及定义服务

可通过规则定义sentinel的推送规则

 

         qps:每秒查询数

        warm up:冷启动,可以逐步提高通过的请求数,直到设定值

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到