防止内卷和被潜规则,Spring Cloud Alibaba微服务架构实战派(上下册)|35岁程序员那些事

本书上册深入探讨了Spring Cloud Alibaba的基础实战,包括Nacos服务治理、配置管理,Sentinel流量防护,Seata分布式事务,RocketMQ消息中间件和Spring Cloud Gateway高性能网关的使用与核心原理。
摘要由CSDN通过智能技术生成

目录

1 写书缘由

2 本书上册核心内容

2.1 Spring Cloud Alibaba基础实战

2.1.1 主要内容

2.1.2 MyBatis-Plus实现多租户架构的核心原理

2.2 分布式服务治理——基于Nacos

2.2.1 主要内容

2.2.2 Spring Cloud Alibaba服务订阅负载均衡的核心原理

2.3 分布式配置管理——基于Nacos

2.3.1 主要内容

2.3.2 基于Spring Cloud Alibaba的配置信息动态变更的核心原理

2.4 分布式系统的高可用流量防护——基于Sentinel

2.4.1 主要内容

2.4.2 基于Spring Cloud ALibaba,动态加载和持久化高可用流量防护规则的原理

2.5 高性能的分布式事务框架——Seata

2.5.1 主要内容

2.5.2 Seata Server启动原理

2.6 高可靠性分布式消息中间件RocketMQ

2.6.1 主要内容

 2.6.2 Spring Cloud Alibaba是如何封装RocketMQ的?

2.7 高性能网关Spring Cloud Gateway

2.7.1 主要内容

 2.7.2 Spring Cloud Gateway如何整合Redis,做网关限流

3 总结

4 欢迎关注公众号,35岁程序员那些事

笔者的畅销书 Spring Cloud Alibaba微服务架构实战派(上下册)出版了,京东、当当和天猫已经开始预售。

1 写书缘由

    笔者也是机缘巧合,才会开启自己的写书之路。

    在写这本书之前,我先后在两家杭州的“独角兽”公司担任技术负责人,并推进公司核心业务的“中台化”改造。在落地业务中台和技术中台的过程中,督促并指导开发人员统一使用Spring Cloud Alibaba作为中台服务最底层的基础框架。为了快速推进业务服务Spring Cloud Alibaba化的进度,我冲在业务的第一线,收集和整理开发人员在使用Spring Cloud Alibaba过程中反馈的技术问题,并提供有效的技术解决方案,直至项目落地。

    我每周都会做技术复盘,通过分析大量的问题总结出一个结论:开发人员反馈的问题大部分都是由于Spring Cloud Alibaba使用不合理所造成的。也就是说,很多开发人员并不了解Spring Cloud Alibaba的原理及如何落地实践。于是,我就产生了把我这几年落地Spring Cloud Alibaba的经验通过图书的方式输出的想法。

2 本书上册核心内容

2.1 Spring Cloud Alibaba基础实战

2.1.1 主要内容

Spring Cloud Alibaba“牛刀小试”,包括:使用Spring Cloud Alibaba作为基础框架实现乐观锁、实现多数据源和实现SQL语句中表名的动态替换。

【实例】用Maven和Spring Cloud Alibaba实现多环境部署,学习完本章内容,读者可以快速的使用配套源码,搭建可扩展的多环境运维部署环境。

【实例】用“MyBatis-Plus + Spring Cloud Alibaba”实现多租户架构,学习完本章内容,读者可以快速的使用配套源码,实现微服务架构中的多租户架构。

2.1.2 MyBatis-Plus实现多租户架构的核心原理

     熟悉Mybatis原理的开发应该都知道它的拦截器机制,Mybatis会使用注解@Intercepts去标注一个拦截器,并在Mybatis框架启动的过程中,扫描当前Spring IOC容器中被注解@Intercepts标记的拦截器。

    第一步:MyBatis-Plus定义一个全局拦截器MybatisPlusInterceptor类,如下所示。

//通过注解@Intercepts,将MyBatis-Plus和Mybatis绑定在一起
@Intercepts(
    {
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
        @Signature(type = StatementHandler.class, method = "getBoundSql", args = {}),
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
    }
)
public class MybatisPlusInterceptor implements Interceptor {
    @Setter
    private List<InnerInterceptor> interceptors = new ArrayList<>();
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
      //遍历内部拦截器列表,并执行InnerInterceptor.beforeUpdate()
    }
}

第二步:MyBatis-Plus定义一个内部多租户拦截器TenantLineInnerInterceptor类,如下所示。

public class TenantLineInnerInterceptor extends JsqlParserSupport implements InnerInterceptor {
    private TenantLineHandler tenantLineHandler;
    //使用代理和反射,生成一个租户处理器TenantLineHandler
    @Override
    public void setProperties(Properties properties) {
        PropertyMapper.newInstance(properties)
            .whenNotBlack("tenantLineHandler", ClassUtils::newInstance, this::setTenantLineHandler);
    }
    ...
}

2.2 分布式服务治理——基于Nacos

2.2.1 主要内容

认识分布式服务治理

了解主流的注册中心

将应用接入Nacos 注册中心

用“NacosNamingService类 + @EnableDiscoveryClient”实现服务的注册/订阅

用“Ribbon + Nacos Client”实现服务发现的负载均衡

用CP模式和AP模式来保持注册中心的数据一致性

用缓存和文件来存储Nacos的元数据

用Nacos Sync来实现应用服务的数据迁移

2.2.2 Spring Cloud Alibaba服务订阅负载均衡的核心原理

Spring Cloud Alibaba定义了一个加载负载均衡规则的类NacosRule,它继承了ribbon-loadbalancer项目中的AbstractLoadBalancerRule类,具体如下所示: 

public class NacosRule extends AbstractLoadBalancerRule {
  @Autowired
	private NacosDiscoveryProperties nacosDiscoveryProperties;
	@Autowired
	private NacosServiceManager nacosServiceManager;
  @Override
	public Server choose(Object key) {
		try {
      //获取Nacos的集群名称
			String clusterName = this.nacosDiscoveryProperties.getClusterName();
      //获取Group的名称
			String group = this.nacosDiscoveryProperties.getGroup();
			DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
			String name = loadBalancer.getName();
      //实例化一个Nacos Client的服务注册中心的名称服务对象NamingService
			NamingService namingService = nacosServiceManager
					.getNamingService(nacosDiscoveryProperties.getNacosProperties());
      //获取指定服务名称的所有健康的服务实例信息
			List<Instance> instances = namingService.selectInstances(name, group, true);
			if (CollectionUtils.isEmpty(instances)) {
				LOGGER.warn("no instance in service {}", name);
				return null;
			}
			...
      //使用负载均衡算法,均衡的选举一个服务实例,并返回一个NacosServer对象,完成负载均衡
			Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose);
			return new NacosServer(instance);
		}
		catch (Exception e) {
			LOGGER.warn("NacosRule error", e);
			return null;
		}
	}
}

Spring Cloud Alibaba复用了Nacos提供的服务负载均衡算法,当然开发人员可以自己实现一个负载均衡算法。Nacos的服务负载均衡算法如下所示。

public class Balancer {
  //按照随机权重,进行服务的负载均衡
  protected static Instance getHostByRandomWeight(List<Instance> hosts) {
        NAMING_LOGGER.debug("entry randomWithWeight");
        if (hosts == null || hosts.size() == 0) {
            NAMING_LOGGER.debug("hosts == null || hosts.size() == 0");
            return null;
        }
        NAMING_LOGGER.debug("new Chooser");
        List<Pair<Instance>> hostsWithWeight = new ArrayList<Pair<Instance>>();
        //过滤掉不健康的服务实例
        for (Instance host : hosts) {
            if (host.isHealthy()) {
                hostsWithWeight.add(new Pair<Instance>(host, host.getWeight()));
            }
        }
        NAMING_LOGGER.debug("for (Host host : hosts)");
        Chooser<String, Instance> vipChooser = new Chooser<String, Instance>("www.taobao.com");
        //刷新服务实例的权重信息,这些权重信息可以通过Nacos的UI控制台,或者Open API动态的修改,并实时的生效
        vipChooser.refresh(hostsWithWeight);
        NAMING_LOGGER.debug("vipChooser.refresh");
        //执行负载均衡算法
        return vipChooser.randomWithWeight();
    }
  ...
}
//负载均衡算法选择器
public class Chooser<K, T> {
  public T randomWithWeight() {
        Ref<T> ref = this.ref;
        //产生随机种子
        double random = ThreadLocalRandom.current().nextDouble(0, 1);
        //采用二分查找,获取下标编号
        int index = Arrays.binarySearch(ref.weights, random);
        if (index < 0) {
            index = -index - 1;
        } else {
            return ref.items.get(index);
        }
        if (index >= 0 && index < ref.weights.length) {
            if (random < ref.weights[index]) {
                return ref.items.get(index);
            }
      
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

架构随笔录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值