主頁 > 軟體工程 > RabbitMQ簡介、安裝、基本特性API--Java測驗

RabbitMQ簡介、安裝、基本特性API--Java測驗

2021-04-01 21:22:35 軟體工程

新的閱讀體驗地址:http://www.zhouhong.icu/post/141

本篇文章所有的代碼:https://github.com/Tom-shushu/Distributed-system-learning-notes/tree/master/rabbitmq-api-demo

一、初識RabbitMQ

是一個開源的訊息代理和佇列服務器,用來通過普通協議在完全不同的應用之間共享資料,RabbitMQ是使用Erlang語言來撰寫的,并且RabbitMQ是基于AMQP協議的,
AMQP協議Advanced Message Queuing Protocol(高級訊息佇列協議)
 定義:具有現代特征的二進制協議,是一個提供統一訊息服務的應用層標準高級訊息佇列協議, 是應用層協議的一個開放標準,為面向訊息中間件設計,
AMQP專業術語:
  • Server:又稱broker,接受客戶端的鏈接,實作AMQP物體服務
  • Connection:連接,應用程式與broker的網路連接
  • Channel:網路信道,幾乎所有的操作都在channel中進行,Channel是進行訊息讀寫的通道,客戶端可以建立多個channel,每個channel代表一個會話任務,
  • Message:訊息,服務器與應用程式之間傳送的資料,由Properties和Body組成.Properties可以對訊息進行修飾,必須訊息的優先級、延遲等高級特性;Body則是訊息體內容,
  • virtualhost: 虛擬地址,用于進行邏輯隔離,最上層的訊息路由,一個virtual host里面可以有若干個Exchange和Queue,同一個Virtual Host 里面不能有相同名稱的Exchange 或 Queue,
  • Exchange:交換機,接收訊息,根據路由鍵轉單訊息到系結佇列
  • Binding:  Exchange和Queue之間的虛擬鏈接,binding中可以包換routing key
  • Routing key: 一個路由規則,虛擬機可用它來確定如何路由一個特定訊息,(如負載均衡)
RabbitMQ整體架構

Exchange和佇列是多對多關系,實際操作一般為1個exchange對多個佇列,為避免設計過于復雜.

二、單機版快速安裝

網不好的朋友也直接使用我下載下來的安裝包(下載有時候會卡主):

鏈接:https://pan.baidu.com/s/1diapYC19UlDy4G-4lgZWHA
提取碼:jf5r
復制這段內容后打開百度網盤手機App,操作更方便哦

  • 1、首先在Linux上進行一些軟體的準備作業

yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz
  • 2、下載安裝必要的軟體
  • 備用地址:
    • https://www.rabbitmq.com/install-rpm.html#downloads
    • https://dl.bintray.com/rabbitmq-erlang/rpm/erlang/

wget https://github.com/rabbitmq/erlang-rpm/releases/download/v23.0.4/erlang-23.0.4-1.el7.x86_64.rpm
wget http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.5/rabbitmq-server-3.8.5-1.el7.noarch.rpm
  • 3、安裝服務命令
rpm -ivh erlang-23.0.4-1.el7.x86_64.rpm
rpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpm
rpm -ivh rabbitmq-server-3.8.5-1.el7.noarch.rpm?
  • 4、啟動

啟動服務
systemctl start rabbitmq-server
查看是否啟動
lsof -i:5672
  • 5、啟動、安裝web管理插件(管控臺)

rabbitmq-plugins enable rabbitmq_management
  • 6、查看管理埠有沒有啟動

lsof -i:15672
或者:
netstat -tnlp | grep 15672
  • 7、添加用戶

#添加用戶 用戶名 admin 密碼 admin web管理工具可用此用戶登錄
sudo rabbitmqctl add_user admin admin
#設定用戶角色 管理員
sudo rabbitmqctl set_user_tags admin administrator
#設定用戶權限(接受來自所有Host的所有操作)
sudo rabbitmqctl set_permissions -p / admin "." "." ".*"  
#查看用戶權限
sudo rabbitmqctl list_user_permissions admin
  • 重新啟動

systemctl start rabbitmq-server
rabbitmq-plugins enable rabbitmq_management
  • 訪問:http://192.168.2.121:15672/ 使用 admin 登錄

  • 代碼測驗
  1. 引入依賴
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>3.6.5</version>
        </dependency>

        2.發送端:

package com.zhouhong.rabbitmq.api.helloworld;
import java.util.HashMap;
import java.util.Map;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender {
    public static void main(String[] args) throws Exception {
        //    1 創建ConnectionFactory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.2.121");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        connectionFactory.setVirtualHost("/");
        //    2 創建Connection
        Connection connection = connectionFactory.newConnection();
        //    3 創建Channel
        Channel channel = connection.createChannel();  
        //    4 宣告
        String queueName = "test001";  
        //    引數: queue名字,是否持久化,獨占的queue(僅供此連接),不使用時是否自動洗掉, 其他引數
        channel.queueDeclare(queueName, false, false, false, null);
        Map<String, Object> headers = new HashMap<String, Object>();
        AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
        .deliveryMode(2)
        .contentEncoding("UTF-8")
        .headers(headers).build();
        for(int i = 0; i < 5;i++) {
            String msg = "Hello World RabbitMQ " + i;
            channel.basicPublish("", queueName , props , msg.getBytes());             
        }
    }
}

    3.接收端

package com.zhouhong.rabbitmq.api.helloworld;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.QueueingConsumer.Delivery;
public class Receiver {
    public static void main(String[] args) throws Exception {        
        ConnectionFactory connectionFactory = new ConnectionFactory() ;          
        connectionFactory.setHost("192.168.2.121");
        connectionFactory.setPort(5672);
        connectionFactory.setPassword("admin");
        connectionFactory.setUsername("admin");
        connectionFactory.setVirtualHost("/");        
        connectionFactory.setAutomaticRecoveryEnabled(true);
        connectionFactory.setNetworkRecoveryInterval(3000);
        Connection connection = connectionFactory.newConnection();        
        Channel channel = connection.createChannel();          
        String queueName = "test001";  
        //    durable 是否持久化訊息
        channel.queueDeclare(queueName, false, false, false, null);  
        QueueingConsumer consumer = new QueueingConsumer(channel);
        //    引數:佇列名稱、是否自動ACK、Consumer
        channel.basicConsume(queueName, true, consumer);  
        //    回圈獲取訊息  
        while(true){  
            //    獲取訊息,如果沒有訊息,這一步將會一直阻塞  
            Delivery delivery = consumer.nextDelivery();  
            String msg = new String(delivery.getBody());    
            System.out.println("收到訊息:" + msg);  
        } 
    }
}

    4.結果(先啟動接收端進行監控,再啟動發送端)

收到訊息:Hello World RabbitMQ 0
收到訊息:Hello World RabbitMQ 1
收到訊息:Hello World RabbitMQ 2
收到訊息:Hello World RabbitMQ 3
收到訊息:Hello World RabbitMQ 4

三、RabbitMQ----交換機

  1. Name:交換機名稱,
  2. Type:交換機型別 direct、topic、fanout、headers,
  3. Durability:是否持久化,ture為持久化,
  4. Auto Delete :當最后一個系結道Exchange上的佇列洗掉后,自動洗掉該Exchange,
  5. Internal:當前Exchange是否用于RabbitMQ內部使用,默認為False,
  6. Arguments:擴展引數,用于擴展AMQP協議自制定化使用,
  7. DirectExchange的訊息被轉發道RouteKey中指定的Queue,
交換機-----Direct exchange
Direct模式可以使用RabbitMQ自帶的Exchange:default Exchange,所以不需要將Exchange進行任何系結操作,訊息傳遞時,RouteKey必須完全匹配才會被佇列接收,否則該訊息會被拋棄,

代碼:
  • 發送端
package com.zhouhong.rabbitmq.api.exchange.direct;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender4DirectExchange {
    public static void main(String[] args) throws Exception {
        //1 創建ConnectionFactory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.2.121");
        connectionFactory.setPort(5672);
        connectionFactory.setPassword("admin");
        connectionFactory.setUsername("admin");
        connectionFactory.setVirtualHost("/");
        //2 創建Connection
        Connection connection = connectionFactory.newConnection();
        //3 創建Channel
        Channel channel = connection.createChannel();  
        //4 宣告
        String exchangeName = "test_direct_exchange";
        //必須要和接收端 routingKey 一一對應
        String routingKey = "test_direct_routingKey";
        //5 發送
        String msg = "Hello World RabbitMQ 4  Direct Exchange Message ... ";
        channel.basicPublish(exchangeName, routingKey , null , msg.getBytes());                 
    }
}
  •  接收端
package com.zhouhong.rabbitmq.api.exchange.direct;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.QueueingConsumer.Delivery;
public class Receiver4DirectExchange {    
    public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory() ;          
        connectionFactory.setHost("192.168.2.121");
        connectionFactory.setPort(5672);
        connectionFactory.setPassword("admin");
        connectionFactory.setUsername("admin");
        connectionFactory.setVirtualHost("/");    
        connectionFactory.setAutomaticRecoveryEnabled(true);
        connectionFactory.setNetworkRecoveryInterval(3000);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();  
        //4 宣告
        String exchangeName = "test_direct_exchange";
        String exchangeType = "direct";
        String queueName = "test_direct_queue";
        String routingKey = "test_direct_routingKey";
        channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName, exchangeName, routingKey);
        //durable 是否持久化訊息
        QueueingConsumer consumer = new QueueingConsumer(channel);
        //引數:佇列名稱、是否自動ACK、Consumer
        channel.basicConsume(queueName, true, consumer);  
        //回圈獲取訊息  
        while(true){  
            //獲取訊息,如果沒有訊息,這一步將會一直阻塞  
            Delivery delivery = consumer.nextDelivery();  
            String msg = new String(delivery.getBody());    
            System.out.println("收到訊息:" + msg);  
        } 
    }
}
交換機-----topic exchange
exchange 將Routekey和某個topic進行一個模糊匹配,發送給對應佇列、可以用通配符進行匹配

比如下面例子
代碼:
  • 接收端
package com.zhouhong.rabbitmq.api.exchange.topic;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.QueueingConsumer.Delivery;
public class Receiver4TopicExchange1 {
    public static void main(String[] args) throws Exception {        
        ConnectionFactory connectionFactory = new ConnectionFactory() ;         
        connectionFactory.setHost("192.168.2.121");
        connectionFactory.setPort(5672);
        connectionFactory.setPassword("admin");
        connectionFactory.setUsername("admin");
        connectionFactory.setVirtualHost("/");        
        connectionFactory.setAutomaticRecoveryEnabled(true);
        connectionFactory.setNetworkRecoveryInterval(3000);
        Connection connection = connectionFactory.newConnection();       
        Channel channel = connection.createChannel();  
        //4 宣告
        String exchangeName = "test_topic_exchange";
        String exchangeType = "topic";
        String queueName = "test_topic_queue";
        // 只能匹配一個 例如:user.txt、user.py都可以,但是user.txt.py 不行
        //String routingKey = "user.*";
        // user.txt、user.py 、user.txt.py 都可以匹配到
        String routingKey = "user.#";
        channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName, exchangeName, routingKey);        
        //durable 是否持久化訊息
        QueueingConsumer consumer = new QueueingConsumer(channel);
        //    引數:佇列名稱、是否自動ACK、Consumer
        channel.basicConsume(queueName, true, consumer);
        System.err.println("consumer1 start.. ");
        //    回圈獲取訊息  
        while(true){  
            //    獲取訊息,如果沒有訊息,這一步將會一直阻塞  
            Delivery delivery = consumer.nextDelivery();  
            String msg = new String(delivery.getBody());    
            System.out.println("收到訊息:" + msg + ", RoutingKey: " + delivery.getEnvelope().getRoutingKey());  
        } 
    }
}
  • 發送端
package com.zhouhong.rabbitmq.api.exchange.topic;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender4TopicExchange {    
    public static void main(String[] args) throws Exception {        
        //1 創建ConnectionFactory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.2.121");
        connectionFactory.setPort(5672);
        connectionFactory.setPassword("admin");
        connectionFactory.setUsername("admin");
        connectionFactory.setVirtualHost("/");        
        //2 創建Connection
        Connection connection = connectionFactory.newConnection();
        //3 創建Channel
        Channel channel = connection.createChannel();  
        //4 宣告
        String exchangeName = "test_topic_exchange";
        String routingKey1 = "user.save";
        String routingKey2 = "user.update";
        String routingKey3 = "user.delete.abc";
        //5 發送        
        String msg = "Hello World RabbitMQ 4 Topic Exchange Message ...";
        channel.basicPublish(exchangeName, routingKey1 , null , msg.getBytes()); 
        channel.basicPublish(exchangeName, routingKey2 , null , msg.getBytes());     
        channel.basicPublish(exchangeName, routingKey3 , null , msg.getBytes()); 
        channel.close();  
        connection.close();  
    }    
}
交換機-----Fanout exchange 廣播模式
1.不處理路由鍵,只需要簡單的將佇列系結到交換機上, 2.發送到交換機的訊息都會被轉發到與該交換機系結的所有佇列上, 3.Fanout交換機轉發訊息是最快的,
代碼:見示例文章開始GitHub地址

四、RabbitMQ高級特性

1、訊息如何保障 100% 的投遞成功
生產端的可靠性投遞的標志:
1、訊息成功發出 2、mq節點成功接收 3、發送端MQ節點確認應答 4、完善的訊息補償機制 解決:訊息資訊落庫,對訊息狀態進行打標 冪等性     1、 select count(1) from t_order where id = 唯一id(或)指紋碼     2、唯一id或指紋碼機制,利用資料庫主鍵去重 2、Confirm
第一步:再channel上開啟確認模式:channel.confirmSelect(); 第二步:再channel上添加監聽:addConfirmListener,監聽成功和失敗的回傳結果,根據具體的結果對訊息進行重新發送、或記錄日期等后續處理!
3、return訊息機制
ReturnListener用于處理不可路由的訊息 我們的訊息生產者,通過指定一個Exchage和Routingkey,把訊息送達某一個佇列中去,然后我們的消費者監聽佇列,進行消費處理操作,如果沒有合適的佇列,則會由returnListener進行接受, Mandatory:如果為true,則監聽器會接收到路由不可達的訊息,然后進行后續處理,如果為false,那么broker端自動洗掉該訊息,
4、消費端ACK與重回佇列
消費端ACK:
  • 在作業的時候一般不會選擇自動ack
  • 消費端的手工ack分為兩種ACK和NACK
  • 消費端進行消費的時候,如果由于業務例外我們可以進行日志的記錄,然后進行補償,這種建議回復NACK,不要重回佇列
  • 如果由于服務器宕機等嚴重問題,那我們就需要手工進行ACK保障消費端消費成功
消費端的重回佇列
  • 是為了對沒有處理成功的訊息,把訊息重新會投遞給broker,
  • 重回佇列,會回到佇列的尾部
  • 也會造成一條訊息一直重復投遞,死回圈了
  • 在實際應用中,都會關閉重回佇列,也就是設定為false
5、TTL佇列和訊息
TTL: time to live的縮寫,也就是生存時間,
  • RabbitMQ 支持訊息過期時間,在訊息發送時可以進行指定
  • RabbitMQ支持佇列過期時間,從訊息入佇列開始計算,只要超過了佇列的超時間時間配置,那么訊息會自動的清除
死佇列: DLX,Dead-Letter-Exchange
  • 利用DLX,當訊息在一個佇列中變成死信(dead message)之后,它能被重新publish到另一個Exchange,這個Exchange就是DLX.
訊息變成死信的幾種情況
  • 訊息被拒絕 并且requeue = false
  • 訊息TTL過期
  • 佇列達到最大長度
DLX也是一個正常的Exchange,實際上是一個屬性控制
  • 當佇列中有死信時,RabbitMQ就會自動的將這個訊息重新發布到設定的Exchange上,進而被路由到另一個佇列.
  • 可以監聽這個佇列中訊息做相應的處理,這個特性可以彌補rabbitMQ3.0以前的immediate引數功能,
  • 在正常佇列上添加引數:arguments.put("x-dead-letter-exchange","dlx.exchange");這樣訊息過期、requeue、佇列達到最大長度時,就可以直接路由到死信佇列,
 

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/270911.html

標籤:其他

上一篇:專案經理VS產品經理VS架構師

下一篇:那些在GitHub能提高你的編程技能的專案

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more