服务监控与优化之负载均衡之负载最低优先

news2024/10/5 10:26:20

相关文章:

  • 自己动手写分布式任务调度框架
  • 用 Java 代码实现负载均衡的五种常见算法
  • 手写实现RPC框架(带注册中心)
  • 本文完整代码地址:https://gitee.com/dongguabai/blog/tree/master/loadbalance

前段时间,我们有一台定时任务执行机器(总共有 3 台机器负责处理定时任务)出现内存使用率超过 92% 的告警。在分布式任务调度中心,通常会有一套负载均衡策略来选择执行当前任务的机器。

这里就有一个思考点:如果一台机器已经超负载或即将超负载,是否可以通过减少其任务分配来降低其在负载均衡中的权重,以实现更好的负载均衡。即基于机器负载情况的动态权重负载均衡,即负载最低优先

前面几种算法主要是站在负载均衡服务的角度,保证每个机器节点获得的调用次数均衡或者相对均衡,但是实际生产环境调用次数相同并不一定真的能够让每台机器真的实现均衡,于是就有了负载最低优先的策略,负载最低优先可以使用如最小连接数、CPU/IO 负载,这里引入《从零开始学架构》中的介绍:

负载最低优先算法基本上能够比较完美地解决轮询算法的缺点,因为采用这种算法后,负载均衡系统需要感知服务器当前的运行状态。当然,其代价是复杂度大幅上升。通俗来讲,轮询可能是 5 行代码就能实现的算法,而负载最低优先算法可能要 1000 行才能实现,甚至需要负载均衡系统和服务器都要开发代码。负载最低优先算法如果本身没有设计好,或者不适合业务的运行特点,算法本身就可能成为性能的瓶颈,或者引发很多莫名其妙的问题。所以负载最低优先算法虽然效果看起来很美好,但实际上真正应用的场景反而没有轮询(包括加权轮询)那么多。

用 Java 代码实现负载均衡的五种常见算法

要实现这一套逻辑,有一个关键点,即如何获取机器负载情况,在 Java 层面可以基于 JMX 来做。JMX 全称为 Java Management Extensions(Java管理扩展),是一种 Java 平台上用于监控和管理应用程序、系统和网络服务的技术和标准。它提供了一种标准化的方式来管理 Java 应用程序的运行时状态、性能以及配置信息。在 java.lang.management 下可以看到很多标准化的接口,如:

  • java.lang.management.OperatingSystemMXBean
  • java.lang.management.MemoryPoolMXBean

随机

这里基于很早之前的一篇博客手写实现RPC框架(带注册中心)来实现负载最低优先的负载均衡,之前是基于随机负载来做的,可以验证一下,使用 12345、12346、12347 三个端口号分别启动三个 Server:

/**
 * @author Dongguabai
 * @date 2018/11/1 18:07
 */
public class ServerDemo {

    public static void main(String[] args) {
        //之前发布服务
/*
        RpcServer rpcServer = new RpcServer();
        rpcServer.publisher(new HelloServiceImpl(),12345);
*/
        //改造后
        IRegistryCenter registryCenter = new RegistryCenterImpl();
        //这里为了方便,获取ip地址就直接写了
        RpcServer rpcServer = new RpcServer(registryCenter,"127.0.0.1:12345");
        //绑定服务
        rpcServer.bind(new HelloServiceImpl(12345));
        rpcServer.publisher();
    }
}

相关日志:

09:59:32.378 [main] INFO blog.dongguabai.lb.core.registry.RegistryCenterImpl - 服务注册成功:/rpcNode/blog.dongguabai.lb.core.demo.IHelloService/127.0.0.1:12347
09:59:32.380 [main] INFO blog.dongguabai.lb.core.RpcServer - 注册服务成功:【serviceName:blog.dongguabai.lb.core.demo.IHelloService,address:127.0.0.1:12347】

可以在 ZK 上看一下:

[zk: 127.0.0.1(CONNECTED) 1] ls /rpcNode/blog.dongguabai.lb.core.demo.IHelloService
[127.0.0.1:12346, 127.0.0.1:12345, 127.0.0.1:12347]
[zk: 127.0.0.1(CONNECTED) 0] get /rpcNode/blog.dongguabai.lb.core.demo.IHelloService/127.0.0.1:12345
0
cZxid = 0x600000005
ctime = Thu Sep 21 18:58:39 PDT 2023
mZxid = 0x600000005
mtime = Thu Sep 21 18:58:39 PDT 2023
pZxid = 0x600000005
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x100151f82810000
dataLength = 1
numChildren = 0

能够看到三个服务都已经注册上去了。

客户端调用,看一下随机负载的效果:

/**
 * @author Dongguabai
 * @date 2018/11/1 18:10
 */
public class ClientDemo {

    public static void main(String[] args) {
        /*RpcClientProxy proxy = new RpcClientProxy();
        IHelloService helloService = proxy.clientProxy(IHelloService.class, "127.0.0.1", 12345);
        String name = helloService.sayHello("张三");
        System.out.println(name);*/
        List<String> list = new ArrayList<>();

        for (int i = 0; i < 30; i++) {
            IServiceDiscovery serviceDiscovery = new ServiceDiscoveryImpl(RegistryCenterConfig.CONNECTING_STR);
            RpcClientProxy proxy = new RpcClientProxy(serviceDiscovery);
            IHelloService service = proxy.clientProxy(IHelloService.class);
            System.out.println(service.sayHello("张三"));
        }
    }
}

输出:

[12347]-你好,张三
[12347]-你好,张三
[12346]-你好,张三
[12346]-你好,张三
[12345]-你好,张三
[12345]-你好,张三
[12346]-你好,张三
[12347]-你好,张三
[12347]-你好,张三
[12345]-你好,张三
[12346]-你好,张三
[12346]-你好,张三
[12346]-你好,张三
[12347]-你好,张三
[12345]-你好,张三
[12347]-你好,张三
[12346]-你好,张三
[12347]-你好,张三
[12345]-你好,张三
[12347]-你好,张三
[12346]-你好,张三
[12345]-你好,张三
[12346]-你好,张三
[12346]-你好,张三
[12345]-你好,张三
[12347]-你好,张三
[12345]-你好,张三
[12346]-你好,张三
[12347]-你好,张三
[12347]-你好,张三

可以看到每个服务接收到的请求比较均匀。

服务发现的代码:

    @Override
    public String discover(String serviceName) {
        //获取/rpcNode/dgb.nospring.myrpc.demo.IHelloService下所有协议地址
        String nodePath = RegistryCenterConfig.NAMESPACE+"/"+serviceName;
        try {
            repos = curatorFramework.getChildren().forPath(nodePath);
        } catch (Exception e) {
            throw new RuntimeException("服务发现获取子节点异常!",e);
        }
        //动态发现服务节点变化,需要注册监听
        registerWatcher(nodePath);

        //这里为了方便,直接使用随机负载
        LoadBalance loadBalance  = new RandomLoadBanalce();
        return loadBalance.selectHost(repos);
    }

随机代码:

/**
 * 随机负载算法
 * @author Dongguabai
 * @date 2018/11/2 10:17
 */
public class RandomLoadBanalce extends AbstractLoadBanance{

    @Override
    protected String doSelect(List<String> repos) {
        return repos.get(new Random().nextInt(repos.size()));
    }
}

随机改造负载最低优先

先梳理一下整个调用流程:

  1. Server 将自身信息(调用地址)注册到 ZK
  2. Client 从 ZK 中获取 Servers 信息
  3. 随机请求一个 Server

如果要改造成负载最低优先的负载均衡,那么 Server 需要定时将自身服务的情况上报给 ZK,Client 基于 ZK 中各个 Server 的服务情况选择相应的 Sever 进行调用。

这里简单点处理,Server 元数据直接放在 ZK 中。

首先定义 Invoker ,即每个服务执行器:

/**
 * @author dongguabai
 * @date 2023-09-22 13:59
 */
@NoArgsConstructor
@Getter
@Setter
@ToString
@EqualsAndHashCode(of = "address")
@AllArgsConstructor
public class Invoker {

    private String address;

    /**
     * 权重
     */
    private int weight = 10;

}

这里权重默认是 10,权重会根据服务的 CPU 情况进行调整:

    @Override
    public Invoker discover(String serviceName) {
        //获取/rpcNode/dgb.nospring.myrpc.demo.IHelloService下所有协议地址
        String nodePath = RegistryCenterConfig.NAMESPACE + "/" + serviceName;
        List<Invoker> invokers = new ArrayList<>();
        try {
            repos = curatorFramework.getChildren().forPath(nodePath);
            for (String child : repos) {
                String childPath = nodePath + "/" + child;
                byte[] data = curatorFramework.getData().forPath(childPath);
                String dataStr = new String(data, StandardCharsets.UTF_8);
                //CPU > 10,权重降低为1,否则为10
                invokers.add(new Invoker(child, Integer.valueOf(dataStr) > 10 ? 1 : 10));
            }
        } catch (Exception e) {
            throw new RuntimeException("服务发现获取子节点异常!", e);
        }
        //动态发现服务节点变化,需要注册监听
        registerWatcher(nodePath);
        //这里为了方便,直接使用随机负载
        LoadBalance loadBalance = new SectionWeightRandomLoadBalance();
        return loadBalance.selectHost(invokers);
    }

每个 Server 会定时将自身的 CPU 负载情况进行上报:

    private static final ScheduledExecutorService SCHEDULED_EXECUTOR = Executors.newSingleThreadScheduledExecutor();

    private void refreshMetadata(String addressPath) {
        int port = Integer.parseInt(addressPath.split(":")[1]);
        SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> {
            try {
                int processCpuLoad = getProcessCpuLoad();
                curatorFramework.setData().forPath(addressPath, String.valueOf(processCpuLoad).getBytes());
                log.info("[{}] refresh cpu : {}", port, processCpuLoad);
            } catch (Exception e) {
                log.error("refreshMetadata error.", e);
            }
        }, 5, 2, TimeUnit.SECONDS);

        //模拟
        highCpuUsage(port);
    }

    private static final OperatingSystemMXBean OPERATING_SYSTEM_MX_BEAN = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

    private static int getProcessCpuLoad() {
        //获取CPU Load
        double cpuLoad = OPERATING_SYSTEM_MX_BEAN.getProcessCpuLoad();
        return (int) (cpuLoad * 100);
    }

基于负载情况进行加权随机处理:

/**
 * @author dongguabai
 * @date 2023-09-22 14:20
 */
public class SectionWeightRandomLoadBalance extends RandomLoadBanalce {

    @Override
    protected Invoker doSelect(List<Invoker> invokers) {
        boolean averageWeight = true;
        int totalWeight = 0;
        for (int i = 0; i < invokers.size(); i++) {
            Invoker invoker = invokers.get(i);
            if (averageWeight && i > 0 && invoker.getWeight() != invokers.get(i - 1).getWeight()) {
                averageWeight = false;
            }
            totalWeight += invoker.getWeight();
        }
        if (averageWeight || totalWeight < 1) {
            return super.doSelect(invokers);
        }
        int index = new Random().nextInt(totalWeight);
        for (Invoker invoker : invokers) {
            if (index < invoker.getWeight()) {
                return invoker;
            }
            index -= invoker.getWeight();
        }
        return super.doSelect(invokers);
    }
}

端口号为 12345 的 Server 会有一个负载的变化,启动 3s 后 CPU 会逐步升高,持续 30s,然后逐步下降:

    public void highCpuUsage(int port) {
        //端口为12345的服务才进行模拟
        if (port != 12345) {
            return;
        }
        try {
            //延迟3s
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException ignored) {
        }
        log.info("...........start highCpuUsage");
        //执行20s
        Thread cpuThread = new Thread(() -> call(), "highCpuUsage-thread");
        cpuThread.start();
        try {
            cpuThread.join();
            log.info("...........end highCpuUsage");
        } catch (InterruptedException ignored) {
        }
    }

    private void call() {
        long startTime = System.currentTimeMillis();
        long duration = 30000;
        while (System.currentTimeMillis() - startTime < duration) {
            // 空的计算任务,消耗CPU资源
            double result = Math.random() * Math.random();
        }
    }

代码修改完成后使用 12345、12346、12347 三个端口号分别启动三个 Server,这是端口号为 12345 Server 的日志输出情况:

17:15:16.974 [main] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    服务注册成功:/rpcNode/blog.dongguabai.lb.example.server.IHelloService/127.0.0.1:12345
17:15:19.987 [main] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    ...........start highCpuUsage
17:15:21.993 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 0
17:15:24.001 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:26.007 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:28.015 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:30.024 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:32.031 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:34.039 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:36.046 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:38.055 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:40.063 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:42.067 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:44.074 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:46.081 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 12
17:15:48.088 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 10
17:15:49.989 [main] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    ...........end highCpuUsage
17:15:50.096 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 10
17:15:52.105 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 0
17:15:54.113 [pool-1-thread-1] INFO  b.dongguabai.lb.core.registry.RegistryCenterImpl -    [12345] refresh cpu : 0

可以看到在 17:15:24.001~17:15:46.081 期间 12345 Server 的 CPU Load 是大于 10 的。

看一下执行效果:

//开始执行
2023-9-22 17:15:19 12347
2023-9-22 17:15:20 12346
2023-9-22 17:15:21 12345
2023-9-22 17:15:22 12347
2023-9-22 17:15:23 12346
//12345 CPU 激增
2023-9-22 17:15:24 12347
2023-9-22 17:15:25 12346
2023-9-22 17:15:26 12347
2023-9-22 17:15:27 12347
2023-9-22 17:15:28 12346
2023-9-22 17:15:29 12347
2023-9-22 17:15:30 12347
2023-9-22 17:15:31 12346
2023-9-22 17:15:32 12347
2023-9-22 17:15:33 12347
2023-9-22 17:15:34 12346
2023-9-22 17:15:35 12346
2023-9-22 17:15:36 12346
2023-9-22 17:15:37 12347
2023-9-22 17:15:38 12346
2023-9-22 17:15:39 12346
2023-9-22 17:15:40 12346
2023-9-22 17:15:41 12347
2023-9-22 17:15:42 12346
2023-9-22 17:15:43 12346
2023-9-22 17:15:44 12346
2023-9-22 17:15:45 12347
2023-9-22 17:15:46 12347
2023-9-22 17:15:47 12347
2023-9-22 17:15:48 12345
2023-9-22 17:15:49 12347
2023-9-22 17:15:50 12345
//12345 CPU 恢复
2023-9-22 17:15:51 12347
2023-9-22 17:15:52 12345
2023-9-22 17:15:53 12346
2023-9-22 17:15:54 12347
2023-9-22 17:15:55 12347
2023-9-22 17:15:56 12347
2023-9-22 17:15:57 12347
2023-9-22 17:15:58 12345
2023-9-22 17:15:59 12346
2023-9-22 17:16:00 12347
2023-9-22 17:16:01 12345
2023-9-22 17:16:02 12345
2023-9-22 17:16:04 12347
2023-9-22 17:16:05 12347
2023-9-22 17:16:06 12346
2023-9-22 17:16:07 12345
2023-9-22 17:16:08 12345
2023-9-22 17:16:09 12346
2023-9-22 17:16:10 12345
2023-9-22 17:16:11 12346
2023-9-22 17:16:12 12347
2023-9-22 17:16:13 12346
2023-9-22 17:16:14 12346
2023-9-22 17:16:15 12346
2023-9-22 17:16:16 12346
2023-9-22 17:16:17 12345
2023-9-22 17:16:18 12347
2023-9-22 17:16:19 12346
2023-9-22 17:16:20 12346
2023-9-22 17:16:21 12346
2023-9-22 17:16:22 12345
2023-9-22 17:16:23 12346
2023-9-22 17:16:24 12345
2023-9-22 17:16:25 12346
2023-9-22 17:16:26 12345
2023-9-22 17:16:27 12346
2023-9-22 17:16:28 12347
2023-9-22 17:16:29 12345
2023-9-22 17:16:30 12345
2023-9-22 17:16:31 12347
2023-9-22 17:16:32 12347
2023-9-22 17:16:33 12347
2023-9-22 17:16:34 12347
2023-9-22 17:16:35 12345
2023-9-22 17:16:36 12346
2023-9-22 17:16:37 12347
2023-9-22 17:16:38 12346
2023-9-22 17:16:39 12346
2023-9-22 17:16:40 12345
2023-9-22 17:16:41 12345
2023-9-22 17:16:42 12345
2023-9-22 17:16:43 12347
2023-9-22 17:16:44 12347
2023-9-22 17:16:45 12345
2023-9-22 17:16:46 12347
2023-9-22 17:16:47 12347
2023-9-22 17:16:48 12347
2023-9-22 17:16:49 12345
2023-9-22 17:16:50 12346
2023-9-22 17:16:51 12346
2023-9-22 17:16:52 12346
2023-9-22 17:16:53 12345
2023-9-22 17:16:54 12346
2023-9-22 17:16:55 12345
2023-9-22 17:16:56 12345
2023-9-22 17:16:57 12345
2023-9-22 17:16:58 12346
2023-9-22 17:17:00 12345
2023-9-22 17:17:01 12347
2023-9-22 17:17:02 12347
2023-9-22 17:17:03 12345
2023-9-22 17:17:04 12345
2023-9-22 17:17:05 12347
2023-9-22 17:17:06 12347
2023-9-22 17:17:08 12345
2023-9-22 17:17:09 12346
2023-9-22 17:17:10 12347
2023-9-22 17:17:12 12347
2023-9-22 17:17:13 12346
2023-9-22 17:17:15 12346
2023-9-22 17:17:16 12347
2023-9-22 17:17:17 12346
2023-9-22 17:17:18 12346
2023-9-22 17:17:19 12347
2023-9-22 17:17:20 12346

这里将执行比例做成一个表格,便于查看:

Server Port12345高CPU Load期间执行次数1234CPU Load恢复后执行次数
12345228
123461231
123471331
总调用次数2790

当 Server 12345 的CPU负载高时,我们可以明显观察到其他服务的调用量明显减少。而当 Server 12345 的CPU负载逐渐恢复正常时,各个服务的调用量也逐步趋于均衡。至此,成功实现了负载最低优先的负载均衡策略。

总结

“负载最低优先” 的负载均衡策略在分布式系统中非常常见,目的是将负载较低的服务器优先分配请求,以确保资源的最佳利用。负载最低优先可以使用如最小连接数、CPU/IO 负载等。

但也要注意的是这种策略会极大增加系统的复杂度,这里引入《从零开始学架构》中的介绍:

负载最低优先算法基本上能够比较完美地解决轮询算法的缺点,因为采用这种算法后,负载均衡系统需要感知服务器当前的运行状态。当然,其代价是复杂度大幅上升。通俗来讲,轮询可能是 5 行代码就能实现的算法,而负载最低优先算法可能要 1000 行才能实现,甚至需要负载均衡系统和服务器都要开发代码。负载最低优先算法如果本身没有设计好,或者不适合业务的运行特点,算法本身就可能成为性能的瓶颈,或者引发很多莫名其妙的问题。所以负载最低优先算法虽然效果看起来很美好,但实际上真正应用的场景反而没有轮询(包括加权轮询)那么多。

References

  • 用 Java 代码实现负载均衡的五种常见算法
  • 手写实现RPC框架(带注册中心)
  • 《从零开始学架构》

欢迎关注公众号:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1032917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【喜讯】斯歌上榜:中国信通院《高质量数字化转型产品及服务全景图》

喜讯&#xff01;9月15号&#xff0c;上海斯歌旗下品牌“纳比云”凭借卓越的自研成果及社会影响力&#xff0c;在众多候选企业中脱颖而出&#xff0c;成功入选由中国信通院发布的2023《高质量数字化转型产品及服务全景图》&#xff08;技术开发领域&#xff09;。 以下为中国信…

项目经理的“四定、五起、六法”工作法

大家好&#xff0c;我是老原。 说来&#xff0c;我也工作十多年了&#xff0c;就像很多刚入门的项目经理一样&#xff0c;一开始不知道怎么预设风险、沟通和团队协调不够好&#xff1b; 有的人就可以规避风险&#xff0c;人际往来和团队管理都信手拈来&#xff0c;整个项目顺…

【问题记录】解决“命令行终端”和“Git Bash”操作本地Git仓库时出现 中文乱码 的问题!

环境 Windows 11 家庭中文版git version 2.41.0.windows.1 问题情况 在使用 “命令行终端” 和 “Git Bash” 在本地Git仓库敲击命令时&#xff0c;对中文名称文件显示一连串的数字&#xff0c;如下所示&#xff1a;这种情况通常是由于字符编码设置不正确所引起的 解决办法 设置…

uniapp项目实践总结(二十)URLScheme 协议知识总结

导语&#xff1a;在日常开发过程中&#xff0c;我们经常可以碰到很多的调起某个应用&#xff0c;打开唤醒某个 APP&#xff0c;链式启动 App 等场景&#xff0c;背后就涉及到了 URLScheme 协议的相关知识&#xff0c;下面就简单介绍一下。 目录 简介常见 URL Scheme跳转方法实…

Vosviewer的安装与使用

Vosviewer的安装与使用 1 安装2 使用参考&#xff1a; 关于vosviewer我就不过多介绍了。 vosviewer与citespace有什么区别?在这里可以引用一下知乎的文章简要说明一下&#xff1a; 1.操作难易VOSviewer很简单&#xff0c;在官网下载的时候会附带一个英文手册&#xff0c;稍微…

YOLOv5、YOLOv8改进:Decoupled Head解耦头

目录 1.Decoupled Head介绍 2.Yolov5加入Decoupled_Detect 2.1 DecoupledHead加入common.py中&#xff1a; 2.2 Decoupled_Detect加入yolo.py中&#xff1a; 2.3修改yolov5s_decoupled.yaml 1.Decoupled Head介绍 Decoupled Head是一种图像分割任务中常用的网络结构&#…

中科驭数DPU芯片K2斩获2023年“中国芯”优秀技术创新产品奖

2023年9月20日&#xff0c;中科驭数DPU芯片K2在2023年琴珠澳集成电路产业促进峰会暨第十八届“中国芯”颁奖仪式上荣获“中国芯”优秀技术创新产品奖。 “中国芯”集成电路优秀产品榜单是由国家工信部门指导、中国电子信息产业发展研究院举办的行业权威评选活动。自2006年以来…

oracle截取字符串前几位用substr函数如何操作?

随着社会的发展&#xff0c;it行业越来越受到人们的追捧&#xff0c;oracle软件作为一款数据库开发软件&#xff0c;更是受到it人士的钦懒&#xff0c;它是为数据存储和管理构建出的数据库管理系统&#xff0c;主要应用于商业智能管理、通信业务、工作流程管理等方面&#xff0…

springboot整合MeiliSearch轻量级搜索引擎

一、Meilisearch与Easy Search点击进入官网了解&#xff0c;本文主要从小微型公司业务出发&#xff0c;选择meilisearch来作为项目的全文搜索引擎&#xff0c;还可以当成来mongodb来使用。 二、starter封装 1、项目结构展示 2、引入依赖包 <dependencies><dependenc…

【操作系统笔记十四】科普:POSIX 是什么

注&#xff1a;本文转载自该文章posix是什么都不知道&#xff0c;还好意思说你懂Linux&#xff1f; Linux开发者越来越多&#xff0c;但是仍然有很多人整不明白POSIX是什么。本文就带着大家来了解一下到底什么是POSIX&#xff0c;了解他的历史和重要性。 一、什么是 POSIX&…

windows使用小技巧之windows照片查看器无法显示此图片

碰到过好几次了&#xff0c;以前没有理会&#xff0c;今天特意去查了一下解决方法&#xff0c;不然确实不太方便。 1、打开“颜色管理”-“高级”&#xff1a; 2、将“设备配置文件”选择为“Agfa&#xff1a;Swop Standard” 3、关闭&#xff0c;重新打开图片&#xff0c;好…

火花塞工作原理

1.红旗H9轿车2023款发布 2023年元旦过后&#xff0c;红旗汽车在人民大会堂举办了红旗H9的新车发布会&#xff0c;一汽红旗全新的H9豪华轿车终于出炉了全套的配置参数&#xff0c;红旗H9的车身长度达到5137mm&#xff0c;宽度1904mm&#xff0c;轴距3060mm&#xff0c;总高则控…

分享一个基于Python的电子产品销售系统可视化销量统计java版本相同(源码+调试+开题+lw)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&…

windows 部署 mindspore GPU 开发环境

基础环境 windows 环境&#xff1a; Windows 11 版本&#xff1a;22H2操作系统版本&#xff1a;22621.2283 wsl2&#xff1a; 1.2.5.0 Docker Desktop&#xff1a; Docker Desktop 4.23.0 CUDA driver for WSL 版本&#xff1a; 535.104.07 宿主机上的 nvidia 环境如下所示&a…

【李沐深度学习笔记】矩阵计算(4)

课程地址和说明 线性代数实现p4 本系列文章是我学习李沐老师深度学习系列课程的学习笔记&#xff0c;可能会对李沐老师上课没讲到的进行补充。 本节是第四篇&#xff0c;由于CSDN限制&#xff0c;只能被迫拆分 矩阵计算 矩阵的导数运算 向量对向量求导的基本运算规则 已知…

如何实现线程池之间的数据透传 ?

如何实现线程池之间的数据透传 &#xff1f; 引言transmittable-thread-local概览capture如何 capture如何保存捕获的数据 save 和 replayrestore 小结 引言 当我们涉及到数据的全链路透传场景时&#xff0c;通常会将数据存储在线程的本地缓存中&#xff0c;如: 用户认证信息透…

灾备系统中的多线程传输功能

多线程传输是指同时使用多个线程进行文件传输&#xff0c;使多个数据包可以同时传输&#xff0c;从而充分利用网络带宽的最大值&#xff0c;提高传输速度。 正常的IE页面文件下载与上传都只有一个线程&#xff0c;有些软件可以实现多线程文件传输&#xff0c;就好像在传输文件…

JDK21你可以不用,新特性还是要了解的

大家好&#xff0c;我是风筝 今年6月份的时候&#xff0c;写过一篇JDK21引入协程&#xff0c;再也不用为并发而头疼了&#xff0c;那时候只是预览版&#xff0c;终于&#xff0c;前两天&#xff08;2023年9月19日&#xff09;发布了 JDK21 正式版。 老早就在 YouTube 上订阅了…

在电脑上怎么分类管理笔记?支持分类整理的电脑云笔记软件

对于大多数上班族而言&#xff0c;在使用电脑办公时&#xff0c;随手记录工作笔记是一个非常常见的场景。无论是会议纪要、工作总结还是项目计划&#xff0c;记录下每一次思考和灵感是提高工作效率的关键。然而&#xff0c;随着时间的推移&#xff0c;电脑上记录的笔记内容逐渐…

OceanMind海睿思入选弯弓研究院《2023中国营销技术生态图谱8.0》

近日&#xff0c;由国内MarTech领域知名机构 弯弓研究院 主办的第五届营销数字化大会暨营销科技MarTech交易展在广州成功召开。 本次大会发布了《2023中国营销技术生态图谱8.0版》 (以下简称“弯弓图谱8.0”)&#xff0c;中新赛克海睿思 凭借成熟的技术实力成功入选弯弓图谱8.0…