Kafka安装部署+go整合

news2024/9/27 21:21:20

1、Kafka的安装

1、下载与安装Kafka

Kafka官网https://Kafka.apache.org/downloads

在这里插入图片描述

所以这里推荐的版本是 : https://archive.apache.org/dist/kafka/2.7.2/kafka_2.12-2.7.2.tgz

将下载下来的安装包直接解压到一个路径下即可完成Kafka的安装,这里统一将Kafka安装到/usr/local目录下

基本操作过程如下:

mkdir -p /www/kuangstudy
cd /www/kuangstudy
wget https://archive.apache.org/dist/kafka/2.7.2/kafka_2.12-2.7.2.tgz
tar -zxvf kafka_2.12-2.7.2.tgz -C /usr/local/
mv /usr/local/kafka_2.12-2.7.2 /usr/local/kafka
#新建存放日志和数据的文件夹
mkdir /usr/local/kafka/logs

这里我们将Kafka安装到了/usr/local目录下。

2、配置Kafka

这里将Kafka安装到/usr/local目录下

因此,Kafka的主配置文件为/usr/local/Kafka/config/server.properties,这里以节点Kafkazk1为例,重点介绍一些常用配置项的含义:

broker.id=1
listeners=PLAINTEXT://127.0.0.1:9092
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/usr/local/Kafka/logs
num.partitions=6
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
zookeeper.connect=localhost:2181
#不是集群,所以可以写成localhost
#zookeeper.connect=127.0.0.1:2181,10.0.0.7:2181,10.0.0.8:2181
zookeeper.connection.timeout.ms=18000
group.initial.rebalance.delay.ms=0
auto.create.topics.enable=true
delete.topic.enable=true

每个配置项含义如下:

  • broker.id:每一个broker在集群中的唯一表示,要求是正数。当该服务器的IP地址发生改变时,broker.id没有变化,则不会影响consumers的消息情况。

  • listeners:设置Kafka的监听地址与端口,可以将监听地址设置为主机名或IP地址,这里将监听地址设置为IP地址。

  • log.dirs:这个参数用于配置Kafka保存数据的位置,Kafka中所有的消息都会存在这个目录下。可以通过逗号来指定多个路径, Kafka会根据最少被使用的原则选择目录分配新的parition。需要注意的是,Kafka在分配parition的时候选择的规则不是按照磁盘的空间大小来定的,而是根据分配的 parition的个数多小而定。

  • num.partitions:这个参数用于设置新创建的topic有多少个分区,可以根据消费者实际情况配置,配置过小会影响消费性能。这里配置6个。

  • log.retention.hours:这个参数用于配置Kafka中消息保存的时间,还支持log.retention.minutes和 log.retention.ms配置项。这三个参数都会控制删除过期数据的时间,推荐使用log.retention.ms。如果多个同时设置,那么会选择最小的那个。

  • log.segment.bytes:配置partition中每个segment数据文件的大小,默认是1GB,超过这个大小会自动创建一个新的segment file。

  • zookeeper.connect
    

    :这个参数用于指定zookeeper所在的地址,它存储了broker的元信息。 这个值可以通过逗号设置多个值,每个值的格式均为:hostname:port/path,每个部分的含义如下:

    • hostname:表示zookeeper服务器的主机名或者IP地址,这里设置为IP地址。
    • port: 表示是zookeeper服务器监听连接的端口号。
    • /path:表示Kafka在zookeeper上的根目录。如果不设置,会使用根目录。
  • auto.create.topics.enable:这个参数用于设置是否自动创建topic,如果请求一个topic时发现还没有创建, Kafka会在broker上自动创建一个topic,如果需要严格的控制topic的创建,那么可以设置auto.create.topics.enable为false,禁止自动创建topic。

  • delete.topic.enable:在0.8.2版本之后,Kafka提供了删除topic的功能,但是默认并不会直接将topic数据物理删除。如果要从物理上删除(即删除topic后,数据文件也会一同删除),就需要设置此配置项为true。

3、添加环境变量

$ vim /etc/profile
export kafka_HOME=/usr/local/kafka
export PATH=$PATH:$kafka_HOME/bin
#生效
$ source /etc/profile

zookeeper服务的启动

cd /usr/local/kafka/bin
# 占用启动
./zookeeper-server-start.sh /usr/local/kafka/config/zookeeper.properties &
# 后台启动
nohup ./zookeeper-server-start.sh /usr/local/kafka/config/zookeeper.properties &

4、Kafka启动脚本

$ vim /usr/lib/systemd/system/kafka.service

[Unit]
Description=Apache kafka server (broker)
After=network.target  zookeeper.service

[Service]
Type=simple
User=root
Group=root
ExecStart=/usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties
ExecStop=/usr/local/kafka/bin/kafka-server-stop.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target

systemctl daemon-reload

5、启动Kafka

在启动Kafka集群前,需要确保ZooKeeper集群已经正常启动。接着,依次在Kafka各个节点上执行如下命令即可:

$ cd /usr/local/kafka
$ nohup bin/kafka-server-start.sh config/server.properties &

# 或者

$ systemctl start kafka
$ jps
21840 kafka
15593 Jps
15789 QuorumPeerMain

这里将Kafka放到后台运行,启动后,会在启动Kafka的当前目录下生成一个nohup.out文件,可通过此文件查看Kafka的启动和运行状态。通过jps指令,可以看到有个Kafka标识,这是Kafka进程成功启动的标志。

6、测试Kafka基本命令操作

kefka提供了多个命令用于查看、创建、修改、删除topic信息,也可以通过命令测试如何生产消息、消费消息等,这些命令位于Kafka安装目录的bin目录下,这里是/usr/local/Kafka/bin。

登录任意一台Kafka集群节点,切换到此目录下,即可进行命令操作。

下面列举Kafka的一些常用命令的使用方法。
(1)显示topic列表

#kafka-topics.sh  --zookeeper 127.0.0.1:2181,10.0.0.7:2181,10.0.0.8:2181 --list
$ kafka-topics.sh  --zookeeper 127.0.0.1:2181 --list
topic123

(2)创建一个topic,并指定topic属性(副本数、分区数等)

#kafka-topics.sh --create --zookeeper 127.0.0.1:2181,10.0.0.7:2181,10.0.0.8:2181 --replication-factor 1 --partitions 3 --topic topic123 
$ kafka-topics.sh --create --zookeeper 127.0.0.1:2181 --replication-factor 1 --partitions 3 --topic topic123
Created topic topic123.
#--replication-factor表示指定副本的个数

(3)查看某个topic的状态

#kafka-topics.sh --describe --zookeeper 127.0.0.1:2181,10.0.0.7:2181,10.0.0.8:2181 --topic topic123
$ kafka-topics.sh --describe --zookeeper 127.0.0.1:2181 --topic topic123
Topic: topic123	PartitionCount: 3	ReplicationFactor: 1	Configs: 
	Topic: topic123	Partition: 0	Leader: 1	Replicas: 1	Isr: 1
	Topic: topic123	Partition: 1	Leader: 1	Replicas: 1	Isr: 1
	Topic: topic123	Partition: 2	Leader: 1	Replicas: 1	Isr: 1

(4)生产消息 阻塞状态

#kafka-console-producer.sh --broker-list 127.0.0.1:9092,10.0.0.7:9092,10.0.0.8:9092 --topic topic123
$ kafka-console-producer.sh --broker-list 127.0.0.1:9092 --topic topic123

(5)消费消息 阻塞状态

#kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092,10.0.0.7:9092,10.0.0.8:9092 --topic topic123
$ kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic topic123
#从头开始消费消息
#Kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic topic123 --from-beginning
$ kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092,10.0.0.7:9092,10.0.0.8:9092 --topic topic123 --from-beginning

(6)删除topic

#kafka-topics.sh --delete --zookeeper 127.0.0.1:2181,10.0.0.7:2181,10.0.0.8:2181 --topic topic123
$ kafka-topics.sh --delete --zookeeper 127.0.0.1:2181 --topic topic_

2、GO整合Kafka实现消息发送和订阅

4.1 消息生产代码示例

package main

import (
	"fmt"
	"github.com/IBM/sarama"
)

func main() {
	// 配置生产者信息
	conf := sarama.NewConfig()
	conf.Producer.RequiredAcks = sarama.WaitForAll // 生产者等待所有分区副本成功提交消息
	conf.Producer.Return.Successes = true          // 成功消息写入返回
	client, err := sarama.NewSyncProducer([]string{"47.115.230.36:9092"}, conf)
	if nil != err {
		fmt.Println("create Kafka sync producer failed", err)
		return
	}
	defer client.Close()

	msg := &sarama.ProducerMessage{
		Topic: "topic123",                          // 指定消息主题
		Value: sarama.StringEncoder("hello world"), // 构造消息
	}

	// 发送消息
	_, _, err = client.SendMessage(msg)
	if nil != err {
		fmt.Println("send message to Kafka failed", err)
		return
	}
	fmt.Println("send message success")
}

4.2 消息消费代码示例

package main

import (
	"fmt"
	"github.com/IBM/sarama"
)

/**
 * @desc 生产者
 * @author feige
 * @date 2023-11-15
 * @version 1.0
 */
func main() {
	// 创建一个消费者
	consumer, err := sarama.NewConsumer([]string{"47.115.230.36:9092"}, nil)
	if err != nil {
		fmt.Println("消费者kafka连接服务失败,失败的原因:", err)
		return
	}
	// 从topic123这个主题去获取消息
	partitions, err := consumer.Partitions("topic123")
	if err != nil {
		fmt.Println("主题获取失败,失败的原因:", err)
		return
	}
	fmt.Println(partitions)

	// 开始遍历分区中的消息,开始进行消费
	for _, partition := range partitions {
		pc, err := consumer.ConsumePartition("topic123", int32(partition), sarama.OffsetNewest)
		if err != nil {
			fmt.Println("分区数据获取失败,失败的原因:", err)
			return
		}
		defer pc.AsyncClose()
		// 开始异步获取消息
		go func(sarama.PartitionConsumer) {
			for message := range pc.Messages() {
				fmt.Printf("当前消费的分区是:%d,offset:%d,key:%v,消息的内容是:%v", message.Partition,
					message.Offset, message.Key, string(message.Value))
				fmt.Println("")
			}
		}(pc)
	}

	// 阻塞让消费一直处于监听状态
	select {}
}

4.3 创建主题代码示例

package main

import (
	"fmt"

	"github.com/Shopify/sarama"
)

func CreateTopic(addrs []string, topic string) bool {
	config := sarama.NewConfig()
	config.Version = sarama.V2_0_0_0         // 设置客户端版本
	config.Admin.Timeout = 3 * time.Second // 设置Admin请求超时时间

	admin, err := sarama.NewClusterAdmin(addrs, config)
	if err!= nil {
		return false
	}
	defer admin.Close()

	err = admin.CreateTopic(topic, &sarama.TopicDetail{NumPartitions: 3, ReplicationFactor: 2}, false)
	if err == nil {
		fmt.Println("success create topic:", topic)
	} else {
		fmt.Println("failed create topic:", topic)
	}

	return err == nil
}

4.4 性能测试结果

Kafka目前已经成为云计算领域中的“事件驱动”架构、微服务架构中的主要消息队列,随着越来越多的公司和组织开始采用Kafka作为基础消息队列技术,越来越多的性能测试报告也陆续出来。笔者提前做了一轮性能测试,并发现它的消费性能比其它消息队列还要好,甚至更好些。下面是测试结果:

测试环境:
  • 操作系统:Ubuntu 16.04
  • CPU:Intel® Xeon® Gold 6148 CPU @ 2.40GHz
  • 内存:128G DDR4 ECC
  • Kafka集群:3节点,每节点配置6个CPU、32G内存、SSD
  • 测试用例:生产者每秒钟发送2万条消息,消费者每秒钟消费100条消息。
测试结果:
Kafka消费者
每秒消费100条消息,平均耗时:67毫秒
每秒消费1000条消息,平均耗时:6.7毫秒
RabbitMQ消费者
每秒消费100条消息,平均耗时:1038毫秒
每秒消费1000条消息,平均耗时:10.38毫秒

3、参考

github.com/Shopify/sarama
github.com/bsm/sarama-cluster

生产者

import (
	"fmt"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/Shopify/sarama"
	"github.com/golang/glog"
)

//同步生产者
func Produce() {
	config := sarama.NewConfig()
	config.Producer.RequiredAcks = sarama.WaitForAll          //赋值为-1:这意味着producer在follower副本确认接收到数据后才算一次发送完成。
	config.Producer.Partitioner = sarama.NewRandomPartitioner //写到随机分区中,默认设置8个分区
	config.Producer.Return.Successes = true
	msg := &sarama.ProducerMessage{}
	msg.Topic = `test0`
	msg.Value = sarama.StringEncoder("Hello World!")
	client, err := sarama.NewSyncProducer([]string{"Kafka_master:9092"}, config)
	if err != nil {
		fmt.Println("producer close err, ", err)
		return
	}
	defer client.Close()
	pid, offset, err := client.SendMessage(msg)

	if err != nil {
		fmt.Println("send message failed, ", err)
		return
	}
	fmt.Printf("分区ID:%v, offset:%v \n", pid, offset)
}


//异步生产者
func AsyncProducer() {
	var topics = "test0"
	config := sarama.NewConfig()
	config.Producer.Return.Successes = true //必须有这个选项
	config.Producer.Timeout = 5 * time.Second
	p, err := sarama.NewAsyncProducer(strings.Split("Kafka_master:9092", ","), config)
	defer p.Close()
	if err != nil {
		return
	}
	//这个部分一定要写,不然通道会被堵塞
	go func(p sarama.AsyncProducer) {
		errors := p.Errors()
		success := p.Successes()
		for {
			select {
			case err := <-errors:
				if err != nil {
					glog.Errorln(err)
				}
			case <-success:
			}
		}
	}(p)
	for {
		v := "async: " + strconv.Itoa(rand.New(rand.NewSource(time.Now().UnixNano())).Intn(10000))
		fmt.Fprintln(os.Stdout, v)
		msg := &sarama.ProducerMessage{
			Topic: topics,
			Value: sarama.ByteEncoder(v),
		}
		p.Input() <- msg
		time.Sleep(time.Second * 1)
	}

}

消费者

package consumer

import (
	"fmt"
	"strings"
	"sync"
	"time"

	"github.com/Shopify/sarama"
	cluster "github.com/bsm/sarama-cluster"
	"github.com/golang/glog"
)

//单个消费者
func Consumer() {
	var wg sync.WaitGroup
	consumer, err := sarama.NewConsumer([]string{"Kafka_master:9092"}, nil)
	if err != nil {
		fmt.Println("Failed to start consumer: %s", err)
		return
	}
	partitionList, err := consumer.Partitions("test0") //获得该topic所有的分区
	if err != nil {
		fmt.Println("Failed to get the list of partition:, ", err)
		return
	}

	for partition := range partitionList {
		pc, err := consumer.ConsumePartition("test0", int32(partition), sarama.OffsetNewest)
		if err != nil {
			fmt.Println("Failed to start consumer for partition %d: %s\n", partition, err)
			return
		}
		wg.Add(1)
		go func(sarama.PartitionConsumer) { //为每个分区开一个go协程去取值
			for msg := range pc.Messages() { //阻塞直到有值发送过来,然后再继续等待
				fmt.Printf("Partition:%d, Offset:%d, key:%s, value:%s\n", msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
			}
			defer pc.AsyncClose()
			wg.Done()
		}(pc)
	}
	wg.Wait()
}

//消费组
func ConsumerGroup() {
	groupID := "test-consumer-group"
	config := cluster.NewConfig()
	config.Group.Return.Notifications = true
	config.Consumer.Offsets.CommitInterval = 1 * time.Second
	config.Consumer.Offsets.Initial = sarama.OffsetNewest //初始从最新的offset开始

	c, err := cluster.NewConsumer(strings.Split("Kafka_master:9092", ","), groupID, strings.Split("test0", ","), config)
	if err != nil {
		glog.Errorf("Failed open consumer: %v", err)
		return
	}
	defer c.Close()
	go func(c *cluster.Consumer) {
		errors := c.Errors()
		noti := c.Notifications()
		for {
			select {
			case err := <-errors:
				glog.Errorln(err)
			case <-noti:
			}
		}
	}(c)
	for msg := range c.Messages() {
		fmt.Printf("Partition:%d, Offset:%d, key:%s, value:%s\n", msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
		c.MarkOffset(msg, "") //MarkOffset 并不是实时写入Kafka,有可能在程序crash时丢掉未提交的offset
	}
}

主函数

package main

import (
	"strom-huang-go/go_Kafka/consumer"
)

func main() {
	// produce.AsyncProducer()
	consumer.Consumer()
}


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

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

相关文章

4种防止模态框弹出时页面滚动的方法

1. Overflow:hidden — 经典方法 overflow:hidden CSS 属性是一种久经考验的防止滚动的方法。只需将一个类&#xff08;例如&#xff0c;no-scroll&#xff09;添加到 <body> 标签&#xff0c;并将其链接到带有 overflow:hidden 的 CSS 规则。 .no-scroll {overflow: h…

地表最强?免费!AI画图模型:Stable Diffusion 3 来了!

前言 Stability AI终于推出了备受期待的Stable Diffusion 3 API。经过几个月技术报告的酝酿&#xff0c;现在用户终于可以实际体验这个模型啦。 虽然完全开源的SD3模型仍在开发中&#xff0c;Stability AI已承诺对普通用户免费开放。用户现在可以通过Fireworks AI平台访问SD3 …

电脑出现错误vcomp140.dll是什么情况?vcomp140.dll丢失怎样修复?

很多小伙伴在使用电脑时会突然收到提示vcomp140.dll文件丢失导致应用程序无法打开&#xff0c;不能正常运行。这是怎么一回事呢&#xff1f;其实就是vcomp140.dll文件被破会坏导致文件被丢失。具体的解决办法其实很简单一起来看看吧。 关于vcomp140.dll文件丢失的详细分析 在计…

我在高职教STM32——EXTI之外部按键中断(2)

大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正是如此,才有了借助CSDN平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思设计的教学课件分…

小顶堆实现查找前 K 个高频元素

小顶堆&#xff08;Min-Heap&#xff09;通常用于实现优先队列。在小顶堆中&#xff0c;根节点的值是最小的&#xff0c;因此通过从堆中移除根节点&#xff0c;你可以高效地获取当前优先级最高&#xff08;即值最小&#xff09;的元素。 优先队列的特点&#xff1a; 允许高效…

2024年【化工自动化控制仪表】考试及化工自动化控制仪表考试内容

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 化工自动化控制仪表考试参考答案及化工自动化控制仪表考试试题解析是安全生产模拟考试一点通题库老师及化工自动化控制仪表操作证已考过的学员汇总&#xff0c;相对有效帮助化工自动化控制仪表考试内容学员顺利通过考…

Struts2框架漏洞(附漏洞修复方法)

Apache Struts 2 最初被称为 WebWork 2&#xff0c;它是一个简洁的、可扩展的框架&#xff0c;可用于创建企业级Java web应用程序。设计这个框架是为了从构建、部署、到应用程序维护方面来简化整个开发周期。 Struts 2在2007年7月23日发布的第一个Struts 2漏洞S2-001。 …

dbeaver设置字体大小

1、【窗口】-【首选项】 2、【外观】-【颜色-字体】-【Dbeaver Fonts】-【Monospace font】 双击或者右边编辑都可以打开设置

【Linux】—— 僵尸进程、孤儿进程

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;Linux跬步积累 &#x1f48c;其他专栏&#xff1a; &#x1f534; 每日一题 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0…

计网学习(一)——计算机网络概述

一、计算机网络概述 Internet翻译&#xff1a;因特网&#xff08;未得到普及&#xff09;>互联网互联网基本特点&#xff1a;连通性和资源共享计算机网络&#xff1a;有若干结点和连接这些节点的链路组成网络把许多计算机连接在一起&#xff0c;而互连网则把许多网络通过路…

数学建模--智能算法之免疫算法

目录 基本原理 应用实例 代码示例 总结 免疫算法在免疫系统研究中的应用和进展是什么&#xff1f; 如何量化评估免疫算法在不同优化问题中的性能和效率&#xff1f; 免疫算法与其他智能优化算法&#xff08;如遗传算法、粒子群优化&#xff09;相比有哪些独特优势和局限性…

“tcp控制协议”的理解

情景解释&#xff1a; 1.过程&#xff1a; 在用户进行网络间通信时&#xff0c;不管是客户端还是服务端&#xff0c;都会有两个缓冲区——发送缓冲区和接受缓冲区。 通过4个缓冲区进行数据交流。 用户通过write()将数据发送到他的发送缓冲区中&#xff0c;再传输到服务端的…

遥感类SCI推荐合集,潜力大+易投,版面有限!

关注GZH【欧亚科睿学术】&#xff0c;第一时间了解期刊最新动态&#xff01; &#x1f525; &#x1f525; &#x1f525; &#x1f525; 遥感类SCI期刊合集 1. 农林科学类&#xff08;中科院1区TOP&#xff0c;领域高权威&#xff09; 【期刊简介】IF&#xff1a;4.0-5.0&am…

Linux源码阅读笔记18-插入模型及删除模块操作

基础知识 模块是一种向Linux内核添加设备驱动程序、文件系统及其他组件的有效方法&#xff0c;不需要编译新内核 优点 通过使用模块&#xff0c;内核发布者能够预先编译大量驱动程序&#xff0c;而不会致使内核映像的尺寸发生膨胀。内核开发者可以将实验性的代码打包到模块中&a…

达梦数据库的系统视图v$large_mem_sqls

达梦数据库的系统视图v$large_mem_sqls 达梦数据库的V$LARGE_MEM_SQLS视图提供了最近1000条使用大内存的SQL语句信息。一条SQL语句如果使用的内存值超过ini参数LARGE_MEM_THRESHOLD&#xff0c;就认为使用了大内存。这个视图帮助用户监控和分析哪些SQL语句在执行时占用了大量内…

【python】Python中位运算算法详细解析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

torch量化接口深度解读-eager模式-fx模式

一、定义 接口总结量化模式解读 二、实现 接口总结 1. PyTorch提供了三种不同的量化模式&#xff1a;Eager模式量化、FX图模式量化&#xff08;维护&#xff09;和PyTorch 2导出量化。 2. Eager Mode Quantization是一个测试版功能。用户需要进行融合&#xff0c;并手动指定量…

2024年AWS云服务器选择哪个区域最好?

在选择2024年AWS云服务器区域时&#xff0c;您需要根据您的业务需求、目标用户群体的位置、数据合规性要求、延迟需求以及成本预算等因素综合考虑。以下是九河云针对不同需求的建议&#xff1a; 北美区域 优势&#xff1a;北美区域&#xff0c;尤其是弗吉尼亚北部&#xff0c…

工业和信息化部明确四方面举措优化信息通信行业营商环境

根据工业和信息化部6日发布的消息&#xff0c;该部门已正式下发《关于创新信息通信行业管理 优化营商环境的意见》。 此意见旨在通过四项主要措施优化行业管理制度和手段&#xff0c;以促进信息通信行业的高质量发展。 这些措施包括&#xff1a;持续改进高效、开放、统一的准…

vue项目部署在子路径中前端配置

vue.config.JS router/index.js或者是man.js