主頁 >  其他 > 豬齒魚平臺中的微服務資料一致性解決方案

豬齒魚平臺中的微服務資料一致性解決方案

2022-01-17 17:20:41 其他

眾所周知,微服務架構解決了很多問題,通過分解復雜的單體式應用,在功能不變的情況下,使應用被分解為多個可管理的服務,為采用單體式編碼方式很難實作的功能提供了模塊化的解決方案,同時,每個微服務獨立部署、獨立擴展,使得持續化集成成為可能,由此,單個服務很容易開發、理解和維護,

微服務架構為開發帶來了諸多好處的同時,也引發了很多問題,比如服務運維變得更復雜,服務之間的依賴關系更復雜,資料一致性難以保證,

本篇文章將討論和介紹豬齒魚是如何保障微服務架構的資料一致性的,

主要內容包括 :

  • 傳統應用使用本地事務保持一致性
  • 多資料源下的分布式事務
  • 微服務架構中應滿足資料最終一致性原則
  • 使用Event Sourcing保證微服務的最終一致性
  • 使用可靠事件模式保證微服務的最終一致性
  • 使用Saga保證微服務的最終一致性

下面將通過一個實體來分別介紹這幾種模式,

在Choerodon 豬齒魚的 DevOps流程中,有這樣一個步驟,

  1. 用戶在Choerodon 平臺上創建一個專案;
  2. DevOps 服務對應創建一個專案;
  3. DevOps 為該專案 在 Gitlab 上創建對應的group,

傳統應用使用本地事務保持一致性

在講微服務架構的資料一致性之前,先介紹一下傳統關系型資料庫是如何保證一致性的,從關系型資料庫中的ACID理論講起,

ACID 即資料庫事務正確執行的四個基本要素,分別是:

  • 原子性(Atomicity):要么全部完成,要么全部不完成,不存在中間狀態
  • 一致性(Consistency):事務必須始終保持系統處于一致的狀態
  • 隔離性(Isolation):事務之間相互隔離,同一時間僅有一個請求用于同一資料
  • 持久性(Durability):事務一旦提交,該事務對資料庫所作的更改便持久的保存在資料庫之中,并不會被回滾

可以通過使用資料庫自身的ACID Transactions,將上述步驟簡化為如下偽代碼:

transaction.strat();
createProject();
devopsCreateProject();
gitlabCreateGroup();
transaction.commit();

這個程序可以說是十分簡單,如果在這一程序中發生失敗,例如DevOps創建專案失敗,那么該事務做回滾操作,使得最終平臺創建專案失敗,由于傳統應用一般都會使用一個關系型資料庫,所以可以直接使用 ACID transactions, 保證了資料本身不會出現不一致,為保證一致性只需要:開始一個事務,改變(插入,洗掉,更新)很多行,然后提交事務(如果有例外時回滾事務),

隨著業務量的不斷增長,單資料庫已經不足以支撐龐大的業務資料,此時就需要對應用和資料庫進行拆分,于此同時,也就出現了一個應用需要同時訪問兩個或者兩個以上的資料庫或多個應用分別訪問不同的資料庫的情況,資料庫的本地事務則不再適用,

為了解決這一問題,分布式事務應運而生,

多資料源下的分布式事務

想象一下,如果很多用戶同時對Choerodon 平臺進行創建專案的操作,應用接收的流量和業務資料劇增,一個資料庫并不足以存盤所有的業務資料,那么我們可以將應用拆分成IAM服務和DevOps服務,其中兩個服務分別使用各自的資料庫,這樣的情況下,我們就減輕了請求的壓力和資料庫訪問的壓力,兩個分別可以很明確的知道自己執行的事務是成功還是失敗,但是同時在這種情況下,每個服務都不知道另一個服務的狀態,因此,在上面的例子中,如果當DevOps創建專案失敗時,就無法直接使用資料庫的事務,

那么如果當一個事務要跨越多個分布式服務的時候,我們應該如何保證事務呢?

為了保證該事務可以滿足ACID,一般采用2PC或者3PC, 2PC(Two Phase Commitment Protocol),實作分布式事務的經典代表就是兩階段提交協議,2PC包括準備階段和提交階段,在此協議中,一個或多個資源管理器的活動均由一個稱為事務協調器的單獨軟體組件來控制,

我們為DevOps服務分配一個事務管理器,那么上面的程序可以整理為如下兩個階段:

準備階段:

提交/回滾階段:

2PC 提供了一套完整的分布式事務的解決方案,遵循事務嚴格的 ACID 特性,

但是,當在準備階段的時候,對應的業務資料會被鎖定,直到整個程序結束才會釋放鎖,如果在高并發和涉及業務模塊較多的情況下,會對資料庫的性能影響較大,而且隨著規模的增大,系統的可伸縮性越差,同時由于 2PC引入了事務管理器,如果事務管理器和執行的服務同時宕機,則會導致資料產生不一致,雖然又提出了3PC 將2PC中的準備階段再次一分為二的來解決這一問題,但是同樣可能會產生資料不一致的結果,

微服務架構中應滿足資料最終一致性原則

不可否認,2PC 和3PC 提供了解決分布式系統下事務一致性問題的思路,但是2PC同時又是一個非常耗時的復雜程序,會嚴重影響系統效率,在實踐中我們盡量避免使用它,所以在分布式系統下無法直接使用此方案來保證事務,

對于分布式的微服務架構而言,傳統資料庫的ACID原則可能并不適用,首先微服務架構自身的所有資料都是通 過API 進行訪問,這種資料訪問方式使得微服務之間松耦合,并且彼此之間獨立非常容易進行性能擴展,其次 不同服務通常使用不同的資料庫,甚至并不一定會使用同一類資料庫,反而使用非關系型資料庫,而大部分的 非關系型資料庫都不支持2PC,

在這種情況下,又如何解決事務一致性問題呢?

一個最直接的辦法就是考慮資料的強一致性,根據Eric Brewer提出的CAP理論,只能在資料強一致性(C)和可用性(A)之間做平衡,

CAP 是指在一個分布式系統下,包含三個要素:Consistency(一致性)、Availability(可用性)、Partition tolerance(磁區容錯性),并且三者不可得兼,

  • 一致性(Consistency),是指對于每一次讀操作,要么都能夠讀到最新寫入的資料,要么錯誤,所有資料變動都是同步的,
  • 可用性(Availability),是指對于每一次請求,都能夠得到一個及時的、非錯的回應,但是不保證請求的結果是基于最新寫入的資料,即在可以接受的時間范圍內正確地回應用戶請求,
  • 磁區容錯性(Partition tolerance),是指由于節點之間的網路問題,即使一些訊息丟包或者延遲,整個系統仍能夠提供滿足一致性和可用性的服務,

關系型資料庫單節點保證了資料強一致性(C)和可用性(A),但是卻無法保證磁區容錯性(P),

然而在分布式系統下,為了保證模塊的磁區容錯性(P),只能在資料強一致性(C)和可用性(A)之間做平衡,具體表現為在一定時間內,可能模塊之間資料是不一致的,但是通過自動或手動補償后能夠達到最終的一致,

可用性一般是更好的選擇,但是在服務和資料庫之間維護事務一致性是非常根本的需求,微服務架構中應該選擇滿足最終一致性,

那么我們應該如何實作資料的最終一致性呢?

使用Event Sourcing保證微服務的最終一致性

什么是Event Sourcing(事件溯源)?

一個物件從創建開始到消亡會經歷很多事件,傳統的方式是保存這個業務物件當前的狀態,但更多的時候,我們也許更關心這個業務物件是怎樣達到這一狀態的,Event Sourcing從根本上和傳統的資料存盤不同,它存盤的不是業務物件的狀態,而是有關該業務物件一系列的狀態變化的事件,只要一個物件的狀態發生變化,服務就需要自動發布事件來附加到事件的序列中,這個操作本質上是原子的,

現在將上面的訂單程序用Event Sourcing 進行改造,將訂單變動的一個個事件存盤起來,服務監聽事件,對訂單的狀態進行修改,

可以看到 Event Sourcing 完整的描述了物件的整個生命周期程序中所經歷的所有事件,由于事件是只會增加不會修改,這種特性使得領域模型十分的穩定,

Event sourcing 為整體架構提供了一些可能性,但是將應用程式的每個變動都封裝到事件保存下來,并不是每個人都能接受的風格,而且大多數人都認為這樣很別扭,同時這一架構在實際應用實踐中也不是特別的成熟,

使用可靠事件模式保證微服務的最終一致性

可靠事件模式屬于事件驅動架構,微服務完成操作后向訊息代理發布事件,關聯的微服務從訊息代理訂閱到該 事件從而完成相應的業務操作,關鍵在于可靠事件投遞和避免事件重復消費,

可靠事件投遞有兩個特性:

  1. 每個服務原子性的完成業務操作和發布事件;
  2. 訊息代理確保事件投遞至少一次 (at least once),避免重復消費要求消費事件的服務實作冪等性,

有兩種實作方式:

1. 本地事件表

本地事件表方法將事件和業務資料保存在同一個資料庫中,使用一個額外的“事件恢復”服務來恢 復事件,由本地事務保證更新業務和發布事件的原子性,考慮到事件恢復可能會有一定的延時,服務在完成本 地事務后可立即向訊息代理發布一個事件,

使用本地事件表將事件和業務資料保存在同一個資料庫中,會在每個服務存盤一份資料,在一定程度上會造成代碼的重復冗余,同時,這種模式下的業務系統和事件系統耦合比較緊密,額外增加的事件資料庫操作也會給資料庫帶來額外的壓力,可能成為瓶頸,

2. 外部事件表

針對本地事件表出現的問題,提出外部事件表方法,將事件持久化到外部的事件系統,事件系統 需提供實時事件服務以接收微服務發布的事件,同時事件系統還需要提供事件恢復服務來確認和恢復事件,

借助Kafka和可靠事件,可以通過如下代碼實作訂單流程,

// IAM ProjectService

@Service
@RefreshScope
public class ProjectServiceImpl implements ProjectService {

    private ProjectRepository projectRepository;

    private UserRepository userRepository;

    private OrganizationRepository organizationRepository;

    @Value("${choerodon.devops.message:false}")
    private boolean devopsMessage;

    @Value("${spring.application.name:default}")
    private String serviceName;

    private EventProducerTemplate eventProducerTemplate;

    public ProjectServiceImpl(ProjectRepository projectRepository,
                              UserRepository userRepository,
                              OrganizationRepository organizationRepository,
                              EventProducerTemplate eventProducerTemplate) {
        this.projectRepository = projectRepository;
        this.userRepository = userRepository;
        this.organizationRepository = organizationRepository;
        this.eventProducerTemplate = eventProducerTemplate;
    }

    @Transactional(rollbackFor = CommonException.class)
    @Override
    public ProjectDTO update(ProjectDTO projectDTO) {
        ProjectDO project = ConvertHelper.convert(projectDTO, ProjectDO.class);
        if (devopsMessage) {
            ProjectDTO dto = new ProjectDTO();
            CustomUserDetails details = DetailsHelper.getUserDetails();
            UserE user = userRepository.selectByLoginName(details.getUsername());
            ProjectDO projectDO = projectRepository.selectByPrimaryKey(projectDTO.getId());
            OrganizationDO organizationDO = organizationRepository.selectByPrimaryKey(projectDO.getOrganizationId());
            ProjectEventPayload projectEventMsg = new ProjectEventPayload();
            projectEventMsg.setUserName(details.getUsername());
            projectEventMsg.setUserId(user.getId());
            if (organizationDO != null) {
                projectEventMsg.setOrganizationCode(organizationDO.getCode());
                projectEventMsg.setOrganizationName(organizationDO.getName());
            }
            projectEventMsg.setProjectId(projectDO.getId());
            projectEventMsg.setProjectCode(projectDO.getCode());
            Exception exception = eventProducerTemplate.execute("project", EVENT_TYPE_UPDATE_PROJECT,
                    serviceName, projectEventMsg, (String uuid) -> {
                        ProjectE projectE = projectRepository.updateSelective(project);
                        projectEventMsg.setProjectName(project.getName());
                        BeanUtils.copyProperties(projectE, dto);
                    });
            if (exception != null) {
                throw new CommonException(exception.getMessage());
            }
            return dto;
        } else {
            return ConvertHelper.convert(
                    projectRepository.updateSelective(project), ProjectDTO.class);
        }
    }
}
// DEVOPS DevopsEventHandler
@Component
public class DevopsEventHandler {

    private static final String DEVOPS_SERVICE = "devops-service";
    private static final String IAM_SERVICE = "iam-service";

    private static final Logger LOGGER = LoggerFactory.getLogger(DevopsEventHandler.class);

    @Autowired
    private ProjectService projectService;
    @Autowired
    private GitlabGroupService gitlabGroupService;

    private void loggerInfo(Object o) {
        LOGGER.info("data: {}", o);
    }

    /**
     * 創建專案事件
     */
    @EventListener(topic = IAM_SERVICE, businessType = "createProject")
    public void handleProjectCreateEvent(EventPayload<ProjectEvent> payload) {
        ProjectEvent projectEvent = payload.getData();
        loggerInfo(projectEvent);
        projectService.createProject(projectEvent);
    }

    /**
     * 創建組事件
     */
    @EventListener(topic = DEVOPS_SERVICE, businessType = "GitlabGroup")
    public void handleGitlabGroupEvent(EventPayload<GitlabGroupPayload> payload) {
        GitlabGroupPayload gitlabGroupPayload = payload.getData();
        loggerInfo(gitlabGroupPayload);
        gitlabGroupService.createGroup(gitlabGroupPayload);
    }
}

使用Saga保證微服務的最終一致性 - Choerodon的解決方案

Saga是來自于1987年Hector GM和Kenneth Salem論文,在他們的論文中提到,一個長活事務Long lived transactions (LLTs) 會相對較長的占用資料庫資源,如果將它分解成多個事務,只要保證這些事務都執行成功, 或者通過補償的機制,來保證事務的正常執行,這一個個的事務被他們稱之為Saga,

Saga將一個跨服務的事務拆分成多個事務,每個子事務都需要定義一個對應的補償操作,通過異步的模式來完 成整個Saga流程,

在Choerodon中,將專案創建流程拆分成多個Saga,

// ProjectService

    @Transactional
    @Override
    @Saga(code = PROJECT_CREATE, description = "iam創建專案", inputSchemaClass = ProjectEventPayload.class)
    public ProjectDTO createProject(ProjectDTO projectDTO) {

        if (projectDTO.getEnabled() == null) {
            projectDTO.setEnabled(true);
        }
        final ProjectE projectE = ConvertHelper.convert(projectDTO, ProjectE.class);
        ProjectDTO dto;
        if (devopsMessage) {
            dto = createProjectBySaga(projectE);
        } else {
            ProjectE newProjectE = projectRepository.create(projectE);
            initMemberRole(newProjectE);
            dto = ConvertHelper.convert(newProjectE, ProjectDTO.class);
        }
        return dto;
    }

    private ProjectDTO createProjectBySaga(final ProjectE projectE) {
        ProjectEventPayload projectEventMsg = new ProjectEventPayload();
        CustomUserDetails details = DetailsHelper.getUserDetails();
        projectEventMsg.setUserName(details.getUsername());
        projectEventMsg.setUserId(details.getUserId());
        ProjectE newProjectE = projectRepository.create(projectE);
        projectEventMsg.setRoleLabels(initMemberRole(newProjectE));
        projectEventMsg.setProjectId(newProjectE.getId());
        projectEventMsg.setProjectCode(newProjectE.getCode());
        projectEventMsg.setProjectName(newProjectE.getName());
        OrganizationDO organizationDO =
                organizationRepository.selectByPrimaryKey(newProjectE.getOrganizationId());
        projectEventMsg.setOrganizationCode(organizationDO.getCode());
        projectEventMsg.setOrganizationName(organizationDO.getName());
        try {
            String input = mapper.writeValueAsString(projectEventMsg);
            sagaClient.startSaga(PROJECT_CREATE, new StartInstanceDTO(input, "project", newProjectE.getId() + ""));
        } catch (Exception e) {
            throw new CommonException("error.organizationProjectService.createProject.event", e);
        }
        return ConvertHelper.convert(newProjectE, ProjectDTO.class);
    }
// DevopsSagaHandler
@Component
public class DevopsSagaHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(DevopsSagaHandler.class);
    private final Gson gson = new Gson();

    @Autowired
    private ProjectService projectService;
    @Autowired
    private GitlabGroupService gitlabGroupService;

    private void loggerInfo(Object o) {
        LOGGER.info("data: {}", o);
    }

    /**
     * 創建專案saga
     */
    @SagaTask(code = "devopsCreateProject",
            description = "devops創建專案",
            sagaCode = "iam-create-project",
            seq = 1)
    public String handleProjectCreateEvent(String msg) {
        ProjectEvent projectEvent = gson.fromJson(msg, ProjectEvent.class);
        loggerInfo(projectEvent);
        projectService.createProject(projectEvent);
        return msg;
    }

    /**
     * 創建組事件
     */
    @SagaTask(code = "devopsCreateGitLabGroup",
            description = "devops 創建 GitLab Group",
            sagaCode = "iam-create-project",
            seq = 2)
    public String handleGitlabGroupEvent(String msg) {
        ProjectEvent projectEvent = gson.fromJson(msg, ProjectEvent.class);
        GitlabGroupPayload gitlabGroupPayload = new GitlabGroupPayload();
        BeanUtils.copyProperties(projectEvent, gitlabGroupPayload);
        loggerInfo(gitlabGroupPayload);
        gitlabGroupService.createGroup(gitlabGroupPayload, "");
        return msg;
    }
}

可以發現,Saga和可靠事件模式很相似,都是將微服務下的事務作為一個個體,然后通過有序序列來執行,但是在實作上,有很大的區別,

可靠事件依賴于Kafka,消費者屬于被動監聽Kafka的訊息,鑒于Kafka自身的原因,如果對消費者進行橫向擴展,效果并不理想, 

而在 Saga 中,我們為 Saga 分配了一個orchestrator作為事務管理器,當服務啟動時,將服務中所有的 SagaTask 注冊到管理器中,當一個 Saga 實體通過sagaClient.startSaga啟動時,服務消費者就可以通過輪詢的方式主動拉取到該實體對應的Saga資料,并執行對應的業務邏輯,執行的狀態可以通過事務管理器進行查看,展現在界面上,

通過Choerodon的事務定義界面,將不同服務的SagaTask 收集展示,可以看到系統中的所有Saga 定義以及所屬的微服務,同時,在每一個Saga 定義的詳情中,可以詳細的了解到該Saga的詳細資訊:

在這種情況下,當并發量增多或者 SagaTask 的數量很多的時候,可以很便捷的對消費者進行擴展, 

Saga的補償機制

Saga支持向前和向后恢復:

  • 向后恢復:如果任意一個子事務失敗,則補償所有已完成的事務
  • 向前恢復:如果子事務失敗,則重試失敗的事務

Choerodon 采用的是向前恢復,通過界面可以很方便的對事務的資訊進行檢索,當Saga發生失敗時,也可以看到失敗的原因,并且手動進行重試,   通過Choerodon的事務實體界面,可以查詢到系統中運行的所有Saga實體,掌握實體的運行狀態,并對失敗的實體進行手動的重試:

對于向前恢復而言,理論上我們的子事務最終總是會成功的,但是在實際的應用中,可能因為一些其他的因素,造成失敗,那么就需要有對應的故障恢復回滾的機制,

使用Saga的要求 

Saga是一個簡單易行的方案,使用Saga的兩個要求: 

  • 冪等:冪等是每個Saga 多次執行所產生的影回應該和一次執行的影響相同,一個很簡單的例子,上述流程中,如果在創建專案的時候因為網路問題導致超時,這時如果進行重試,請求恢復,如果沒有冪等,就可能創建了兩個專案,
  • 可交換:可交換是指在同一層級中,無論先執行那個Saga最終的結果都應該是一樣的,

綜合比較

2PC是一個阻塞式,嚴格滿足ACID原則的方案,但是因為性能上的原因在微服務架構下并不是最佳 的方案,

Event sourcing 為整體架構提供了一些可能性,但是如果隨著業務的變更,事件結構自身發生一定的變化時,需要通過額外的方式來進行補償,而且當下并沒有一個成熟完善的框架,

基于事件驅動的可靠事件是建立在訊息佇列基礎上,每一個服務,除了自己的業務邏輯之外還需要額外的事件 表來保存當前的事件的狀態,所以相當于是把集中式的事務狀態分布到了每一個服務當中,雖然服務之間去中 心化,但是當服務增多,服務之間的分布式事務帶來的應用復雜度也再提高,當事件發生問題時,難以定位,

而Saga降低了資料一致性的復雜度,簡單易行,將所有的事務統一可視化管理,讓運維更加簡單,同時每一個 消費者可以進行快速的擴展,實作了事務的高可用,


本文由豬齒魚技術團隊原創,轉載請注明出處

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

標籤:其他

上一篇:深度介紹Flink在位元組跳動資料流的實踐

下一篇:影像處理技術(二)濾波去噪(下)

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

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more