集群部署專題之二:超高性能RPC框架Zeroc-ICE集群部署簡易教程

来源:https://www.cnblogs.com/xl-xueling/archive/2023/09/01/17670837.html
-Advertisement-
Play Games

### 歡迎訪問我的GitHub > 這裡分類和彙總了欣宸的全部原創(含配套源碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### 題目描述 - 難度:中等 - 給定一個不含重覆數字的數 ...


一、前言

Zeroc ICE在簡中互聯網的資料十分匱乏,以至於大家線上使用時可能會有所顧慮。其實大家盡可放心,ZerocICE是一款性能和穩定性都非常優秀的RPC組件,這也是我當時選擇ZerocICE作為XL-LightHouse的RPC組件的唯一原因。為便於大家快速瞭解ZerocICE,本文以v3.7版本為例介紹其部署和使用方式。

二、特性

  • 跨語言通信
  • 高性能RPC
  • 安全通信
  • 實時壓縮
  • 註冊中心支持主從備份
  • 節點負載均衡,可動態調整
  • 支持同步調用和非同步調用

三、名詞解釋

1、Slice語義
ZerocICE目前支持的開發語言有:C++、Java、C#、JavaScript、Python、Ruby、Swift、Objective-C、PHP。通過Slice語義,不同語言開發的客戶端和服務端可以完全互通。Slice語義可以理解成一種描述介面構成(介面名稱、介面參數類型、返回值類型)的標準。ZerocICE提供了Slice轉化工具,可以在各種系統平臺將Slice語義轉化成對應的介面的代碼。比如相同的Slice文件,在X86平臺可以通過Slice2Java轉化成相應的Java介面代碼,在ARM平臺通過Slice2C++可以轉化成對應的C++介面代碼。

2、Ice.Object

Ice.Object是RPC介面的抽象,ICE中一個Object對象可以包含多個介面,每一個介面對應一個響應客戶端請求的Object實體。ICE使用(Object Identity)來區分不同的Object對象,identity在集群中必須全局唯一。

3、Proxy
Ice.Object是相對於ICE服務端來說的,而Proxy則是相對於ICE客戶端來說的.客戶端要想調用某個介面,必須持有該對象的代理,Proxy就是Object對象在客戶端的代理者。

4、Adapter
Adapter是對象適配器,用於把客戶端請求映射到某個Object對象的特定方法上。

5、IceBox

IceBox是應用容器,每個IceBox實例叫做一個Server,對應一個獨立的進程,系統為每個server分配一個獨立的server id,ICE通過對管理IceBox進程來實現負載均衡等操作。

6、IceNode
IceBox對應的獨立進程,而IceNode則對應的獨立伺服器節點,一個伺服器節點可以啟動多個IceBox進程實例。

7、IceGrid

ICE可以同時管理多個IceGrid,每個IceGrid可以理解成是一套服務的整體拓撲結構,Locator是用於定位IceGrid的定址信息。

8、Registry

服務的註冊中心,客戶端在調用介面時,需要指定主從註冊中心的地址,介面處理時首先請求註冊中心,註冊中心為其分配處理當前請求的adapter,adapter再將請求定位到具體的指定server進程中的特定object對象處理。

9、部署及運行結構

很多朋友覺得ICE複雜,可能是因為ICE提出了很多新的概念,而不清每個概念的包含關係,以至於不能理解它的運行方式,再加上資料匱乏所以難以上手。我覺得只要從兩個角度去看這個問題可能會比較清晰,一個是物理結構(伺服器節點),另一個是軟體結構(服務運行結構)。

  • 從物理節點的角度

一個IceGrid集群,包括至少一個註冊中心節點(建議線上使用主從註冊中心節點),並且一個IceGrid集群管理多個Node節點。

  • 從服務運行的角度
IceGrid集群可以啟動一個或多個應用(Application),每個應用可以占用當前IceGrid集群中的一個或多個節點,這裡的Application概念你可以理解成是我們常說的微服務。 Application啟動時其配置文件指定了當前應用運行所可以占用的節點信息,以及每個節點可以啟動的Server實例,這個Server實例就是IceBox進程。註意:application啟動時預設不會同時啟動server實例,server實例是根據客戶端請求併發量自動啟動的,當然也可以手動啟動。

為什麼IceGrid部署時明明已經啟動了對應的Node節點,但application的配置文件還需要加Node配置?
其實這個問題很好理解,Grid可以管理多個節點,所以部署時被其管理的每個節點都要啟動一個icegridnode進程。而Grid也可以包含多個application,每個application可以根據需要占用Grid所有節點中的一個或多個。

service和adapter區別?
ICE中的service對應的是介面,一個server中可以包含多個介面。
adapter是特定對象上的介面,用來將客戶端請求分配到特定server上去處理。可能有些拗口,不過我拿XL-LightHouse的進程舉一個例子就很明白了。

如上圖:
server list,將集群所有IceBox進程羅列出來。
service list,serverID將當前server中的介面名稱羅列出來。
adapter list,ICE將所有server中的每個介面實例都分配了一個adapter句柄並將其羅列出來。

四、Ice安裝

部署前請確保系統已安裝JDK、GCC等依賴包!

不同發行版的安裝方式略有不同,以下命令只適合RHEL、CentOS、Rocky和Almalinux,如果您是其他的Linux發行版,請按照官網描述的方式安裝(也可以參考XL-LightHouse源碼中的/bin/install/install_ice.sh文件)。

官網安裝參考:https://doc.zeroc.com/ice/3.7/release-notes/using-the-linux-binary-distributions
下麵以AlmaLinux安裝為例:

#註意:rpm安裝需要根據系統版本指定el版本,使用uname命令可以查看系統el版本,不能配錯
[root@VM-6-22-rockylinux ~]# uname -a
Linux VM-6-22-rockylinux 5.14.0-162.6.1.el9_1.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Nov 18 02:06:38 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

我用的Alma9.1部署時需要指定el9,安裝命令即為:
sudo yum install https://zeroc.com/download/ice/3.7/el9/ice-repo-3.7.el9.noarch.rpm
sudo yum install ice-all-runtime ice-all-devel

安裝成功後,可以查看到相關的命令:

[root@VM-6-37-almalinux soft]# ice
icebox           iceboxadmin      icegridadmin     icegridgui       icegridregistry  icepatch2client  icestormadmin    
icebox++11       icebridge        icegriddb        icegridnode      icepatch2calc    icepatch2server  icestormdb  

五、Slice文件生成

完整代碼請查閱:https://github.com/xl-xueling/ZerocICEDemo.git

(1)、創建slice文件printer.ice

[["java:package:com.dtstep.test.ice"]]
module PrinterServer {
        interface Printer{
                void printStr(string str);
        };
};

(2)、生成介面代碼

#進入到Linux環境,執行以下命令
slice2java printer.ice 

以上命令會在當前目錄生成介面代碼,因為我這裡的部署客戶端和服務端都是使用的Java語言,所以該介面代碼客戶端和服務端都需要用,如果客戶端和服務端是跨語言的需要用相應的命令生成不同的介面代碼。

(3)、創建工程並引入依賴包

<dependencies>
        <dependency>
            <groupId>com.zeroc</groupId>
            <artifactId>ice</artifactId>
            <version>3.7.9</version>
        </dependency>
        <dependency>
            <groupId>com.zeroc</groupId>
            <artifactId>icebox</artifactId>
            <version>3.7.9</version>
        </dependency>
        <dependency>
            <groupId>com.zeroc</groupId>
            <artifactId>icegrid</artifactId>
            <version>3.7.9</version>
        </dependency>
        <dependency>
            <groupId>com.zeroc</groupId>
            <artifactId>ice-compat</artifactId>
            <version>3.7.9</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.zeroc</groupId>
            <artifactId>glacier2</artifactId>
            <version>3.7.9</version>
        </dependency>
    </dependencies>

(4)、將上面生成的介面代碼拷貝到工程中。

六、本地運行模式

完整代碼請查閱:https://github.com/xl-xueling/ZerocICEDemo.git

(1)、創建服務端實現類

public class PrinterServer {

    public static void main(String[] args) {
        Communicator ic = null;
        try {
            ic = Util.initialize();
            ObjectAdapter adapter = ic.
                    createObjectAdapterWithEndpoints("PrinterServiceAdapter", "default -p 10000");
            LocalPrinterServiceImpl servant = new LocalPrinterServiceImpl();
            adapter.add(servant, Util.stringToIdentity("PrinterService"));
            adapter.activate();
            System.out.println("The server starts listening ...");
            ic.waitForShutdown();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ic != null) {
                ic.destroy();
            }
        }
    }
}

(2)、創建客戶端端實現類

public class PrinterClient {

    public static void main(String[] args) {
        Communicator ic = null;
        try {
            ic = Util.initialize();
            ObjectPrx base = ic.stringToProxy("PrinterService:default -p 10000");
            PrinterPrx proxy = PrinterPrx.checkedCast(base);
            for(int i=0;i<500;i++){
                String msg = "Hello World_" + i;
                proxy.printStr(msg);
                System.out.println("client send message,msg:" + msg);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ic != null) {
                ic.destroy();
            }
        }
    }
}

(3)、同時本地運行客戶端和服務端可以正常發送和接收消息

七、集群模式配置

註意:
1、以下操作不要在root賬號下執行,如果在root賬號下啟動icegridnode,ice啟動服務為了安全起見使用的是nobody用戶,而該用戶沒有目錄訪問許可權,所以啟動會報錯!
2、完整代碼請查閱:https://github.com/xl-xueling/ZerocICEDemo.git
3、以下內容我直接基於【XL-LightHouse開源通用型流式數據統計項目】的結構進行修改,XL-LightHouse是對程式員日常開發很有幫助的輔助工具,歡迎GitHub搜索瞭解。

(1)、集群規劃
以下操作我在三台AlmaLinux節點上部署該集群,IP分別為:

10.206.6.37 #作為註冊中心主節點和Node運算節點
10.206.6.39 #作為註冊中心從節點和Node運算節點
10.206.6.25 #作為Node運算節點

(2)、創建工程所需目錄

在三台伺服器上依次創建以下目錄結構。

#該路徑用於存儲相關配置文件
mkdir -p /opt/soft/PrinterProject/conf

#該路徑用於存儲註冊中心的數據文件及日誌信息
mkdir -p /opt/soft/PrinterProject/data/registdata
#該路徑用於存儲Node節點的運行數據文件
mkdir -p /opt/soft/PrinterProject/data/nodedata
#該路徑用於存儲Node節點的輸出日誌信息
mkdir -p /opt/soft/PrinterProject/data/nodeoutput

#創建依賴包路徑,包含工程jar包和ICE依賴包
mkdir -p /opt/soft/PrinterProject/lib

#賦予目錄讀寫許可權
chmod -R 755 /opt/soft/PrinterProject

(3)、創建註冊中心主節點配置文件 master_registry.cfg

IceGrid.InstanceName=PrinterIceGrid
IceGrid.Registry.Client.Endpoints=tcp -p 4061
IceGrid.Registry.Server.Endpoints=tcp
IceGrid.Registry.Internal.Endpoints=tcp
IceGrid.Registry.PermissionsVerifier=PrinterIceGrid/NullPermissionsVerifier
IceGrid.Registry.AdminPermissionsVerifier=PrinterIceGrid/NullPermissionsVerifier
IceGrid.Registry.LMDB.Path=/opt/soft/PrinterProject/data/registdata
IceGrid.Registry.DynamicRegistration=1
Ice.Admin.InstanceName=AdminInstance
Ice.LogFile=/opt/soft/PrinterProject/data/registdata/ice-regist.log

(4)、創建註冊中心從節點配置文件 slave_registry.cfg

Ice.Default.Locator=PrinterIceGrid/Locator:tcp -h 10.206.6.37 -p 4061
IceGrid.Registry.Client.Endpoints=tcp -p 4061
IceGrid.Registry.Server.Endpoints=tcp
IceGrid.Registry.Internal.Endpoints=tcp
IceGrid.Registry.PermissionsVerifier=PrinterIceGrid/NullPermissionsVerifier
IceGrid.Registry.AdminPermissionsVerifier=PrinterIceGrid/NullPermissionsVerifier
IceGrid.Registry.LMDB.Path=/opt/soft/PrinterProject/data/registdata
IceGrid.Registry.DynamicRegistration=1
IceGrid.Registry.ReplicaName=Replica1
Ice.LogFile=/opt/soft/PrinterProject/data/registdata/ice-regist.log

(5)、創建每台節點對應的node.cfg文件

註意:每個節點的Node.Name不可相同,而且需要與application.xml文件中的節點名稱一致。

Ice.Default.Locator=PrinterIceGrid/Locator:tcp -h 10.206.6.37 -p 4061:tcp -h 10.206.6.39 -p 4061
IceGrid.Node.Name=node1
IceGrid.Node.Endpoints=tcp
#配置文件中的路徑必須首先創建出來,並且目錄需要有寫入數據的許可權
IceGrid.Node.Data=/opt/soft/PrinterProject/data/nodedata
IceGrid.Node.Output=/opt/soft/PrinterProject/data/nodeoutput
IceGrid.Node.CollocateRegistry=0
Ice.StdErr=/opt/soft/PrinterProject/data/nodeoutput/ice_stderr.log

(6)、創建應用配置文件application.xml

<icegrid>
    <application name="PrinterServiceApplication">
        <properties id="MultiThreaded">
            <property name="Ice.PrintStackTraces" value="1"/>
            <property name="IceSSL.Trace.Security" value="2"/>
            <property name="Ice.ThreadPool.Client.Size" value="50"/>
            <property name="Ice.ThreadPool.Client.SizeMax" value="500"/>
            <property name="Ice.ThreadPool.Server.Size" value="50"/>
            <property name="Ice.ThreadPool.Serxver.SizeMax" value="500"/>
            <property name="IceBox.InheritProperties" value="1"/>
            <property name="Ice.Override.ConnectTimeout" value="2000"/>
            <property name="Ice.Override.Timeout" value="2000" />
            <property name="IceBox.Trace.ServiceObserver" value="1"/>
            <property name="Ice.Default.Timeout" value="2000"/>
            <property name="Ice.Default.LocatorCacheTimeout" value="1200" />
            <property name="Ice.BackgroundLocatorCacheUpdates" value="1"/>
        </properties>
        <server-template id="PrinterBoxTemplate">
            <parameter name="index" default="0"/>
            <icebox id="printer-icebox${index}" exe="java" activation="on-demand" >
                <properties>
                    <properties refid="MultiThreaded" />
                </properties>
                <option>-Xmx4000M</option>
                <option>-Xms4000m</option>
                <option>-XX:+UseCompressedOops</option>
                <option>-XX:+HeapDumpOnOutOfMemoryError</option>
                <option>-XX:+UseG1GC</option>
                <option>-XX:-UseBiasedLocking</option>
                <option>-XX:G1HeapRegionSize=4M</option>
                <option>com.zeroc.IceBox.Server</option>
                <env>CLASSPATH=.:/opt/soft/PrinterProject/lib/*</env>
                <!--該處配置server端的介面類地址-->
                <service name="PrinterService" entry="com.dtstep.test.ice.PrinterServer.cluster.server.PrinterService">
                    <adapter name="PrinterService" id="PrinterService${index}" endpoints="default" replica-group="PrinterServiceRep" />
                </service>
            </icebox>
        </server-template>
        <replica-group id="PrinterServiceRep">
            <load-balancing type="adaptive" n-replicas="0" />
            <!--該處的type配置slice文件的module名稱和interface名稱-->
            <object identity="PrinterServiceIdentity" type="::PrinterServer::Printer"/>
        </replica-group>
        <!--node名稱,必須與node.cfg中的名稱對應-->
        <node name="node1">
            <!--註意template名稱需要與上面的server-template保持一致 -->
            <server-instance template="PrinterBoxTemplate" index="11"/>
            <server-instance template="PrinterBoxTemplate" index="12"/>
        </node>
        <node name="node2">
            <server-instance template="PrinterBoxTemplate" index="21"/>
            <server-instance template="PrinterBoxTemplate" index="22"/>
        </node>
        <node name="node3">
            <server-instance template="PrinterBoxTemplate" index="31"/>
            <server-instance template="PrinterBoxTemplate" index="32"/>
        </node>
     </application>
</icegrid>

(7)、創建集群Server端實現

public class PrinterService implements Service  {

    @Override
    public void start(String s, Communicator communicator, String[] strings) {
        ObjectAdapter adapter = communicator.createObjectAdapter(s);
        communicator.getProperties().setProperty("Ice.MessageSizeMax", "1409600");
        ClusterPrinterServiceImpl servant = new ClusterPrinterServiceImpl();
        adapter.add(servant, Util.stringToIdentity("PrinterServiceIdentity"));
        adapter.activate();
        System.out.println("printer server start success!");
    }

    @Override
    public void stop() {

    }
}

(8)、創建集群Client端實現

public class ClientTest {

    public static void main(String[] args) {
        Communicator ic = null;
        try {
            String initParams = "--Ice.Default.Locator=PrinterIceGrid/Locator:tcp -h 10.206.6.39 -p 4061:tcp -h 10.206.6.37 -p 4061 -z";
            String [] params = new String[]{initParams};
            ic = Util.initialize(params);
            //註意該處配置與介面對應的replica-group的identity名稱保持一致
            ObjectPrx objectPrx = ic.stringToProxy("PrinterServiceIdentity").ice_connectionId(UUID.randomUUID().toString()).ice_locatorCacheTimeout(1200);
            PrinterPrx proxy = PrinterPrx.checkedCast(objectPrx);
            for(int i=0;i<500;i++){
                String msg = "Hello World_" + i;
                proxy.printStr(msg);
                System.out.println("client send message,msg:" + msg);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ic != null) {
                ic.destroy();
            }
        }
    }
}

(9)、將上述配置文件上傳到conf目錄。
(10)、將工程打包和maven依賴包上傳到lib目錄下
(11)、工程的完整文件及路徑信息如下

[root@VM-6-37-almalinux PrinterProject]# pwd
/opt/soft/PrinterProject
[root@VM-6-37-almalinux PrinterProject]# tree -a ./
./
├── conf
│   ├── application.xml
│   ├── master_registry.cfg
│   ├── node1.cfg
│   ├── node2.cfg
│   ├── node3.cfg
│   ├── printer.ice
│   └── slave_registry.cfg
├── data
│   ├── nodedata
│   ├── nodeoutput
│   └── registdata
└── lib
    ├── glacier2-3.7.9.jar
    ├── ice-3.7.9.jar
    ├── icebox-3.7.9.jar
    ├── ice-compat-3.7.9.jar
    ├── icegrid-3.7.9.jar
    └── TestICE-1.0-SNAPSHOT.jar

5 directories, 13 files

(12)、將以上工程文件夾同步到集群各個節點。

七、集群模式啟動

(1)、在第一臺伺服器上啟動註冊中心主節點

#註意:如果執行重啟操作,請檢查一下icegridregistry進程是否仍存在,如果存在先kill掉,然後務必刪除registdata目錄下的文件後再重啟。

icegridregistry --Ice.Config=/opt/soft/PrinterProject/conf/master_registry.cfg &

執行完後,查看/opt/soft/PrinterProject/data/registdata/ice-regist.log是否有異常。

(2)、在第二台伺服器上啟動註冊中心主節點,註意與主節點配置文件不同

#註意:如果重啟請檢查一下icegridregistry進程是否仍存在,如果存在kill掉,然後務必刪除registdata目錄下的文件後再重啟。

icegridregistry --Ice.Config=/opt/soft/PrinterProject/conf/slave_registry.cfg &

執行完後,查看/opt/soft/PrinterProject/data/registdata/ice-regist.log是否有異常。

(3)、在三台伺服器依次啟動節點,註意配置文件各不相同

#註意:如果重啟請檢查一下icegridnode進程是否仍存在,如果存在kill掉,並同時將nodedata目錄下文件刪除後再重啟。

icegridnode --Ice.Config=/opt/soft/PrinterProject/conf/node1.cfg &

icegridnode --Ice.Config=/opt/soft/PrinterProject/conf/node2.cfg &

icegridnode --Ice.Config=/opt/soft/PrinterProject/conf/node3.cfg &

(4)、進程檢查

執行完以上操作後,在註冊中心主節點執行

icegridadmin命令,user id和password隨便輸入進入到ICE控制台。

執行help命令,可查看所有組件,執行 node help,service help ...可查看每個組件的幫助信息。
執行node list命令,查看當前節點是否啟動正常,如果正常進行下一步。

八、啟動應用Application

執行icegridamin命令進入ICE控制台。

# 啟動應用
>> application add /opt/soft/PrinterProject/conf/application.xml

# 啟動應用後,預設不會立即啟動server,當有客戶端請求時會自動啟動server

# 查看server 列表
>> server list

# 手動啟動server,進入nodeout目錄查看日誌是否正常。
>> server start printer-icebox11

# 查看應用列表
>> application list

# 移除應用
>> application remove PrinterServiceApplication

執行cluster目錄內的ClientTest.java發送消息到服務端,服務端的nodeoutput目錄可以正常輸出日誌信息(註意:由於集群在三台伺服器上啟動了6個進程,所以需要具體看下請求被分發到了哪個進程,輸出的日誌文件是不同的,線上使用的時候可以配置log4j讓節點內的多個進程都輸出到一個日誌文件)。

[work@VM-6-25-almalinux nodeoutput]$ tail -f printer-icebox32.out 
server receive message,msg:Hello World_25
server receive message,msg:Hello World_26
server receive message,msg:Hello World_27
server receive message,msg:Hello World_28
server receive message,msg:Hello World_29
server receive message,msg:Hello World_30
server receive message,msg:Hello World_31
server receive message,msg:Hello World_32
server receive message,msg:Hello World_33
server receive message,msg:Hello World_34
server receive message,msg:Hello World_35

完整代碼及配置信息請查閱:https://github.com/xl-xueling/ZerocICEDemo.git

九、解鎖新技能、打開新世界

上述內容向大家介紹了一款超高性能的RPC服務框架ZerocICE的集群部署方式和初步使用。接下來向大家推薦一款更具有實用價值的開發好幫手XL-LightHouse。XL-LightHouse是一款通用型流式大數據統計工具,對於程式員來說,它有幾個特性:

1、世界範圍獨一無二;
2、它對各種工種的程式員都具有很大的實用價值;
3、你只要用上它,就會離不開它;

建議您花一兩分鐘的時間GitHub搜索XL-LightHouse或訪問dtstep.com瞭解更多!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ## pprof簡介 `pprof`是Go語言的一個性能分析庫,它可以幫助開發者找出程式中的性能瓶頸。`pprof`提供了CPU分析、記憶體分析、阻塞分析等多種性能分析功能。 以下是`pprof`的主要特性: 1. **CPU分析**:`pprof`可以記錄程式在CPU上的運行時間,並將這些數據以火焰 ...
  • [TOC]([Qt開發探幽(二)]淺談關於元對象,巨集和Q_ENUM) # [Qt開發探幽(二)]淺談關於元對象,巨集和Q_ENUM ## 前言 最近在開發的時候,我自己寫了一套虛函數。這也是我第一次寫這麼大一個框架,遇到了一些有點莫名其妙的問題(也不能算莫名奇妙,只能說有點玩不明白),詳情可以見 [[ ...
  • acwing學習筆記,記錄容易忘記的知識點和難題。快速排序、歸併排序、整數二分、浮點數二分、高精度運算、一維首碼和、二維首碼和、一維差分、二維差分、雙指針演算法、位運算、整數離散化、區間合併 ...
  • 使用`Matplotlib`對分析結果可視化時,比較各類分析結果是常見的場景。在這類場景之下,將多個分析結果繪製在一張圖上,可以幫助用戶方便地組合和分析多個數據集,提高數據可視化的效率和準確性。 本篇介紹`Matplotlib`繪製子圖的常用方式和技巧。 # 1. 添加子圖的方式 添加子圖主要有兩種 ...
  • 在筆者前幾篇文章中我們一直在探討如何利用`Metasploit`這個滲透工具生成`ShellCode`以及如何將ShellCode註入到特定進程內,本章我們將自己實現一個正向`ShellCode`Shell,當進程被註入後,則我們可以通過利用NC等工具連接到被註入進程內,並以對方的許可權及身份執行命令... ...
  • ![](https://img2023.cnblogs.com/other/1218593/202309/1218593-20230901100033869-964667327.png) ## **背景** 在我們平常的編碼中,通常會將一些對象保存起來,這主要考慮的是對象的創建成本。 比如像線程資源 ...
  • 今天推薦一個github的開源工具 [pkgu](https://github.com/Abeautifulsnow/pkgu),支持以表格形式展示當前python環境下的有新版本的package的版本信息,並支持全部或部分更新這些已經過期或者有新版的庫。 該工具目前還提供了 `cache` 功能, ...
  • ## 14.1、概述 ### 14.1.1、編程式事務 > 事務功能的相關操作全部通過自己編寫代碼來實現: ``` Connection conn = ...; try { // 開啟事務:關閉事務的自動提交 conn.setAutoCommit(false); // 核心操作 // 提交事務 co ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...