主頁 > 軟體設計 > 2021-09-23 基于ffmpeg+nginx+rtsp的http-flv點播方案-推流失敗問題分析

2021-09-23 基于ffmpeg+nginx+rtsp的http-flv點播方案-推流失敗問題分析

2021-09-24 09:27:01 軟體設計

專案場景:

使用ffmpeg拉取rtsp服務器的碼流,并且推rtmp流到nginx,web前端使用flv碼流進行點播;
拉流以及推流使用的是ffmpeg原生介面;
點播服務器使用是NGINX,并集成了http-flv模塊(可以參考我的其他檔案,)


問題描述:

ffmpeg打開rtsp的url,從in_stream的碼流中,復制所需要的h264編碼資訊;然后 寫入對應的rtmp流(out_stream)中,結果發現寫入函式av_interleaved_write_frame一直例外,無法寫入?并且錯誤資訊為“ Broke Pipe"?
        AVStream *in_stream = ifmt_ctx->streams[videoindex];
        AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
       ......
        //復制AVCodecContext的設定(Copy the settings of AVCodecContext)
        ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
       ......
       //緊接著呼叫打開、寫入頭、設定一些引數、回圈讀取資料、寫入資料
        ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
       ......  
        ret = avformat_write_header(ofmt_ctx, /*NULL*/&options);
     	......
         av_dump_format(ofmt_ctx, 0, out_filename, 1);
       ......
        while (m_bRun)
        {
            AVStream *in_stream, *out_stream;
            ret = av_read_frame(ifmt_ctx, &pkt);
            if (ret < 0)
            {
                int err_code = ret;
                char buf[1024] = { 0 };
                if (ret < 0) {
                    av_strerror(err_code, buf, 1024);
                    qDebug()<<buf;						//在此處報錯
               
                }             
            }
			......        
            ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
        }

原因分析:

常規分析手段:
  1. 抓包分析

    通過抓包看,是nginx服務器主動結束了連接;

  2. 分析nginx日志
    由于是在 av_interleaved_write_frame函式發生了例外,該函式直接作用是將“h264資料”送至nginx服務器,所以進一步打開nginx debug日志等級,錯誤日志如下:

2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 02 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 0A ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (10) 6F 6E 4D 65 74 61 44 61 74 61 ‘onMetaData’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 03 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 06 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (6) 53 65 72 76 65 72 ‘Server’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 02 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 44 ‘?D’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (68) 4E 47 49 4E 58 20 48 54 54 50 2D 46 4C 56 20 28 ‘NGINX HTTP-FLV (’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 05 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (5) 77 69 64 74 68 ‘width’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 40 84 00 00 00 00 00 00 ‘@???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 06 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (6) 68 65 69 67 68 74 ‘height’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 40 7E 00 00 00 00 00 00 ‘@~???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 0C ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (12) 64 69 73 70 6C 61 79 57 69 64 74 68 ‘displayWidth’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 40 84 00 00 00 00 00 00 ‘@???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 0D ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (13) 64 69 73 70 6C 61 79 48 65 69 67 68 74 ‘displayHeight’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 40 7E 00 00 00 00 00 00 ‘@~???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 08 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 64 75 72 61 74 69 6F 6E ‘duration’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 00 00 00 00 00 00 00 00 ‘???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 09 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (9) 66 72 61 6D 65 72 61 74 65 ‘framerate’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 00 00 00 00 00 00 00 00 ‘???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 03 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (3) 66 70 73 ‘fps’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 00 00 00 00 00 00 00 00 ‘???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 0D ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (13) 76 69 64 65 6F 64 61 74 61 72 61 74 65 ‘videodatarate’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 00 00 00 00 00 00 00 00 ‘???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 0C ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (12) 76 69 64 65 6F 63 6F 64 65 63 69 64 ‘videocodecid’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 40 1C 00 00 00 00 00 00 ‘@???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 0D ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (13) 61 75 64 69 6F 64 61 74 61 72 61 74 65 ‘audiodatarate’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 00 00 00 00 00 00 00 00 ‘???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 0C ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (12) 61 75 64 69 6F 63 6F 64 65 63 69 64 ‘audiocodecid’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 00 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (8) 00 00 00 00 00 00 00 00 ‘???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 07 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (7) 70 72 6F 66 69 6C 65 ‘profile’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 02 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 20 '? ’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (32) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ‘???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 05 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (5) 6C 65 76 65 6C ‘level’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 02 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 20 '? ’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (32) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ‘???’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (2) 00 00 ‘??’
2021/09/22 20:07:50 [debug] 1729538#0: *17 AMF write (1) 09 ‘?’
2021/09/22 20:07:50 [debug] 1729538#0: *17 RTMP prep amf_meta (18) fmt=0 csid=5 timestamp=0 mlen=409 msid=1 nbufs=4
2021/09/22 20:07:50 [debug] 1729538#0: *17 reusing formerly read data: 17
2021/09/22 20:07:50 [debug] 1729538#0: *17 RTMP bheader fmt=0 csid=6
2021/09/22 20:07:50 [debug] 1729538#0: *17 RTMP mheader fmt=0 video (9) time=0+0 mlen=5 len=0 msid=1
2021/09/22 20:07:50 [debug] 1729538#0: *17 RTMP recv video (9) csid=6 timestamp=0 mlen=5 msid=1 nbufs=1
2021/09/22 20:07:50 [debug] 1729538#0: *17 nhandlers: 6
2021/09/22 20:07:50 [debug] 1729538#0: *17 calling handler 0
2021/09/22 20:07:50 [debug] 1729538#0: *17 codec: avc header 1700000000
2021/09/22 20:07:50 [error] 1729538#0: *17 123456 codec: invalid video codec header size=5, client: 172.21.34.145, server: 0.0.0.0:1935
2021/09/22 20:07:50 [debug] 1729538#0: *17 handler 0 failed
2021/09/22 20:07:50 [debug] 1729538#0: *17 finalize session
2021/09/22 20:07:50 [debug] 1729538#0: *17 post event 0000000001654C48
2021/09/22 20:07:50 [debug] 1729538#0: timer delta: 42
2021/09/22 20:07:50 [debug] 1729538#0: posted event 0000000001654C48
2021/09/22 20:07:50 [debug] 1729538#0: *17 delete posted event 0000000001654C48
2021/09/22 20:07:50 [debug] 1729538#0: *17 close session
2021/09/22 20:07:50 [info] 1729538#0: *17 disconnect, client: 172.21.34.145, server: 0.0.0.0:1935

這段日志中,明顯可以看到的操作是在寫 flv 的包頭;舉個例子,其中“onMetaData”等均是flv 包頭格式;onMetaData是FLV檔案中的第一個Tag, 用來表示當前檔案的一些基本資訊: 比如視音頻的編碼型別id、視頻的寬和高、檔案大小、視頻長度、創建日期等, 順著日志往下閱讀,發現下面兩行日志:

2021/09/22 20:07:50 [debug] 1729538#0: *17 codec: avc header 1700000000
2021/09/22 20:07:50 [error] 1729538#0: *17 123456 codec: invalid video codec header size=5, client: 172.21.34.145, server: 0.0.0.0:1935

avc header 是h264的編碼頭,這一段是無效資料,導致了例外,以及后面的close session;

  1. ffmpeg 函式對應的avc header是哪?
    對應下面資料結構中的“ extradata”;
typedef struct AVCodecParameters {
    /**
     * General type of the encoded data.
     */
    enum AVMediaType codec_type;
    /**
     * Specific type of the encoded data (the codec used).
     */
    enum AVCodecID   codec_id;
    /**
     * Additional information about the codec (corresponds to the AVI FOURCC).
     */
    uint32_t         codec_tag;

    /**
     * Extra binary data needed for initializing the decoder, codec-dependent.
     *
     * Must be allocated with av_malloc() and will be freed by
     * avcodec_parameters_free(). The allocated size of extradata must be at
     * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding
     * bytes zeroed.
     */
    uint8_t *extradata;
    /**
     * Size of the extradata content in bytes.
     */
    int      extradata_size;

    /**
     * - video: the pixel format, the value corresponds to enum AVPixelFormat.
     * - audio: the sample format, the value corresponds to enum AVSampleFormat.
     */
    int format;

    /**
     * The average bitrate of the encoded data (in bits per second).
     */
    int64_t bit_rate;

    /**
     * The number of bits per sample in the codedwords.
     *
     * This is basically the bitrate per sample. It is mandatory for a bunch of
     * formats to actually decode them. It's the number of bits for one sample in
     * the actual coded bitstream.
     *
     * This could be for example 4 for ADPCM
     * For PCM formats this matches bits_per_raw_sample
     * Can be 0
     */
    int bits_per_coded_sample;

    /**
     * This is the number of valid bits in each output sample. If the
     * sample format has more bits, the least significant bits are additional
     * padding bits, which are always 0. Use right shifts to reduce the sample
     * to its actual size. For example, audio formats with 24 bit samples will
     * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32.
     * To get the original sample use "(int32_t)sample >> 8"."
     *
     * For ADPCM this might be 12 or 16 or similar
     * Can be 0
     */
    int bits_per_raw_sample;

    /**
     * Codec-specific bitstream restrictions that the stream conforms to.
     */
    int profile;
    int level;

    /**
     * Video only. The dimensions of the video frame in pixels.
     */
    int width;
    int height;

    /**
     * Video only. The aspect ratio (width / height) which a single pixel
     * should have when displayed.
     *
     * When the aspect ratio is unknown / undefined, the numerator should be
     * set to 0 (the denominator may have any value).
     */
    AVRational sample_aspect_ratio;

    /**
     * Video only. The order of the fields in interlaced video.
     */
    enum AVFieldOrder                  field_order;

    /**
     * Video only. Additional colorspace characteristics.
     */
    enum AVColorRange                  color_range;
    enum AVColorPrimaries              color_primaries;
    enum AVColorTransferCharacteristic color_trc;
    enum AVColorSpace                  color_space;
    enum AVChromaLocation              chroma_location;

    /**
     * Video only. Number of delayed frames.
     */
    int video_delay;

    /**
     * Audio only. The channel layout bitmask. May be 0 if the channel layout is
     * unknown or unspecified, otherwise the number of bits set must be equal to
     * the channels field.
     */
    uint64_t channel_layout;
    /**
     * Audio only. The number of audio channels.
     */
    int      channels;
    /**
     * Audio only. The number of audio samples per second.
     */
    int      sample_rate;
    /**
     * Audio only. The number of bytes per coded audio frame, required by some
     * formats.
     *
     * Corresponds to nBlockAlign in WAVEFORMATEX.
     */
    int      block_align;
    /**
     * Audio only. Audio frame size, if known. Required by some formats to be static.
     */
    int      frame_size;

    /**
     * Audio only. The amount of padding (in samples) inserted by the encoder at
     * the beginning of the audio. I.e. this number of leading decoded samples
     * must be discarded by the caller to get the original audio without leading
     * padding.
     */
    int initial_padding;
    /**
     * Audio only. The amount of padding (in samples) appended by the encoder to
     * the end of the audio. I.e. this number of decoded samples must be
     * discarded by the caller from the end of the stream to get the original
     * audio without any trailing padding.
     */
    int trailing_padding;
    /**
     * Audio only. Number of samples to skip after a discontinuity.
     */
    int seek_preroll;
} AVCodecParameters;

  1. 常規手段之,列印分析in_stream 以及out_stream的對應的parameter引數中的exteradata欄位;
    加入以下代碼,將
void myprintf(uint8_t* data,int len)
{

    QString disp_string,S;
    QByteArray ba;
    ba.resize(len);

    QString m_strMSG = QString("myprintf len=:%1").arg(len);
    for (int i = 0 ;i < len; i++)
    {
        ba[i] = data[i];

    }
    for(int i=0;i<ba.size();i++)
    {
        S.sprintf("0x%02x, ", (unsigned char)ba.at(i));
        disp_string += S;
    }   
    qDebug()<<m_strMSG<<"\n";   
    qDebug()<<disp_string<<"\n";
}

......

//進行列印
 myprintf(out_stream->codecpar->extradata,out_stream->codecpar->extradata_size);



解決方案:

發現,從in_stream中獲取的AVCodecParameters中的extradata是一串無效值;那么只需要將這個欄位重新填入正確的值即可; 這段值應該填入正確的sps\pps等資訊,剩下的就是編碼實作了;舉個例子,下面資料 17 00 00 00 00 就是video tag標簽,后面圈出來的資料,就是對應的avc heaer資訊,其中包含了正確的h264所需要的sps\pps等資料;

在這里插入圖片描述

文章的最后:如果需要研究flv封裝格式的特點,可以具體搜索網路資源,

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

標籤:其他

上一篇:Gen-Z 可擴展連接器和SFF-TA-1002規范。

下一篇:億級流量系統架構演進之路

標籤雲
其他(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)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more