2022年1月9日 星期日

新手學Docker 基本概念

有裝的vm的人都知道,當一台機器需要有兩個作業系統時,windows + Linux 怎麼辦? 最快的方法就是虛擬環境 VM,但需要切割一小塊的記憶體和空間,而且還需要安裝整個作業系統耶~ 於是有人提出了好方法 ,只要需要一小塊的空間 (Container) 容器,裝戴著部份核心的作業系統(比vm 更加的輕量化,就可以執行不同作業系統的功能,另外docker 不是用取代VM的,如果僅需要某些作業系統的核心或函式庫等就很適合Docker用法。

但是想瞭解docker ,網路上有太多的名詞【映像檔Image】、【容器Container】、【倉庫Responsiory】越聽越胡塗,簡單的說如比你有一個windows作業系統的碟片這我們稱之為image,你將光碟片的東西安裝起來後執行的作業系統稱為container,我的解讀是這個意思,但專業術語還是看以下的說明吧

原作者: https://cwhu.medium.com/docker-tutorial-101-c3808b899ac6

l  映像檔 Image

Docker 映像檔是一個模板,用來重複產生容器實體。例如:一個映像檔裡可以包含一個完整的 MySQL 服務、一個 Golang 的編譯環境、或是一個 Ubuntu 作業系統。

透過 Docker 映像檔,我們可以快速的產生可以執行應用程式的容器。而 Docker 映像檔可以透過撰寫由命令行構成的 Dockerfile 輕鬆建立,或甚至可以從公開的地方下載已經做好的映像檔來使用。

l  容器 Container

就像是用蛋糕模具烤出來的蛋糕本體,容器是用映像檔建立出來的執行實例。它可以被啟動、開始、停止、刪除。每個容器都是相互隔離、保證安全的平台。,Docker 映像檔是唯讀(read-only)的,而容器在啟動的時候會建立一層可以被修改的可寫層作為最上層,讓容器的功能可以再擴充。這點在下面的實例會有更多補充。

l  倉庫 Repository

倉庫(Repository)是集中存放映像檔的場所,也可以想像成存放蛋糕模具的大本營。倉庫註冊伺服器(Registry)上則存放著多個倉庫,你可以任易的取用使用透過docker 的指令,你可以在上面建立多個倉庫,然後透過 pushpull 的方式上傳、存取。

 l  啟用hyper-v

筆者用自身的經驗告訴大家如何安裝吧

如果你是 Windows 的專業版,就可以順利的點選以下的Hyper-Vtool

因為我的作業系統是window 10 家用版想啟用Hyper-V 的管理工具,沒有發現相關的選項~ 後續查相關文件發現是Windows home 不支援… WSDL, 我只能先用powershell 指令執行wsdl2

相關文件 : https://docs.microsoft.com/zh-tw/windows/wsl/install-manual

步驟一: 啟用windows 子系統linux

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

步驟二: 啟用VM

dism.exe/online/enable-feature/featurename:VirtualMachinePlatform/all/norestart

步驟三: 下戴Linux 核心更新套件

https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

步驟四: wsl2 設為預設版本

wsl --set-default-version 2

以上做完後~ 恭喜你完成第一步了…  

l  安裝docker

相關文件: https://docs.docker.com/desktop/windows/install/

下戴點

https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe

 如果各位順利安裝完畢先恭喜各位完成docker安裝囉








2021年1月7日 星期四

SQL LOCK的情境介紹

  

一、Uplock 更新鎖 

用於可更新的資源上。防止當多個工作階段正在讀取、鎖定及後來可能更新資源時發生常見的死結


二、ReadPast 系統會略過資料被鎖定的資料列,取回未被鎖定的資料列 

以上兩個功能搭配的話,不會讓資料一直被鎖定中,如果交易發生碰撞行為時,會另外取得未被鎖定的資料,減少碰撞的機率。 

視窗A:

USE joyceRemine

GO

 BEGIN TRANSACTION Transaction1 

 SELECT TOP 10 * FROM issues WITH (UPDLOCK,READPAST) order by # asc 

 WAITFOR DELAY '00:00:30' 

ROLLBACK


同時另開新視窗

視窗B:

SELECT TOP 10 * FROM issues WITH (UPDLOCK,READPAST) order by # asc

結果如下 : 視窗B撈出另外10筆資料,不會與A視窗的資料重複

視窗A                       視窗B

 

 

 如果搭配update 語法 

 

BEGIN TRANSACTION Transaction1

        UPDATE issues

        SET 更新日期 = GETDATE()

        WHERE # in (SELECT TOP 10 # FROM issues WITH (UPDLOCK,READPAST) order by # asc ) 

 WAITFOR DELAY '00:00:10'

COMMIT

 這種語法就不用擔心死結了,就算同時大量湧進資料表執行這隻SPX,也不會更新同一批的資料囉~   

2018年11月26日 星期一

Sails(v1) + Vue.js 完整攻略


Sails(v1) + Vue.js 完整攻略

一、Sails 架構簡易說明

新增sails  : 一句指令搞定
npm install sails -g

開啟新的專案
sails new test-project  開啟新的

依指示進行(選擇1:web App) , sails v1 改版 vue.js 列為為前端工具

啟動專案
sails lift

當然~ 他的網頁架構非常的複雜,一時之間也很難說明,依主架構分如下

1.         Controller : 邏輯層:  依頁面名稱來放置位置

範例1: Page頁面的controller

module.exports = {
  exits: {
    success: {
      viewTemplatePath: 'pages/dispatch/add-cases',
    },

    redirect: {
      description: 'The requesting user is already logged in.',
      responseType: 'redirect'
    }
  },
  fn: async function (inputs, exits) {
    return exits.success();
  }
};

ViewTemplatePath: 使用Pages 頁面,如果沒設定頁面時,通常是用來呼叫資料或存取資料用,例如WEB API

範例2: 傳入資料,並寫入資料
module.exports = {

  inputs: {
    title:{
      required: true,
      type: 'string',
      description:"請說明任務名稱"
     },
     content:{
      required: false,
      type: 'string',
      description:"請說明任務內容"
     },
     caseType:{
      required: true,
      type: 'number',
      description:"任務選項"
     },
     dispatchTime:{
      required: true,
      type: 'string',
      description:"任務日期"
     }
  },

  exits: {
    success: {
      description: 'The message was sent successfully.'
    }

  },
  fn: async function(inputs, exits) {
    console.log(inputs);
    await Cases.create(
      {
        title:inputs.title,
        content:inputs.content,
        caseType:inputs.caseType,
        dispatchTime:inputs.dispatchTime
      }
     );
     console.log(this.req);
    return exits.success();
  }
};

Fn: 函式用inputs 接收頁面傳回的資料,Inputs的值型別,要事先宣告
物件型別,之後透過前端頁面傳入inputs欄位值,並將值存入資料表

直接新增/修改/刪除資料,參考以下官方文件: https://sailsjs.com/documentation/reference/waterline-orm/models
有更多關於資料的methods使用說明

2.         Model : 建立資料層 (建立資料表的欄位)

module.exports = {
  attributes: {
    title: {
      type: 'string'
    },
    content: {
      type: 'string'
    },
    caseType: {
      type: 'number'
    },
    startDate: {
      type: 'string'
    },
    endDate: {
      type: 'string'
    },
    startLocation: {
      type: 'string'
    },
    endLocation: {
      type: 'string'
    }
  },
};

如同資料表,訂好資料模組存取的型態和名稱

3.         Vue.js
引用vue.JS , 讓原本的sails的頁面EJS (HTMLJavaScript) 分離

Assets/JS/pages/ dispatch/list-cases.js :
//sails 中的寫法, parasails.registePage 宣告對應頁面名稱
parasails.registerPage("list-cases",{
    data:{
        lists:[],
    },
    beforeMount: function() {
        // Attach raw data exposed by the server.
        _.extend(this, window.SAILS_LOCALS);//讀取controller傳入參數
      },
      methods: {
        edit(){
            alert("你確定要修改嗎?");
        },
      }
});

如果有從controller端傳回資料到View中,需要事先在beforeMount window.SAILS_LOCALS 加到this 物件中

Views/pages/dispatch/list-cases.ejs (畫面)
//id的值,呼應parasails.registePage,所以id名稱不能重複
<div id="list-cases" v-cloak> 
    <table class="table table-striped">
        <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">標題</th>
                <th scope="col">內文</th>
                <th scope="col">日期</th>
                <th>功能</th>
            </tr>
        </thead>
        <tbody>
//list並未喧告在Vue.js, 資料是直接從sailscontroller的值
            <tr v-for="(item, index) in lists">
                <th scope="row">
                    <div class="checkbox">
                        <label><input type="checkbox" value=""></label>
                    </div>
                </th>
                <td>{{item.title}}</td>
                <td>{{item.content}}</td>
                <td>{{item.dispatchTime}}</td>
                <td>
                    <a href=# @click="edit"> <span style="font-size: 18px; color:coral;">
                            <i class="far fa-edit"></i>
                        </span>
                    </a>
                    &nbsp;
                    <a href=#>
                        <span style="font-size: 18px; color: Dodgerblue;">
                            <i class="fas fa-trash"></i>
                        </span>
                    </a>
                </td>
            </tr>
        </tbody>
    </table>
</div>
<%- /* Expose locals as `window.SAILS_LOCALS` :: */ exposeLocalsToBrowser() %>
//在畫面最下面,一定要加這一行
VUE.js要讀取到window.SAILS_LOCALS物件,而這是唯一從sailscontroller讀取傳回參數的方法之一,官方說法,這樣才會安全性,如果有興趣的朋友可以再深入研究相關的話題。

Controller: 
module.exports = {
    exits: {
      success: {
        responseType: 'view',
        viewTemplatePath: 'pages/dispatch/list-cases',
      },
 
      redirect: {
        description: 'The requesting user is already logged in.',
        responseType: 'redirect'
      }
    },
   
    fn: async function (inputs, exits) {
      var lists = await Cases.find();//讀取所有Cases的所有資料列
      return exits.success({lists: lists}); //傳回參數
    }
  };



設定mongoDB

Config /datastores.js

module.exports.datastores = {
  default: {
   adapter: 'sails-mongo',
   url: 'mongodb://root@localhost/foo'
  },
};

如果是本機端有mongoServer : mongodb://root@localhost/dbname  , 如果是遠端mongoDB Server 就要設遠端的連線。

Config/ Model.js
module.exports.models = {
  schema: true,
  migrate: 'alter',
  attributes: {
    createdAt: { type: 'number', autoCreatedAt: true, },
    updatedAt: { type: 'number', autoUpdatedAt: true, },
    id: {  type: 'string', columnName: '_id' },
    //---------------------------------------
    //  /\   Using MongoDB?
    //  ||   Replace `id` above with this instead:
    //
    // ```
    // id: { type: 'string', columnName: '_id' },
    // ```
    //
    // Plus, don't forget to configure MongoDB as your default datastore:
    // https://sailsjs.com/docs/tutorials/using-mongo-db
    //--------------------------------------------------
  },

mongoDB_id取代原本的id項目

設定routing
module.exports.routes = {
 
  'GET /dispatch/addCases': { action: 'dispatch/add-cases' },
  'GET /dispatch/listCases':{ action: 'dispatch/list-cases' },
  'POST  /api/v1/dispatch/saveCases':
 { action: 'dispatch/save-cases' },
};


所有POST/GET 的網址都要在Config/routes.js 設定

設定Assets/JS/ Cloud.setup.js
Cloud.setup({

  /* eslint-disable */
  methods: {"saveCases":
{"verb":"POST","url":"/api/v1/dispatch/saveCases","args":["title","content","caseType","dispatchTime","dispatchTime"]}
  /* eslint-enable */

});

將參數結果送出某個controller (前端語法),再由後端controllerinputs 變數接收下來,參數一定要一致,否則無法傳送到後端喔這很重要!!!!

儲存頁面

列表:
以上是簡單的介紹喔~