Apollo核心功能源码分析(1)-发布配置信息流程分析

探索xxl-job + apollo工具在自动化测试框架的应用——使用xxl-job运行TestNG测试方法 使用xxl-job运行TestNG测试方法 0.引言 对于Spring Boot框架想必大家在开发人员的口中经常听到,在各种微信公众号号上想必也能经常看见,但在自动化框架中,我想大多数测试人员应该用不上。包括我在内,我一直认为自动化测试框架使用TestNG就足够了,不需要再额外增加一个新的框架来增加脚本的开发难度。但由于我们要使用xxl-job与apollo,导致我们必须使用Spring boot框架进行配置,这就使得我在使用TestNG编写自动化测试脚本时,必须将测试框架整合到Spring boot框架中 阅读详情

序言:

Apollo目前是国内开源中对于配置中心这一组件来说使用率应该是最高的一个项目了,它可以快速整合入我们当前的SOA(Dubbo体系),微服务架构中(springcloud体系)。相对于之前基于zk的自我实现(开发成本太高,强依赖与zk),或springcloud config(开发成本不高,使用简单但是运行维护很是不变复杂)来说,它提供了一套基于配置管理平台,对于某一服务在不同环境(开发-DEV,测试-TEST,预生产,生产-PRO)使用不同配置或同一环境不同集群都可以做到协做管理。基于Eureka的使得整体可以做到高可用,也提供本地缓存方式,使得即使Apollo不可用也可提供暂时性的服务。还提供了用户权限管理,灰度发布等其它功能。关于此可详细从官网中进行自我学习。

1:服务端描述

看过Apollo官网的大体介绍,可以知晓在Apollo的整体架构中,有多种角色(整体看待apollo,它是一个小型的微服务架构-虽然只有可怜的3个服务:Config,Admin,Portal),如下所示是官网中整体架构图:

overall-architecture

如下所示对于上述各组件的详细描述(来自官网描述):

1.1 Config Service

  • 提供配置获取接口
  • 提供配置更新推送接口(基于Http long polling)
    • 服务端使用Spring DeferredResult实现异步化,从而大大增加长连接数量
    • 目前使用的tomcat embed默认配置是最多10000个连接(可以调整),使用了4C8G的虚拟机实测可以支撑10000个连接,所以满足需求(一个应用实例只会发起一个长连接)。
  • 接口服务对象为Apollo客户端

1.2 Admin Service

  • 提供配置管理接口
  • 提供配置修改、发布等接口
  • 接口服务对象为Portal

1.3 Meta Server

  • Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port)
  • Client通过域名访问Meta Server获取Config Service服务列表(IP+Port)
  • Meta Server从Eureka获取Config Service和Admin Service的服务信息,相当于是一个Eureka Client
  • 增设一个Meta Server的角色主要是为了封装服务发现的细节,对Portal和Client而言,永远通过一个Http接口获取Admin Service和Config Service的服务信息,而不需要关心背后实际的服务注册和发现组件
  • Meta Server只是一个逻辑角色,在部署时和Config Service是在一个JVM进程中的,所以IP、端口和Config Service一致

1.4 Eureka

  • 基于Eureka和Spring Cloud Netflix提供服务注册和发现
  • Config Service和Admin Service会向Eureka注册服务,并保持心跳
  • 为了简单起见,目前Eureka在部署时和Config Service是在一个JVM进程中的(通过Spring Cloud Netflix)

1.5 Portal

  • 提供Web界面供用户管理配置
  • 通过Meta Server获取Admin Service服务列表(IP+Port),通过IP+Port访问服务
  • 在Portal侧做load balance、错误重试

1.6 Client

  • Apollo提供的客户端程序,为应用提供配置获取、实时更新等功能
  • 通过Meta Server获取Config Service服务列表(IP+Port),通过IP+Port访问服务
  • 在Client侧做load balance、错误重试

1.7 NginxLB

 

  • 和域名系统配合,协助Portal访问MetaServer获取AdminService地址列表

  • 和域名系统配合,协助Client访问MetaServer获取ConfigService地址列表

  • 和域名系统配合,协助用户访问Portal进行配置管理

ConfigService和AdminService会共享ConfigDB,ConfigDB中存放项目在某个环境中的配置信息,在多环境部署情况下ConfigService/AdminService/ConfigDB三者在每个环境(DEV/FAT/UAT/PRO)中都要部署一份。

2:用户发送配置变更整体流程分析

而对于一个配置的修改发布,上述角色都会贯穿其中,在各自的领域提供自己的贡献,如下所示是官网上发送配置的流程,实际大体也是如此,只不过少画了Meat Server逻辑角色在其中的作用。

release-message-notification-design

当使用者从界面上发布一个配置时,会经历多少个的网络io请求后才会到达client端,基于上图进行源码分析:

使用者从浏览器端发起一个http请求,此时由Portal Server服务进行第一次接受

经过上述内部流程后,通过restTemplate(该类为apollo实现RetryableRestTemplate-包含重试功能)朝adminService服务发送http请求,如下所示:

AdminServer通过该接口接受portal Server请求,并组装message进行push

写入数据库中,当数据写入成功,那么该次变更也就成功了。剩下就是Config Server的事情了

最终数据库中数据:

为什么Apollo使用数据库作为消息推送的载体:

对于一个mq消息推送机制来说,现有存在三种种机制。基于push模式,基于pull模式,以及两种都有的模式,RabbitMQ,Kafka,RocketMQ3种组件分别对应现有的3种开源的mq实现。三种模式都各有特点,push模式更适用于对时间敏感的业务需求,例如交易,定时器执行(这里说下开源分布式调度组件xxljob就是基于Netty通信的一个push模式,由身为Netty客户端的服务端push身为Netty服务端的客户端)。Apollo感觉比较特殊,为了减少避免外部组件的依赖,又因为Apollo作为一个配置中心,管理全局的配置信息,而对于一个配置信息那么它不论在生产,测试,开发环境基本变化很少,所以此处引入一个mq组件对于Apollo来说太过于笨重,所以它使用数据库ReleaseMessage表作为它的消息推送的存储。

当数据写入到数据库后,该请求就代表结束了,也就告知用户该次配置发布成功了。但对于apollo来说,实际上才完成了一半的功能。接下来就是到ConfigServer服务的时间了,它通过一个线程异步的扫描ReleaseMessage表中的Message信息,构建成一个message通过观察者模式向注册的ReleaseMessageListener发送通知。如下所示:

public class ReleaseMessageScanner implements InitializingBean {
  private static final Logger logger = LoggerFactory.getLogger(ReleaseMessageScanner.class);
  @Autowired
  private BizConfig bizConfig;
  //ReleaseMessage 数据库
  @Autowired
  private ReleaseMessageRepository releaseMessageRepository;
  private int databaseScanInterval;
  //listeners
  private List<ReleaseMessageListener> listeners;
  //周期任务调度器 100ms执行一次
  private ScheduledExecutorService executorService;
  private long maxIdScanned;

  public ReleaseMessageScanner() {
    listeners = Lists.newCopyOnWriteArrayList();
    //单线程执行
    executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory
        .create("ReleaseMessageScanner", true));
  }

  //bean初始化后执行
  @Override
  public void afterPropertiesSet() throws Exception {
    //设置周期时间 默认100ms
    databaseScanInterval = bizConfig.releaseMessageScanIntervalInMilli();
    maxIdScanned = loadLargestMessageId();
    //延时100ms 扫描数据
    executorService.scheduleWithFixedDelay((Runnable) () -> {
      Transaction transaction = Tracer.newTransaction("Apollo.ReleaseMessageScanner", "scanMessage");
      try {
        //扫描message
        scanMessages();
        transaction.setStatus(Transaction.SUCCESS);
      } catch (Throwable ex) {
        transaction.setStatus(ex);
        logger.error("Scan and send message failed", ex);
      } finally {
        transaction.complete();
      }
    }, databaseScanInterval, databaseScanInterval, TimeUnit.MILLISECONDS);

  }

  /**
   * add message listeners for release message
   * @param listener
   */
  public void addMessageListener(ReleaseMessageListener listener) {
    if (!listeners.contains(listener)) {
      listeners.add(listener);
    }
  }

  /**
   * 扫描表中的message信息 直到无message
   */
  private void scanMessages() {
    boolean hasMoreMessages = true;
    //线程被中断
    while (hasMoreMessages && !Thread.currentThread().isInterrupted()) {
      hasMoreMessages = scanAndSendMessages();
    }
  }

  /**
   * scan messages and send
   *
   * @return whether there are more messages
   */
  private boolean scanAndSendMessages() {
    //current batch is 500
    //每次从数据中拿取500条
    List<ReleaseMessage> releaseMessages =
        releaseMessageRepository.findFirst500ByIdGreaterThanOrderByIdAsc(maxIdScanned);
    //无消息结束循环
    if (CollectionUtils.isEmpty(releaseMessages)) {
      return false;
    }
    //通过listener
    fireMessageScanned(releaseMessages);
    int messageScanned = releaseMessages.size();
    maxIdScanned = releaseMessages.get(messageScanned - 1).getId();
    return messageScanned == 500;
  }

  /**
   * find largest message id as the current start point
   * @return current largest message id
   */
  private long loadLargestMessageId() {
    ReleaseMessage releaseMessage = releaseMessageRepository.findTopByOrderByIdDesc();
    return releaseMessage == null ? 0 : releaseMessage.getId();
  }

  /**
   * 通知listener 已获取数据
   * @param messages
   */
  private void fireMessageScanned(List<ReleaseMessage> messages) {
    for (ReleaseMessage message : messages) {
      //遍历所有listener 基于观察者模式
      for (ReleaseMessageListener listener : listeners) {
        try {
          //处理message
          listener.handleMessage(message, Topics.APOLLO_RELEASE_TOPIC);
        } catch (Throwable ex) {
          Tracer.logError(ex);
          logger.error("Failed to invoke message listener {}", listener.getClass(), ex);
        }
      }
    }
  }
}

那么Apollo中mq是一种模式呢,个人感觉主要是pull模式但又结合了一定的push,因为它主要是由client发起http请求到ConfigServer端(/notifications/v2),而Server会保持与该请求的60s的连接,如果在这时间内无任何对应的namespace配置变更,则返回304并定时开始下一轮的请求连接,若有则向response中写入变更的namespace信息。client收到response会立即请求Config Service获取该namespace的最新配置。源码如下所示:

在接受client请求数据后经过一系列检查初始化后,封装DeferredResultWrapper对象并写入缓存map中,实际可以理解就是client向server进行注册一次有效时长的连接。

而NotificationControllerV2也实现了ReleaseMessageListener接口,实现了handleMessage(),也就是会收到配置变更的消息。以下是handleMessage方法中核心处理代码。

至此Apollo的服务端推送逻辑结束了,下文讲述客户端pull配置信息逻辑以及对应的源码。

2:客户端

以下描述下客户端在Apollo整体架构中的作用,以及在发布配置信息流程体系中的作用如下所示是从官网copy过来的客户端整体设计图:

从上图可以看出,Apollo的客户端需要与服务端存在两种获取配置信息方式,第一种就是第一篇中描述的push方式(实际上也是客户端先发起一个60s的一个连接),一旦服务端收到用户发送的变更请求就会触发一次push。第二种就是client定时向客户端pull配置信息(定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定System Property: apollo.refreshInterval来覆盖,单位为分钟,不过一般通过该方式返回的结果都是304即未发生变更)。当client获取到最新的数据会写入到内存中进行缓存,并同步到具体的应用程序。同时也会将数据写入到本地中缓存,避免因为Apollo的当机导致的服务不可用。

对于Apollo的理解还是建议去查看官网描述:https://github.com/ctripcorp/apollo/wiki/ 

配置中心Apollo 源码分析01 代码结构概述 705个java类, 6.6w代码行数,算是中小型的开源项目 1.apollo-adminservice : 后台管理相关 2.apollo-biz :基本功能封装, 包括鉴权,配置,服务注册发现,灰度发布,存储,消息 3.apollo-client : apollo的客户端 4.apollo-common:基础工具函数封装 5.apollo-configService :配置服务 6. apollo-core : 核心功能 7.apollo-portal : apol.. 阅读详情

相关推荐

【Java进阶营】【SpringCloud技术专题】「Eureka源码分析」从源码层面让你认识Eureka工作流程和运作机制(上)

前言介绍 了解到了SpringCloud,大家都应该知道注册中心,而对于我们从过去到现在,SpringCloud中用的最多的注册中心就是Eureka了,所以深入Eureka的原理和源码,接下来我们要进行讲解下eureka的源码分析,由此应运而产生的本章节的内容。 基本原理 Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。 Eureka

hong1008611的博客 333

SpringBoot+Apollo配置动态线程池

文章目录前言实现核心依赖配置文件实现代码 前言 尽管我们经过谨慎的评估,仍然不能够保证一次计算出来来的线程池参数是合适的,那么我们是否可以将修改线程池参数的成本降下来,这样至少可以发生故障的时候可以快速调整从而缩短故障恢复的时间呢?基于这个思考,我们是否可以将线程池的参数从代码中迁移到分布式配置中心上,实现线程池参数可动态配置和即时生效,线程池参数动态化前后的参数修改流程对比如下 实现 分布式配置中心这里使用的是Apollo 核心依赖 <dependency> &l

念念不忘,必有回响 5463

Java定时任务调度框架Quartz核心原理与Spring Boot整合实战

定时任务调度是构建可靠后台系统的核心技术之一,它允许程序在预定时间或周期性地自动执行特定操作。其核心原理在于将任务定义、触发规则与执行调度进行解耦,通过调度器统一管理。这项技术的价值在于能够自动化处理大量周期性业务,如数据同步、报表生成和系统监控,从而提升系统自动化水平和运维效率。在Java生态中,Quartz作为经典的企业级调度框架,凭借其稳定性和丰富的功能,成为处理复杂调度需求的首选。它通过调度器、触发器和任务三要素协同工作,并支持基于数据库的集群部署,确保任务在分布式环境下的高可用与负载均衡。本文将结

weixin_30307921的博客 389

Apollo 7 — ConfigService 消息扫描设计实现

目录 设计 代码实现 总结 1.设计 Apollo 为了减少依赖,将本来 MQ 的职责转移到了 Mysql 中。具体表现为 Mysql 中的 ReleaseMessage 表。 具体官方文档可见:发送ReleaseMessage的实现方式 用张图简单的来表示一下 : 有人肯定要问了,为什么 Admin Service 和 Config Service 不放在一起呢?我曾提过 issue 问过...

weixin_34365635的博客 212

apollo全流程、原理、源码解析

目录 apollo架构 流程解析(用户界面和服务端(apollo-adminservice)通信过程) 流程解析(服务端(apollo-adminservice)和configservice端通信过程) apollo架构 流程解析(用户界面和服务端(apollo-adminservice)通信过程) 1、用户在前端触发增、删、改操作 2、前端服务会将请求发送至apollo-portal服务(ItemController),在发送请求之前apollo-portal做了以下事.

jiaojie1112的博客 2917

【信息科学与工程学】计算机科学与自动化——第一百九十八篇 高并发高可用的知识点01

以上补充约 110 行,涵盖分布式协调、服务网格细节、数据库高级特性、性能分析工具、混沌工程、安全渗透、合规审计、研发效能、新兴技术、架构模式、实用工具及经典论文。涵盖数据库索引与锁、NoSQL、前端性能、安全攻防、压测工具深入、监控深入、云原生存储、服务治理扩展、代码质量、DevOps 文化、行业标准、软技能及未来趋势。好的,继续补充更多高并发、高可用、高可靠的知识与技术,涵盖更深层的数据库内部机制、分布式事务、服务治理、运维自动化、安全与前沿技术等领域。

weixin_49199313的博客 732

Apollo 源码解析 —— Admin Service 发送 ReleaseMessage

1. 概述 老艿艿:本系列假定胖友已经阅读过《Apollo 官方 wiki 文档》。 本文接《Apollo 源码解析 —— Portal 发布配置》一文,分享配置发布的第三步,Admin Service 发布配置后,发送 ReleaseMessage 给各个Config Service。 FROM《Apollo配置中心设计》的2.1.1 发送ReleaseMessage的实现方式 Admin Service 在配置发布后,需要通知所有的 Config Service 有配置发布...

weixin_42073629的博客 588

问题解决:打开VMware创建的虚拟机,电脑立刻蓝屏并重启

VMware Workstation 与 Device/Credential Guard 不兼容。在禁用 Device/Credenti

weixin_55118477的博客 3万+

【Thread】线程工厂-ThreadFactory

ThreadFactory---线程工厂 在apollo源码中有这么一段代码 ExecutorService m_longPollingService = Executors.newSingleThreadExecutor(ApolloThreadFactory.create("RemoteConfigLongPollService", true)); m_longPo...

dengzong6976的博客 276

EPLAN二次开发入门:Visual Studio 2019环境配置与插件调试实战

本文详细介绍了EPLAN二次开发入门的关键步骤,重点讲解如何在Visual Studio 2019中配置开发环境并进行插件调试。通过创建符合命名规范的项目、引用核心API库、实现插件接口以及使用附加进程调试等实战技巧,帮助电气工程师快速掌握EPLAN插件开发,提升自动化设计效率。

h6i7j8的博客 763

ipsec 加密流程(一):ipsec策略匹配

《openswan》专栏系列文章主要是记录openswan源码学习过程中的笔记。 Author: Toney Email: vip_13031075266@163.com Date: 2020.11.22 Copyright: 未经同意不得转载!!! Version:2.6.51.5 Reference:https://download.openswan.org/openswan/ 1. ipsec策略匹配流程(ipsec_tunnel_start_xmit) 注:open...

遇见你是我最美丽的意外 9122

【Apollo CyberRT】源码分析之 “component” 模块

与组件类不同,定时组件类在 Initialize() 中没有创建任何的 Reader 读者,也没有搞出调度器、协程工厂、创建任务等一系列复杂的操作,任务全部交给时间轮处理。Component类是各个组件的基类实现,组件类似与ros里的node,每个算法模块都可以自己实现为一个Component的基类,从而加入到CyberRT的框架中。定时调度模块没有绑定消息收发,需要用户自己创建reader来读取消息,如果需要读取多个消息,可以创建多个reader。定时组件类与组件类有所不同,它比组件类多了定时器。

zhaoyqcsdn的博客 1286

Allan方差读图分析IMU误差指标

Allan方差标定IMU参数实测分析

weixin_44927558的博客 3566

Apollo配置中心客户端源码解析

配置中心在现在的分布式系统可以说是一个必不可少的核心组件了,国内使用最广泛的配置中心应该是携程开发的Apollo。Apollo的思想还是挺简单的,简单地说,服务端利用Eureka做高可用,配置信息存到数据库,客户端调用服务端的接口,拉取最新的配置,如果有变化,就更新客户端的配置。服务端提供了可视化的图形界面去修改配置,保存到数据库。我们今天先来看下客户端部分是如何来实现的。 客户端的主要功能就是调用服务端接口,获取最新的配置,然后更新配置。由于apollo-client的代码还是比较复杂了,因此在它的基础上

若鱼的专栏 948

RV1126开发板性能实测:网络、温度与功耗全解析

本文对RV1126开发板进行了全面的性能实测,重点分析了网络性能、温度表现与功耗特性。测试发现UDP带宽可达500Mbps,但TCP性能受限于协议栈;散热设计对持续性能至关重要,大板子在AI推理和视频推流中表现更稳定。为嵌入式开发者提供了真实的选型参考和优化建议。

d3e4f的博客 267

Mac Pro M2芯片成功安装麒麟银河高级服务器虚拟机

本人用的是1、Macbook m2pro芯片 16G+5123、安装homebrew、wegt、qemu。

vagatable_XX的博客 3300

pb9.0.3 8836补丁包_Apollo 2.0 框架及源码分析(一) | 软硬件框架

前言如引言中介绍的,这篇软硬件框架多为现有消息的整合加一些个人的想法。关于 Apollo 介绍的文章已经有许多,很多要点大家都已经足够了解,这些点在本篇中会被略写。本篇文章如有错误、不足之处,还请大家多多指教。Apollo 官方 GitHub 链接:Apollo Auto在历经1.0,1.5 两个版本更新之后,百度无人驾驶平台 Apollo 2.0 在2018年初正式发布。其技术框架如下图所示 [...

weixin_39875941的博客 1250

别再死记硬背了!用Wireshark抓包实战,5分钟搞懂GRE、L2TP、IPsec的区别

本文通过Wireshark抓包实战,详细解析GRE、L2TP和IPsec三大隧道协议的核心差异与应用场景。从报文结构到配置示例,帮助网络工程师快速掌握这些协议的本质,提升VPN部署与故障排查能力。特别适合准备HCIP认证的工程师深化理解。

weixin_30352645的博客 439

Apollo2.0自动驾驶之apollo/modules/prediction/common/geometry_util.h

/****************Apollo源码分析**************************** Copyright 2018 The File Authors &amp; zouyu. All Rights Reserved. Contact with: 1746430162@qq.com 181663309504 源码主要是c++实现的,也有少...

北漠苍狼的专栏(QQ:1746430162) 762

EMI辐射发射超标案例

EMI辐射发射超标案例

让你爱上电路设计 8503

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Apollo2.0自动驾驶howto文件夹之how_to_run_offline_sequential_obstacle_perception_visualizer.md

/****************Apollo源码分析**************************** Copyright 2018 The File Authors &amp; zouyu. All Rights Reserved. Contact with: 1746430162@qq.com 181663309504 源码主要是c++实现的,也有少...

北漠苍狼的专栏(QQ:1746430162) 434

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

配置中心技术评估指南:从QuickConfig实战到生产环境部署

配置管理是现代分布式系统的核心基础设施,通过集中化管理应用配置参数实现环境隔离和动态更新。其工作原理基于客户端-服务器架构,支持配置的拉取、缓存和实时监听机制,确保系统在运行时能够快速响应配置变更。在微服务架构中,配置中心的技术价值体现在提升部署效率、降低运维复杂度以及增强系统可观测性。常见的应用场景包括功能开关、参数调优和多环境配置管理。以QuickConfig为代表的轻量级配置中心工具,特别适合中小型项目的快速集成验证,本文通过Docker环境部署、客户端集成示例和性能优化策略,为开发者提供从技术验证到

weixin_34302561的博客 406

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

React Native第三方库集成:常用库选型与最佳实践指南 [特殊字符]

React Native作为一款优秀的跨平台移动应用开发框架,其强大的生态系统和丰富的第三方库支持是开发者选择它的重要原因。本文将为你详细介绍React Native第三方库的完整集成指南,包括常用库的选型策略、最佳实践以及性能优化技巧。 ## 为什么需要第三方库?🤔 React Native虽然提供了丰富的内置组件,但在实际开发中,我们经常需要集成各种功能模块,如图像处理、地图导航、推送通

gitblog_00906的博客 1004

2025年Java开发者成长地图:从核心原理到微服务架构的实战进阶

Java作为企业级应用开发的主流语言,其知识体系涵盖从语言基础到分布式架构的多个层面。理解JVM内存模型与垃圾回收机制是编写高性能应用的基础,而并发编程中的线程池与AQS原理则是解决高并发场景的关键。在微服务架构成为主流的今天,掌握Spring Boot自动配置原理及Spring Cloud服务治理组件,能够帮助开发者构建可扩展、易维护的分布式系统。结合Redis缓存与消息队列等中间件,可以有效提升系统吞吐量与可靠性。本文围绕Java核心、微服务架构及工程实践,为开发者提供一套从原理到实战的成长策略,助力应

cuanji3287的博客 626

深入MLX Affine 4-bit量化格式:Qwen3.8-27B-GPTQ-4bit中scales、biases与group_size详解

**Qwen3.8-27B-GPTQ-4bit** 是基于 **MLX Affine 4-bit 量化格式**打造的 15 GB 多模态大模型。本文结合仓库中的真实配置文件,带你搞懂 `bits`、`group_size`、`mode` 三大参数,以及 `weight`、`scales`、`biases` 三组张量如何分工协作,再看 GPTQ 误差补偿如何让量化模型更贴近 bf16 原版。 ##

gitblog_00330的博客 80

【动态定时任务】从apollo配置中心获取定时任务的执行时间,能够实时修改定时任务执行时间

基本原理:设置两次定时任务,一次专门捕获apollo的定时任务时间是否修改。另一次获取apollo上设置的定时任务执行时间,执行定时任务。

weixin_45716265的博客 1784
上一篇: Java中J.U.C包下锁的基础-AQS分析
下一篇: 阿里开源一站式分布式事务框架seata源码分析(AT模式下TM与RM分析)
F_Hello_World
博客等级 码龄11年 38粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值