当前位置: 首页 > news >正文

常州网站制作哪家好北京 工业网站建设公司

常州网站制作哪家好,北京 工业网站建设公司,四川省住房建设厅网站打不开,未成年在线观看视频播放免费Go操作各大消息队列教程 1 RabbitMQ 1.1 概念 ①基本名词 当前市面上mq的产品很多#xff0c;比如RabbitMQ、Kafka、ActiveMQ、ZeroMQ和阿里巴巴捐献给Apache的RocketMQ。甚至连redis这种NoSQL都支持MQ的功能。 Broker#xff1a;表示消息队列服务实体Virtual Host#x…Go操作各大消息队列教程 1 RabbitMQ 1.1 概念 ①基本名词 当前市面上mq的产品很多比如RabbitMQ、Kafka、ActiveMQ、ZeroMQ和阿里巴巴捐献给Apache的RocketMQ。甚至连redis这种NoSQL都支持MQ的功能。 Broker表示消息队列服务实体Virtual Host虚拟主机。标识一批交换机、消息队列和相关对象。vhost是AMQP概念的基础必须在链接时指定RabbitMQ默认的vhost是 /。 AMQP(Advanced Message Queuing Protocol)高级消息队列协议 Exchange交换器用来接收生产者发送的消息并将这些消息路由给服务器中的队列。Queue消息队列用来保存消息直到发送给消费者。它是消息的容器也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面等待消费者连接到这个队列将其取走。 ②常见模式 1. simple简单模式 消息的消费者(consumer) 监听(while) 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失) 2. worker工作模式 多个消费者从一个队列中争抢消息 (隐患,高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize,与同步锁的性能不一样) 保证一条消息只能被一个消费者使用)应用场景:红包;大项目中的资源调度(任务分配系统不需知道哪一个任务执行系统在空闲,直接将任务扔到消息队列中,空闲的系统自动争抢) 3. publish/subscribe发布订阅共享资源 消费者订阅消息然后从订阅的队列中获取消息进行消费。 X代表交换机rabbitMQ内部组件,erlang 消息产生者是代码完成,代码的执行效率不高,消息产生者将消息放入交换机,交换机发布订阅把消息发送到所有消息队列中,对应消息队列的消费者拿到消息进行消费相关场景:邮件群发,群聊天,广播(广告) 4. routing路由模式 交换机根据路由规则将消息路由到不同的队列中消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息; 5. topic主题模式路由模式的一种 星号井号代表通配符星号代表多个单词,井号代表一个单词路由功能添加模糊匹配消息产生者产生消息,把消息交给交换机交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费 1.2 搭建docker方式 ①拉取镜像 # 拉取镜像 docker pull rabbitmq:3.7-management②创建并启动容器 # 创建并运行容器 docker run -d --name myrabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.7-management #5672是项目中连接rabbitmq的端口我这里映射的是567215672是rabbitmq的web管理界面端口我映射为15672# 输入网址http://ip:15672即可进入rabbitmq的web管理页面,账户密码guest / guest③web界面创建用户和virtual host 下面为了我们后续的操作首先我们新建一个Virtual Host并且给他分配一个用户名用来隔离数据根据自己需要自行创建 新增virtual host 新增用户 点击新建好的用户设置其host 最终效果 1.3 代码操作 ①RabbitMQ struct包含创建、消费、生产消息 package RabbitMQimport (fmtgithub.com/streadway/amqplog )//amqp:// 账号 密码地址:端口号/vhost const MQURL amqp://ziyi:ziyi10.253.50.145:5672/ziyitype RabbitMQ struct {//连接conn *amqp.Connection//管道channel *amqp.Channel//队列名称QueueName string//交换机Exchange string//key Simple模式 几乎用不到Key string//连接信息Mqurl string }//创建RabbitMQ结构体实例 func NewRabbitMQ(queuename string, exchange string, key string) *RabbitMQ {rabbitmq : RabbitMQ{QueueName: queuename, Exchange: exchange, Key: key, Mqurl: MQURL}var err error//创建rabbitmq连接rabbitmq.conn, err amqp.Dial(rabbitmq.Mqurl)rabbitmq.failOnErr(err, 创建连接错误)rabbitmq.channel, err rabbitmq.conn.Channel()rabbitmq.failOnErr(err, 获取channel失败)return rabbitmq }//断开channel和connection func (r *RabbitMQ) Destory() {r.channel.Close()r.conn.Close() }//错误处理函数 func (r *RabbitMQ) failOnErr(err error, message string) {if err ! nil {log.Fatalf(%s:%s, message, err)panic(fmt.Sprintf(%s:%s, message, err))} }//简单模式step1。创建简单模式下RabbitMQ实例 func NewRabbitMQSimple(queueName string) *RabbitMQ {return NewRabbitMQ(queueName, , ) }//订阅模式创建rabbitmq实例 func NewRabbitMQPubSub(exchangeName string) *RabbitMQ {//创建rabbitmq实例rabbitmq : NewRabbitMQ(, exchangeName, )var err error//获取connectionrabbitmq.conn, err amqp.Dial(rabbitmq.Mqurl)rabbitmq.failOnErr(err, failed to connecct rabbitmq!)//获取channelrabbitmq.channel, err rabbitmq.conn.Channel()rabbitmq.failOnErr(err, failed to open a channel!)return rabbitmq }//订阅模式生成 func (r *RabbitMQ) PublishPub(message string) {//尝试创建交换机不存在创建err : r.channel.ExchangeDeclare(//交换机名称r.Exchange,//交换机类型 广播类型fanout,//是否持久化true,//是否字段删除false,//true表示这个exchange不可以被client用来推送消息仅用来进行exchange和exchange之间的绑定false,//是否阻塞 true表示要等待服务器的响应false,nil,)r.failOnErr(err, failed to declare an exchange)//2 发送消息err r.channel.Publish(r.Exchange,,false,false,amqp.Publishing{//类型ContentType: text/plain,//消息Body: []byte(message),}) }//订阅模式消费端代码 func (r *RabbitMQ) RecieveSub() {//尝试创建交换机不存在创建err : r.channel.ExchangeDeclare(//交换机名称r.Exchange,//交换机类型 广播类型fanout,//是否持久化true,//是否字段删除false,//true表示这个exchange不可以被client用来推送消息仅用来进行exchange和exchange之间的绑定false,//是否阻塞 true表示要等待服务器的响应false,nil,)r.failOnErr(err, failed to declare an exchange)//2试探性创建队列创建队列q, err : r.channel.QueueDeclare(, //随机生产队列名称false,false,true,false,nil,)r.failOnErr(err, Failed to declare a queue)//绑定队列到exchange中err r.channel.QueueBind(q.Name,//在pub/sub模式下这里的key要为空,r.Exchange,false,nil,)//消费消息message, err : r.channel.Consume(q.Name,,true,false,false,false,nil,)forever : make(chan bool)go func() {for d : range message {log.Printf(Received a message:%s,, d.Body)}}()fmt.Println(退出请按 CtrlC)-forever }//话题模式 创建RabbitMQ实例 func NewRabbitMQTopic(exchagne string, routingKey string) *RabbitMQ {//创建rabbitmq实例rabbitmq : NewRabbitMQ(, exchagne, routingKey)var err errorrabbitmq.conn, err amqp.Dial(rabbitmq.Mqurl)rabbitmq.failOnErr(err, failed to connect rabbingmq!)rabbitmq.channel, err rabbitmq.conn.Channel()rabbitmq.failOnErr(err, failed to open a channel)return rabbitmq }//话题模式发送信息 func (r *RabbitMQ) PublishTopic(message string) {//尝试创建交换机不存在创建err : r.channel.ExchangeDeclare(//交换机名称r.Exchange,//交换机类型 话题模式topic,//是否持久化true,//是否字段删除false,//true表示这个exchange不可以被client用来推送消息仅用来进行exchange和exchange之间的绑定false,//是否阻塞 true表示要等待服务器的响应false,nil,)r.failOnErr(err, topic failed to declare an exchange)//2发送信息err r.channel.Publish(r.Exchange,//要设置r.Key,false,false,amqp.Publishing{//类型ContentType: text/plain,//消息Body: []byte(message),}) }//话题模式接收信息 //要注意key //其中* 用于匹配一个单词#用于匹配多个单词可以是零个 //匹配 表示匹配imooc.* 表示匹配imooc.hello,但是imooc.hello.one需要用imooc.#才能匹配到 func (r *RabbitMQ) RecieveTopic() {//尝试创建交换机不存在创建err : r.channel.ExchangeDeclare(//交换机名称r.Exchange,//交换机类型 话题模式topic,//是否持久化true,//是否字段删除false,//true表示这个exchange不可以被client用来推送消息仅用来进行exchange和exchange之间的绑定false,//是否阻塞 true表示要等待服务器的响应false,nil,)r.failOnErr(err, failed to declare an exchange)//2试探性创建队列创建队列q, err : r.channel.QueueDeclare(, //随机生产队列名称false,false,true,false,nil,)r.failOnErr(err, Failed to declare a queue)//绑定队列到exchange中err r.channel.QueueBind(q.Name,//在pub/sub模式下这里的key要为空r.Key,r.Exchange,false,nil,)//消费消息message, err : r.channel.Consume(q.Name,,true,false,false,false,nil,)forever : make(chan bool)go func() {for d : range message {log.Printf(Received a message:%s,, d.Body)}}()fmt.Println(退出请按 CtrlC)-forever }//路由模式 创建RabbitMQ实例 func NewRabbitMQRouting(exchagne string, routingKey string) *RabbitMQ {//创建rabbitmq实例rabbitmq : NewRabbitMQ(, exchagne, routingKey)var err errorrabbitmq.conn, err amqp.Dial(rabbitmq.Mqurl)rabbitmq.failOnErr(err, failed to connect rabbingmq!)rabbitmq.channel, err rabbitmq.conn.Channel()rabbitmq.failOnErr(err, failed to open a channel)return rabbitmq }//路由模式发送信息 func (r *RabbitMQ) PublishRouting(message string) {//尝试创建交换机不存在创建err : r.channel.ExchangeDeclare(//交换机名称r.Exchange,//交换机类型 广播类型direct,//是否持久化true,//是否字段删除false,//true表示这个exchange不可以被client用来推送消息仅用来进行exchange和exchange之间的绑定false,//是否阻塞 true表示要等待服务器的响应false,nil,)r.failOnErr(err, failed to declare an exchange)//发送信息err r.channel.Publish(r.Exchange,//要设置r.Key,false,false,amqp.Publishing{//类型ContentType: text/plain,//消息Body: []byte(message),}) }//路由模式接收信息 func (r *RabbitMQ) RecieveRouting() {//尝试创建交换机不存在创建err : r.channel.ExchangeDeclare(//交换机名称r.Exchange,//交换机类型 广播类型direct,//是否持久化true,//是否字段删除false,//true表示这个exchange不可以被client用来推送消息仅用来进行exchange和exchange之间的绑定false,//是否阻塞 true表示要等待服务器的响应false,nil,)r.failOnErr(err, failed to declare an exchange)//2试探性创建队列创建队列q, err : r.channel.QueueDeclare(, //随机生产队列名称false,false,true,false,nil,)r.failOnErr(err, Failed to declare a queue)//绑定队列到exchange中err r.channel.QueueBind(q.Name,//在pub/sub模式下这里的key要为空r.Key,r.Exchange,false,nil,)//消费消息message, err : r.channel.Consume(q.Name,,true,false,false,false,nil,)forever : make(chan bool)go func() {for d : range message {log.Printf(Received a message:%s,, d.Body)}}()fmt.Println(退出请按 CtrlC)-forever }//简单模式Step:2、简单模式下生产代码 func (r *RabbitMQ) PublishSimple(message string) {//1、申请队列如果队列存在就跳过不存在创建//优点保证队列存在消息能发送到队列中_, err : r.channel.QueueDeclare(//队列名称r.QueueName,//是否持久化false,//是否为自动删除 当最后一个消费者断开连接之后是否把消息从队列中删除false,//是否具有排他性 true表示自己可见 其他用户不能访问false,//是否阻塞 true表示要等待服务器的响应false,//额外数据nil,)if err ! nil {fmt.Println(err)}//2.发送消息到队列中r.channel.Publish(//默认的Exchange交换机是default,类型是direct直接类型r.Exchange,//要赋值的队列名称r.QueueName,//如果为true根据exchange类型和routkey规则如果无法找到符合条件的队列那么会把发送的消息返回给发送者false,//如果为true,当exchange发送消息到队列后发现队列上没有绑定消费者则会把消息还给发送者false,//消息amqp.Publishing{//类型ContentType: text/plain,//消息Body: []byte(message),}) }func (r *RabbitMQ) ConsumeSimple() {//1、申请队列如果队列存在就跳过不存在创建//优点保证队列存在消息能发送到队列中_, err : r.channel.QueueDeclare(//队列名称r.QueueName,//是否持久化false,//是否为自动删除 当最后一个消费者断开连接之后是否把消息从队列中删除false,//是否具有排他性false,//是否阻塞false,//额外数据nil,)if err ! nil {fmt.Println(err)}//接收消息msgs, err : r.channel.Consume(r.QueueName,//用来区分多个消费者,//是否自动应答true,//是否具有排他性false,//如果设置为true,表示不能同一个connection中发送的消息传递给这个connection中的消费者false,//队列是否阻塞false,nil,)if err ! nil {fmt.Println(err)}forever : make(chan bool)//启用协程处理go func() {for d : range msgs {//实现我们要处理的逻辑函数log.Printf(Received a message:%s, d.Body)//fmt.Println(d.Body)}}()log.Printf(【*】warting for messages, To exit press CCTRALC)-forever }func (r *RabbitMQ) ConsumeWorker(consumerName string) {//1、申请队列如果队列存在就跳过不存在创建//优点保证队列存在消息能发送到队列中_, err : r.channel.QueueDeclare(//队列名称r.QueueName,//是否持久化false,//是否为自动删除 当最后一个消费者断开连接之后是否把消息从队列中删除false,//是否具有排他性false,//是否阻塞false,//额外数据nil,)if err ! nil {fmt.Println(err)}//接收消息msgs, err : r.channel.Consume(r.QueueName,//用来区分多个消费者consumerName,//是否自动应答true,//是否具有排他性false,//如果设置为true,表示不能同一个connection中发送的消息传递给这个connection中的消费者false,//队列是否阻塞false,nil,)if err ! nil {fmt.Println(err)}forever : make(chan bool)//启用协程处理go func() {for d : range msgs {//实现我们要处理的逻辑函数log.Printf(%s Received a message:%s, consumerName, d.Body)//fmt.Println(d.Body)}}()log.Printf(【*】warting for messages, To exit press CCTRALC)-forever }②测试代码 1. simple简单模式 consumer.go func main() {//消费者rabbitmq : RabbitMQ.NewRabbitMQSimple(ziyiSimple)rabbitmq.ConsumeSimple() }producer.go func main() {//Simple模式 生产者rabbitmq : RabbitMQ.NewRabbitMQSimple(ziyiSimple)for i : 0; i 5; i {time.Sleep(time.Second * 2)rabbitmq.PublishSimple(fmt.Sprintf(%s %d, hello, i))} }2. worker模式 consumer.go func main() {/*worker模式无非就是多个消费者去同一个队列中消费消息*///消费者1rabbitmq1 : RabbitMQ.NewRabbitMQSimple(ziyiWorker)go rabbitmq1.ConsumeWorker(consumer1)//消费者2rabbitmq2 : RabbitMQ.NewRabbitMQSimple(ziyiWorker)rabbitmq2.ConsumeWorker(consumer2) }producer.go func main() {//Worker模式 生产者rabbitmq : RabbitMQ.NewRabbitMQSimple(ziyiWorker)for i : 0; i 100; i {//time.Sleep(time.Second * 2)rabbitmq.PublishSimple(fmt.Sprintf(%s %d, hello, i))} }3. publish/subscribe模式 consumer.go: func main() {//消费者rabbitmq : RabbitMQ.NewRabbitMQPubSub( newProduct)rabbitmq.RecieveSub() }producer.go func main() {//订阅模式发送者rabbitmq : RabbitMQ.NewRabbitMQPubSub( newProduct)for i : 0; i 20; i {rabbitmq.PublishPub(订阅模式生产第 strconv.Itoa(i) 条数据)fmt.Println(i)time.Sleep(1 * time.Second)} }4. router模式 consumer.go func main() {//消费者rabbitmq : RabbitMQ.NewRabbitMQRouting(exZi, imooc_one)rabbitmq.RecieveRouting() }producer.go func main() {//路由模式生产者imoocOne : RabbitMQ.NewRabbitMQRouting(exZi, imooc_one)imoocTwo : RabbitMQ.NewRabbitMQRouting(exZi, imooc_two)for i : 0; i 10; i {imoocOne.PublishRouting(hello imooc one! strconv.Itoa(i))imoocTwo.PublishRouting(hello imooc two! strconv.Itoa(i))time.Sleep(1 * time.Second)fmt.Println(i)} }5. topic模式 consumer.go func main() {/*星号井号代表通配符星号代表多个单词,井号代表一个单词路由功能添加模糊匹配消息产生者产生消息,把消息交给交换机交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费*///Topic消费者//rabbitmq : RabbitMQ.NewRabbitMQTopic(exImoocTopic, #) //匹配所有的key:topic88和topic99rabbitmq : RabbitMQ.NewRabbitMQTopic(exImoocTopic, imooc.topic88.three) //只匹配topic88的rabbitmq.RecieveTopic() }producer.go func main() {//Topic模式生产者imoocOne : RabbitMQ.NewRabbitMQTopic(exImoocTopic, imooc.topic88.three)imoocTwo : RabbitMQ.NewRabbitMQTopic(exImoocTopic, imooc.topic99.four)for i : 0; i 10; i {imoocOne.PublishTopic(hello imooc topic three! strconv.Itoa(i))imoocTwo.PublishTopic(hello imooc topic four! strconv.Itoa(i))time.Sleep(1 * time.Second)fmt.Println(i)} }2 Kafka 2.1 基本概念 Kafka是分布式的其所有的构件borker(server服务端集群)、producer(消息生产)、consumer(消息消费者)都可以是分布式的。 producer给broker发送数据这些消息会存到kafka server里然后consumer再向kafka server发起请求去消费这些数据。 kafka server在这个过程中像是一个帮你保管数据的中间商。所以kafka服务器也可以叫做brokerbroker直接翻译可以是中间人或者经纪人的意思。 在消息的生产时可以使用一个标识topic来区分且可以进行分区每一个分区都是一个顺序的、不可变的消息队列 并且可以持续的添加。 同时为发布和订阅提供高吞吐量。据了解Kafka每秒可以生产约25万消息50 MB每秒处理55万消息110 MB。 消息被处理的状态是在consumer端维护而不是由server端维护。当失败时能自动平衡 参考https://blog.csdn.net/lingfy1234/article/details/122900348 应用场景 监控消息队列流处理日志聚合持久性日志 基础概念 topic话题brokerkafka服务集群已发布的消息保存在一组服务器中称之为kafka集群。集群中的每一个服务器都是一个代理brokerpartition分区topic物理上的分组message消息每个producer可以向一个topic主题发布一些消息 1.⽣产者从Kafka集群获取分区leader信息 2.⽣产者将消息发送给leader 3.leader将消息写入本地磁盘 4.follower从leader拉取消息数据 5.follower将消息写入本地磁盘后向leader发送ACK 6.leader收到所有的follower的ACK之后向生产者发送ACK 2.2 常见模式 ①点对点模式:火车站出租车抢客 发送者将消息发送到消息队列中消费者去消费如果消费者有多个他们会竞争地消费也就是说对于某一条消息只有一个消费者能“抢“到它。类似于火车站门口的出租车抢客的场景。 ②发布订阅模式组间无竞争组内有竞争 消费者订阅对应的topic主题只有订阅了对应topic消费者的才会接收到消息。 例如 牛奶有很多种光明牛奶希望牛奶等只有你订阅了光明牛奶送奶工才会把光明牛奶送到对应位置你也才会有机会消费这个牛奶 注意为了提高消费者的消费能力kafka中引入了消费者组的概念。相当于是不同消费者组之间因为订阅的topic不同不会有竞争关系。但是消费者组内是有竞争关系。 例如 成都、厦门的出租车司机分别组成各自的消费者组。成都的出租车司机只拉成都的人厦门的只拉厦门的人。因此他们两个消费者组不是竞争关系成都市内的出租车司机之间是竞争关系。消费者组内是竞争关系 2.3 docker-compose部署 vim docker-compose.ymlversion: 3 services:zookeeper:image: confluentinc/cp-zookeeper:6.2.0ports:- 2181:2181environment:ZOOKEEPER_CLIENT_PORT: 2181ZOOKEEPER_TICK_TIME: 2000kafka:image: confluentinc/cp-kafka:6.2.0ports:- 9092:9092environment:KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181#KAFKA_ADVERTISED_LISTENERS后面改为自己本地宿主机的ip例如我本地mac的ip为192.168.0.101KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.0.101:9092KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1depends_on:- zookeeper# 进入到docker-compose.yml所在目录执行下面命令 docker-compose up -d # 查看部署结果,状态为up表明部署成功 docker-compose ps 2.4 代码操作 # 1. 创建对应topic docker-compose exec kafka kafka-topics --create --topic test-topic --partitions 1 --replication-factor 1 --bootstrap-server 192.168.0.101:9092# 2. 查看topic列表 docker-compose exec kafka kafka-topics --list --zookeeper zookeeper:2181①producer.go package mainimport (fmtgithub.com/IBM/sarama )// 基于sarama第三方库开发的kafka clientfunc main() {config : sarama.NewConfig()config.Producer.RequiredAcks sarama.WaitForAll // 发送完数据需要leader和follow都确认config.Producer.Partitioner sarama.NewRandomPartitioner // 新选出一个partitionconfig.Producer.Return.Successes true // 成功交付的消息将在success channel返回// 构造一个消息msg : sarama.ProducerMessage{}msg.Topic web_logmsg.Value sarama.StringEncoder(this is a test log)// 连接kafkaclient, err : sarama.NewSyncProducer([]string{localhost:9092}, config)if err ! nil {fmt.Println(producer closed, err:, err)return}defer client.Close()// 发送消息pid, offset, err : client.SendMessage(msg)if err ! nil {fmt.Println(send msg failed, err:, err)return}fmt.Printf(pid:%v offset:%v\n, pid, offset) }②consumer.go package mainimport (fmtgithub.com/IBM/sarama )// kafka consumerfunc main() {consumer, err : sarama.NewConsumer([]string{localhost:9092}, nil)if err ! nil {fmt.Printf(fail to start consumer, err:%v\n, err)return}partitionList, err : consumer.Partitions(web_log) // 根据topic取到所有的分区if err ! nil {fmt.Printf(fail to get list of partition:err%v\n, err)return}fmt.Println(partitionList)for partition : range partitionList { // 遍历所有的分区// 针对每个分区创建一个对应的分区消费者pc, err : consumer.ConsumePartition(web_log, int32(partition), sarama.OffsetNewest)if err ! nil {fmt.Printf(failed to start consumer for partition %d,err:%v\n, partition, err)return}defer pc.AsyncClose()// 异步从每个分区消费信息go func(sarama.PartitionConsumer) {for msg : range pc.Messages() {fmt.Printf(Partition:%d Offset:%d Key:%v Value:%v, msg.Partition, msg.Offset, msg.Key, string(msg.Value))}}(pc)}//演示时使用select {} }③运行效果
http://www.hkea.cn/news/14263452/

相关文章:

  • 做平面设计都在那个网站找免费素材?免费网站app哪个好
  • 大连网站制作流程承包网站开发
  • 南宁做网站seo怎么建立一个好公司网站
  • 50个单页面网站设计欣赏(2)网页直接玩的传奇
  • 洛阳企业网站建设北仑网站制作
  • 手机网站打不开wordpress局域网无法访问
  • 网站推广服务费会计分录怎么做网页设计与网站建设简答题
  • 网站备案时间广州越秀区重点场所
  • 网站开发合同付款比例wordpress logo 尺寸
  • 安徽城乡建设网站电脑做微信推送的网站
  • 铜陵高端网站建设查看网站是否备案
  • 淘宝客优惠券网站建设加盟官网海南海口网站开发公司
  • 做生意的网站久久人才招聘网
  • 博物馆网站做的最好的frontpage做视频网站
  • 网站可以分为哪些类型上海建设部门网站
  • 移动云服务器租用南宁百度seo排名优化
  • 百度搜索关键词数据杭州seook优屏网络
  • 合作行业网站建设新浪微博做wordpress图床
  • 镇江教育云平台网站建设下列属于网页制作平台的是
  • 房地产网页设计网站建设高端建站平台设计风格出众
  • 广州购物网站建设雍熙网站建设
  • ps做全屏网站画布要多大wordpress 4.7
  • 网站制作计划书模板网站建设编辑叫什么岗位
  • 洛阳霞光高端定制网站建设建设搜索引擎友好的网站
  • 金融 网站 模板code wordpress
  • 上海酒店团购网站建设wordpress 分段循环
  • 贵金属如何用网站开发客户重庆网站运营公司
  • 重庆新闻发布会直播seo和sem的区别与联系
  • 网站解析后显示在建设中wordpress oracle
  • 深圳网站建设优化服务wordpress蜘蛛爬虫记录