主頁 > 軟體設計 > 分布式事務之解決方案(最大努力通知)

分布式事務之解決方案(最大努力通知)

2020-09-14 13:21:01 軟體設計

 

6.分布式事務解決方案之最大努力通知

6.1. 什么是最大努力通知

最大努力通知也是一種解決分布式事務的方案,下邊是一個是充值的例子:
在這里插入圖片描述
互動流程 :
1、賬戶系統呼叫充值系統介面
2、充值系統完成支付處理向賬戶系統發起充值結果通知
若通知失敗,則充值系統按策略進行重復通知
3、賬戶系統接收到充值結果通知修改充值狀態
4、賬戶系統未接收到通知會主動呼叫充值系統的介面查詢充值結果
通過上邊的例子我們總結最大努力通知方案的目標 :
目標 :發起通知方通過一定的機制最大努力將業務處理結果通知到接收方,
具體包括 :
1、有一定的訊息重復通知機制,
因為接收通知方可能沒有接收到通知,此時要有一定的機制對訊息重復通知,
2、訊息校對機制,
如果盡最大努力也沒有通知到接收方,或者接收方消費訊息后要再次消費,此時可由接收方主動向通知方查詢訊息資訊來滿足需求,
最大努力通知與可靠訊息一致性有什么不同?
1、解決方案思想不同
可靠訊息一致性,發起通知方需要保證將訊息發出去,并且將訊息發到接收通知方,訊息的可靠性關鍵由發起通知方來保證,
最大努力通知,發起通知方盡最大的努力將業務處理結果通知為接收通知方,但是可能訊息接收不到,此時需要接收通知方主動呼叫發起通知方的介面查詢業務處理結果,通知的可靠性關鍵在接收通知方,
2、兩者的業務應用場景不同
可靠訊息一致性關注的是交易程序的事務一致,以異步的方式完成交易,
最大努力通知關注的是交易后的通知事務,即將交易結果可靠的通知出去,
3、技術解決方向不同
可靠訊息一致性要解決訊息從發出到接收的一致性,即訊息發出并且被接收到,
最大努力通知無法保證訊息從發出到接收的一致性,只提供訊息接收的可靠性機制,可靠機制是,最大努力的將訊息通知給接收方,當訊息無法被接收方接收時,由接收方主動查詢消費(業務處理結果),

6.2. 解決方案

通過對最大努力通知的理解,采用MQ的ack機制就可以實作最大努力通知,
方案1 :
在這里插入圖片描述
本方案是利用MQ的ack機制由MQ向接收通知方發送通知,流程如下 :
1、發起通知方將通知發給MQ,
使用普通訊息機制將通知發給MQ,
注意 :如果訊息沒有發出去可由接收通知方主動請求發起通知方查詢業務執行結果,
2、接收通知方監聽MQ,
3、接收通知方接收訊息,業務處理完成回應ack,
4、接收通知方若沒有回應ack則MQ會重復通知,
MQ會按照間隔1min、5min、10min、30min、1h、2h、5h、10h的方式,逐步拉大通知間隔(如果MQ采用rocketMq,在broker中可進行配置),直到達到通知要求的時間視窗上限,
5、接收通知方可通過訊息校對介面來校對訊息的一致性,
方案2 :
本方案也是利用MQ的ack機制,與方案1不同的是應用程式向接收通知方發送通知,如下圖 :
在這里插入圖片描述
互動流程如下 :
1、發起通知方將通知發給MQ,
使用可靠訊息一致方案中的事務訊息保證本地事務與訊息的原子性,最終將通知先發給MQ,
2、通知程式監聽MQ,接收MQ的訊息,
方案1中接收通知方直接監聽MQ,方案2中由通知程式監聽MQ,
通知程式若沒有回應ack則MQ會重復通知,
3、通知程式通過互聯網介面協議(如http、webservice)呼叫接收通知方案介面,完成通知,
通知程式呼叫接收通知方案介面成功就表示通知成功,即消費MQ訊息成功,MQ將不再向通知程式投遞通知訊息,
4、接收通知方可通過訊息校對介面來校對訊息的一致性,
方案1和方案2的不同點 :
1、方案1中接收通知方與MQ介面,即接收通知方案監聽MQ,此方案主要應用與內部應用之間的通知,
2、方案2中由通知程式與MQ介面,通知程式監聽MQ,收到MQ的訊息后由通知程式通過互聯網介面協議呼叫接收通知方,此方案主要應用于外部應用之間的通知,例如支付寶、微信的支付結果通知,

6.3.RocketMQ實作最大努力通知型事務

6.3.1.業務說明

本實體通過RocketMq中間件實作最大努力通知型分布式事務,模擬充值程序,
本案例有賬戶系統和充值系統兩個微服務,其中賬戶系統的資料庫是bank1資料庫,其中有張三賬戶,充值系統的資料庫使用bank1_pay資料庫,記錄了賬戶的充值記錄,
業務流程如下圖 :
在這里插入圖片描述
互動流程如下 :
1、用戶請求充值系統進行充值,
2、充值系統完成充值將充值結果發給MQ,
3、賬戶系統監聽MQ,接收充值結果通知,如果接收不到訊息,MQ會重復發送通知,接收到充值結果通知賬戶系統增加充值金額,
4、賬戶系統也可以主動查詢充值系統的充值結果查詢介面,增加金額,

6.3.2.程式組成部分

本示例程式組成部分如下 :
資料庫:MySQL-5.7.25
包括bank1和bank1_pay兩個資料庫,
JDK:64位 jdk1.8.0_201
rocketmq 服務端:RocketMQ-4.5.0
rocketmq 客戶端:RocketMQ-Spring-Boot-starter.2.0.2-RELEASE 微服務框架:spring-boot-2.1.3、spring-cloud-Greenwich.RELEASE
微服務及資料庫的關系 :
dtx/dtx-notifymsg-demo/dtx-notifymsg-demo-bank1 銀行1,操作張三賬戶, 連接資料庫bank1 dtx/dtx-notifymsg-demo/dtx-notifymsg-demo-pay 銀行2,操作充值記錄,連接資料庫bank1_pay
在這里插入圖片描述
互動流程如下 :
1、用戶請求充值系統進行充值,
2、充值系統完成充值將充值結果發給MQ,
3、賬戶系統監聽MQ,接收充值結果通知,如果接收不到訊息,MQ會重復發送通知,接收到充值結果通知賬戶系統增加充值金額,
4、賬戶系統也可以主動查詢充值系統的充值結果查詢介面,增加金額,

6.3.3.創建資料庫

創建bank1庫,并匯入以下表結構和資料(包含張三賬戶)

CREATE DATABASE `bank1` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
DROP TABLE IF EXISTS `account_info`; CREATE TABLE `account_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`account_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '戶 主姓名',
`account_no` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '銀行卡號',
`account_password` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT
'帳戶密碼',
`account_balance` double NULL DEFAULT NULL COMMENT '帳戶余額', PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
INSERT INTO `account_info` VALUES (2, '張三的賬戶', '1', '', 10000);
DROP TABLE IF EXISTS `de_duplication`; CREATE TABLE `de_duplication` (
`tx_no` varchar(64) COLLATE utf8_bin NOT NULL, `create_time` datetime(0) NULL DEFAULT NULL, PRIMARY KEY (`tx_no`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

創建bank1_pay庫,并匯入以下表結構:

 CREATE DATABASE `bank1_pay` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; CREATE TABLE `account_pay` (
`id` varchar(64) COLLATE utf8_bin NOT NULL,
`account_no` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '賬號', `pay_amount` double NULL DEFAULT NULL COMMENT '充值余額',
`result` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '充值結果:success,fail',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

6.3.4.啟動RocketMQ

rocketMQ啟動方式與RocketMQ實作可靠訊息最終一致性事務中完全一致

6.3.5.discover-server

discover-server是服務注冊中心,測驗工程將自己注冊至discover-server,

6.3.6.工程概述

(1)父工程maven依賴說明
在dtx父工程中指定了SpringBoot和SpringCloud版本

<dependency> 
	<groupId>org.springframework.boot</groupId> 
	<artifactId>spring‐boot‐dependencies</artifactId>      					   <version>2.1.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency> 
	<groupId>org.springframework.cloud</groupId> 
	<artifactId>spring‐cloud‐dependencies</artifactId> 	<version>Greenwich.RELEASE</version>
 	<type>pom</type>
	<scope>import</scope>
</dependency>

在dtx-notifymsg-demo父工程中指定了rocketmq-spring-boot-starter的版本,

 <dependency>
	<groupId>org.apache.rocketmq</groupId> 
	<artifactId>rocketmq‐spring‐boot‐starter</artifactId> 
	<version>2.0.2</version>
</dependency>

(2)配置rocketMQ
在application-local.properties中配置rocketMQ nameServer地址及生產組 :

rocketmq.producer.group = producer_bank2
rocketmq.name-server = 127.0.0.1:9876

6.3.7 dtx-notifydemo-pay

dtx-notifydemo-pay實作如下功能 :
1、充值介面;
2、充值完成要通知;
3、充值結果查詢介面,
(2)Dao

@Mapper
@Component
public interface AccountPayDao {
@Insert("insert into account_pay(id,account_no,pay_amount,result) values(#{id},# {accountNo},#{payAmount},#{result})")
int insertAccountPay(@Param("id") String id,@Param("accountNo") String accountNo, @Param("payAmount") Double pay_amount,@Param("result") String result);
@Select("select id,account_no accountNo,pay_amount payAmount,result from account_pay where id=#{txNo}")
AccountPay findByIdTxNo(@Param("txNo") String txNo); 
}

(3)Service

@Service
@Slf4j
public class AccountPayServiceImpl implements AccountPayService{
@Autowired
RocketMQTemplate rocketMQTemplate;
@Autowired
AccountPayDao accountPayDao;
@Transactional
@Override
public AccountPay insertAccountPay(AccountPay accountPay) {
	int result = accountPayDao.insertAccountPay(accountPay.getId(),
	accountPay.getAccountNo(), accountPay.getPayAmount(), "success");
	if(result>0){ //發送通知
		rocketMQTemplate.convertAndSend("topic_notifymsg",accountPay);
		return accountPay; 
	}
	return null; 
}
	@Override
	public AccountPay getAccountPay(String txNo) {
		AccountPay accountPay = accountPayDao.findByIdTxNo(txNo);
 		return accountPay; 
 	}
}

(4)Controller

@RestController
public class AccountPayController {
@Autowired
AccountPayService accountPayService;
//充值
@GetMapping(value = "/paydo")
public AccountPay pay(AccountPay accountPay){
	//事務號
	String txNo = UUID.randomUUID().toString(); accountPay.setId(txNo);
	return accountPayService.insertAccountPay(accountPay);
}
//查詢充值結果
@GetMapping(value = "/payresult/{txNo}")
public AccountPay payresult(@PathVariable("txNo") String txNo){
		return accountPayService.getAccountPay(txNo); 
	}
}

6.3.8 dtx-notifydemo-bank1

dtx-notifydemo-bank1實作如下功能 :
1、監聽MQ,接收充值結果,根據充值結果完成賬戶金額修改,
2、主動查詢充值系統,根據充值結果完成賬戶金額修改,
1)Dao

 @Mapper
@Component
public interface AccountInfoDao {
	//修改賬戶金額
	@Update("update account_info set account_balance=account_balance+#{amount} where account_no=#{accountNo}")
	int updateAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount);
	//查詢冪等記錄,用于冪等控制
	@Select("select count(1) from de_duplication where tx_no = #{txNo}") 
	int isExistTx(String txNo);
	//添加事務記錄,用于冪等控制
	@Insert("insert into de_duplication values(#{txNo},now());") 
	int addTx(String txNo);
}

2)AccountInfoService

@Service
@Slf4j
public class AccountInfoServiceImpl implements AccountInfoService {
	@Autowired
	AccountInfoDao accountInfoDao;
	@Autowired
	PayClient payClient; /**
	* 更新帳號余額,并發送訊息 *
	* @param accountChange */
	@Transactional
	@Override
	public void updateAccountBalance(AccountChangeEvent accountChange) {
	//冪等校驗
	int existTx = accountInfoDao.isExistTx(accountChange.getTxNo()); if(existTx >0){
	log.info("已處理訊息:{}", JSONObject.toJSONString(accountChange));
	return ; }
	//添加事務記錄 accountInfoDao.addTx(accountChange.getTxNo()); //更新賬戶金額
	accountInfoDao.updateAccountBalance(accountChange.getAccountNo(),accountChange.getAmount()); }
	/**
	* 主動查詢充值結果 *
	* @param tx_no */
	@Override
	public AccountPay queryPayResult(String tx_no) {
		//主動請求充值系統查詢充值結果
		AccountPay accountPay = payClient.queryPayResult(tx_no); //充值結果
		String result = accountPay.getResult(); 
		log.info("主動查詢充值結果:{}", 		JSON.toJSONString(accountPay)); 
		if("success".equals(result)){
			AccountChangeEvent accountChangeEvent = new AccountChangeEvent();
			accountChangeEvent.setAccountNo(accountPay.getAccountNo());
			accountChangeEvent.setAmount(accountPay.getPayAmount());
			accountChangeEvent.setTxNo(accountPay.getId());
			updateAccountBalance(accountChangeEvent);
		}
		return accountPay; 
	}
}
@FeignClient(value = "dtx‐notifymsg‐demo‐pay", fallback = PayFallback.class)
public interface PayClient {
	@GetMapping("/pay/payresult/{txNo}")
	AccountPay queryPayResult(@PathVariable("txNo") String txNo); 
}
@Component
public class PayFallback implements PayClient {
	@Override
	public AccountPay queryPayResult(String txNo) {
		AccountPay accountPay = new AccountPay();
		accountPay.setResult("fail");
		return accountPay;
	} 
}

3)監聽MQ

@Component
@Slf4j
@RocketMQMessageListener(topic="topic_notifymsg",consumerGroup="consumer_group_notifymsg_bank1") 
public class NotifyMsgListener implements RocketMQListener<AccountPay> {
	@Autowired
	AccountInfoService accountInfoService;
	@Override
	public void onMessage(AccountPay accountPay) {
		log.info("接收到訊息:{}", JSON.toJSONString(accountPay)); 
		AccountChangeEvent accountChangeEvent = new AccountChangeEvent();
		accountChangeEvent.setAmount(accountPay.getPayAmount());
		accountChangeEvent.setAccountNo(accountPay.getAccountNo());
		accountChangeEvent.setTxNo(accountPay.getId());
		accountInfoService.updateAccountBalance(accountChangeEvent); 
		log.info("處理訊息完成:{}", JSON.toJSONString(accountChangeEvent));
	} 
}

4)Controller

@RestController
@Slf4j
public class AccountInfoController {
	@Autowired
	private AccountInfoService accountInfoService;
		//主動查詢充值結果
		@GetMapping(value = "/payresult/{txNo}")
		public AccountPay result(@PathVariable("txNo") String txNo){
		AccountPay accountPay = accountInfoService.queryPayResult(txNo);
		return accountPay; 
	}
}

6.3.9 測驗場景

  • 充值系統充值成功,賬戶系統主動查詢充值結果,修改賬戶金額,
  • 充值系統充值成功,發送訊息,賬戶系統接收訊息,修改賬戶金額,
  • 賬戶系統修改賬戶金額冪等測驗,

6.4. 小結

最大努力通知方案是分布式事務中對一致性要求最低的一種,適用于一些最終一致性時間敏感度低的業務;
最大努力通知方案需要實作如下功能 :
1、訊息重復通知機制,
2、訊息校對機制,

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

標籤:架構設計

上一篇:JSP+Servlet 實作:理財產品資訊管理系統

下一篇:【高可用架構】開發機上部署Deploy專案(一)

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