主頁 > 後端開發 > AWS Lambda 借助 Serverless Framework,迅速起飛

AWS Lambda 借助 Serverless Framework,迅速起飛

2020-10-28 12:06:34 後端開發

前言

微服務架構有別于傳統的單體式應用方案,我們可將單體應用拆分成多個核心功能,每個功能都被稱為一項服務,可以單獨構建和部署,這意味著各項服務在作業時不會互相影響

這種設計理念被進一步應用,就變成了無服務(Serverless),「無服務」看似挺荒唐的,其實服務器依舊存在,只是我們不需要關注或預置服務器,這讓開發人員的精力更集中——只關注功能實作

Serverless 的典型便是 AWS Lambda

AWS Lambda

如果你是 Java 開發人員,你應該聽說過或使用過 JDK 1.8 里面的 Lambda,但是 AWS 中的 Lambda 和 JDK 中的 Lambda 沒有任何關系

這里的 AWS Lambda 就是一種計算服務,無需預置或管理服務器即可運行代碼,借助 Lambda,我們幾乎可以為任何型別的應用程式或后端服務運行代碼,而且完全無需管理,我們要做的只是上傳相應的代碼,Lambda 會處理運行和擴展 HA 代碼所需的一切作業

說的直白一點

Lambda 就好比實作某一個功能的方法 (現實中,通常會讓 Lambda 功能盡可能單一),我們將這個方法做成了一個服務供呼叫

到這里你可能會有個困惑,Lambda 既然就是一個「方法」,那誰來呼叫?或怎么來呼叫呢?

如何呼叫 Lambda

為了回答上面這個問題,我們需要登陸到 AWS,打開 Lambda 服務,然后創建一個 Lambda Function (hello-lambda)

Lambda 既然是個方法,就要選擇相應的 Runtime 環境,如下圖所示,總有一款適合你的(最近在用 Node.js, 這里就用這個吧)

點擊右下角的 Create function 按鈕進入配置頁面

在上圖紅色框線的位置就可以配置出發 Lambda 的觸發器了,點擊 Add trigger

從上圖可以看出,AWS 內置的很多服務都可以觸發 Lambda,我在作業中常用的有:

  • API Gateway (一會的 demo 會用到,也是最常見的呼叫方式)
  • ALB - Application Loac Balancer
  • CloudFront
  • DynamoDB
  • S3
  • SNS - Simple Notification Service
  • SQS - Simple Queue Service

上面只是 AWS 內置的一些服務,向下滑動,你會發現,你也可以配置很多非 AWS 的事件源

到這里,上面的問題你應該已經有了答案了,這里暫時先無需任何 trigger,先點擊右上角的 Test 測驗一下 Lambda

一個簡單的 Lambda Function 就實作了,紅色框線的 response 只是告訴大家,每個請求都會有相應的 Request ID,更有 START/END 標識快速定位 Log 內容 (可以通過 CloudWatch 查看,這里暫不展開說明)

你也可能已經開始發散你的思維了,如何運用 AWS Lambda,其實在 AWS 官網有很多樣例:

經典案例

比如為了適應多平臺圖片展示,一張原始圖片上傳到 S3 后,會通過 Lambda resize 適應不同平臺大小的圖片

比如使用 AWS Lambda 和 Amazon API Gateway 構建后端,以驗證和處理 API 請求,當某一個用戶發布一條動態,訂閱用戶將收到相應的通知

接下來我們就用 Lambda 實作經典的分布式訂單服務案例

訂單服務 Demo

為了增強用戶使用體驗,或者為了提升程式吞吐量,亦或是為了架構設計程式解耦,考慮到以上這些情況,我們通常都會借助訊息中間件來完成

假設有一常見場景,用戶下訂單時如果選擇開具發票,則需要呼叫發票服務,很顯然呼叫發票服務不是程式運行的關鍵路徑,這種場景,我們就可以通過訊息中間件來解耦,這里有兩個服務:

  1. 訂單服務
  2. 發票服務

如果用 Lambda 來實作兩個服務,整體設計思想就是這樣滴:

現實中,我們不可能在 AWS console 通過點擊按鈕來創建各個服務的,在 AWS 實際開發中, 我們通過寫 CloudFormation Template (以下會簡稱 CFT,其實就是一種 YAML 或者 JSON 格式的定義)來創建相關 AWS 服務,如果上述這個 Demo,從圖中可以看出,我們要創建的服務還是非常多的:

  • Lambda * 2
  • API Gateway
  • SQS

如果寫 AWS 原生的 CFT,要實作的內容還是挺多的

但是...... 懶惰的程式員總是能帶來很多驚喜

Serverless Framework

寫 JDBC 麻煩,就有了各種持久層框架的出現,同樣寫 AWS 原生 CFT 麻煩,就有了 Serverless Framework (以下會簡稱 SF)的出現幫助我們定義相關 Serverless 組件 (順便問一下,GraphQL 你們有在用嗎?)

SF 不但簡化了 AWS 原生 CFT 的撰寫,還簡化了跨云服務的定義,就好比設計模式當中的 Facade,在上面建立了一層門面,隱藏了底部不同服務的細節,降低了跨云并用云的門檻,目前支持的云服務有下面這些

這里暫時不會對 SF 展開深入的說明,在我們的 demo 中只不過是要應用 SF 來定義

安裝 Serverless Framework

如果你有安裝 Node,那只需要一條 npm 命令全域安裝即可:

npm update -g serverless

安裝過后檢查一下安裝版本是否成功

sls -version

配置 Serverless Framework

由于要使用 AWS 的 Lambda,所以要對 SF 做基本的配置,至少要讓 SF 有權限創建 AWS 服務,當你創建一個 AWS 用戶時,你可以獲取 AK 「access_key_id」和 SK 「secret_access_key」(不是 SKII 哦),其實就是一種用戶名和密碼形式

然后通過下面一條命令添加配置就可以了:

serverless config credentials --provider aws --key 1234 --secret 5678 --profile custom-profile
  • --provider 云服務商
  • --key 你的AK
  • --secret 你的SK
  • --profile 如果你有多個賬戶時,你可以添加這個 profile 做快速區分

運行上述命令后,就會在 ~/.aws/目錄創建一個名為 credentials 的檔案存盤上述配置,就像這樣:

到這里準備作業就都完成了,開始寫我們的定義就好了

創建 Serverless 應用

通過下面一條命令創建 serverless 應用

sls create --template aws-nodejs --path ./demo --name lambda-sqs-lambda
  • --template 指定創建的模版
  • --path 指定創建的目錄
  • --name 指定創建的服務名稱

運行上述命令后,進入 demo 目錄就是下面這個結構和內容了

?  demo tree
.
├── handler.js
└── serverless.yml

0 directories, 2 files

因為我們是用 Node.js 來撰寫 Serverless 應用,同樣在 demo 目錄下執行下面命令來初始化該目錄,因為我們后面要用到兩個 npm package

npm init -y

現在的結構是這樣的(其實就多了一個 package.json):

?  demo tree
.
├── handler.js
├── package.json
└── serverless.yml

0 directories, 3 files

至此,準備作業都已就緒,接下來就在 serverless.yml 中寫相應的定義就可以了 (門檻很低:按照相應的 key 寫 YAML 即可,是不是很簡單?),打開 serverless.yml 檔案來看一下,瞬間懵逼?

# Welcome to Serverless!
#
# This file is the main config file for your service.
# It's very minimal at this point and uses default values.
# You can always add more config options for more control.
# We've included some commented out config examples here.
# Just uncomment any of them to get that config option.
#
# For full config options, check the docs:
#    docs.serverless.com
#
# Happy Coding!

service: lambda-sqs-lambda
# app and org for use with dashboard.serverless.com
#app: your-app-name
#org: your-org-name

# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
# frameworkVersion: "=X.X.X"

provider:
  name: aws
  runtime: nodejs12.x

# you can overwrite defaults here
#  stage: dev
#  region: us-east-1

# you can add statements to the Lambda function's IAM Role here
#  iamRoleStatements:
#    - Effect: "Allow"
#      Action:
#        - "s3:ListBucket"
#      Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ]  }
#    - Effect: "Allow"
#      Action:
#        - "s3:PutObject"
#      Resource:
#        Fn::Join:
#          - ""
#          - - "arn:aws:s3:::"
#            - "Ref" : "ServerlessDeploymentBucket"
#            - "/*"

# you can define service wide environment variables here
#  environment:
#    variable1: value1

# you can add packaging information here
#package:
#  include:
#    - include-me.js
#    - include-me-dir/**
#  exclude:
#    - exclude-me.js
#    - exclude-me-dir/**

functions:
  hello:
    handler: handler.hello
#    The following are a few example events you can configure
#    NOTE: Please make sure to change your handler code to work with those events
#    Check the event documentation for details
#    events:
#      - http:
#          path: users/create
#          method: get
#      - websocket: $connect
#      - s3: ${env:BUCKET}
#      - schedule: rate(10 minutes)
#      - sns: greeter-topic
#      - stream: arn:aws:dynamodb:region:XXXXXX:table/foo/stream/1970-01-01T00:00:00.000
#      - alexaSkill: amzn1.ask.skill.xx-xx-xx-xx
#      - alexaSmartHome: amzn1.ask.skill.xx-xx-xx-xx
#      - iot:
#          sql: "SELECT * FROM 'some_topic'"
#      - cloudwatchEvent:
#          event:
#            source:
#              - "aws.ec2"
#            detail-type:
#              - "EC2 Instance State-change Notification"
#            detail:
#              state:
#                - pending
#      - cloudwatchLog: '/aws/lambda/hello'
#      - cognitoUserPool:
#          pool: MyUserPool
#          trigger: PreSignUp
#      - alb:
#          listenerArn: arn:aws:elasticloadbalancing:us-east-1:XXXXXX:listener/app/my-load-balancer/50dc6c495c0c9188/
#          priority: 1
#          conditions:
#            host: example.com
#            path: /hello

#    Define function environment variables here
#    environment:
#      variable2: value2

# you can add CloudFormation resource templates here
#resources:
#  Resources:
#    NewResource:
#      Type: AWS::S3::Bucket
#      Properties:
#        BucketName: my-new-bucket
#  Outputs:
#     NewOutput:
#       Description: "Description for the output"
#       Value: "Some output value"

乍一看,你可能覺得眼花繚亂,其實這是一個相對完整的 Lambda 配置全集,我們不需要這么詳細的內容,不過這個檔案作為我們的參考

接下來我們就定義 demo 所需要的一切 (關鍵注釋已經寫在代碼中)

service:
  name: lambda-sqs-lambda # 定義服務的名稱

provider:
  name: aws # 云服務商為 aws
  runtime: nodejs12.x # 運行時 node 的版本
  region: ap-northeast-1 # 發布到 northeast region,其實就是東京 region
  stage: dev # 發布環境為 dev
  iamRoleStatements: # 創建 IAM role,允許 lambda function 向佇列發送訊息
    - Effect: Allow
      Action:
        - sqs:SendMessage
      Resource:
        - Fn::GetAtt: [ receiverQueue, Arn ]
      
functions: # 定義兩個 lambda functions
  order:
    handler: app/order.checkout # 第一個 lambda function 程式入口是 app 目錄下的 order.js 里面的 checkout 方法
    events:	# trigger 觸發器是 API Gateway 的方式,當接收到 /order 的 POST 請求時觸發該 lambda function
      - http:
          method: post
          path: order

  invoice:
    handler: app/invoice.generate # 第二個 lambda function 程式入口是 app 目錄下的 invoice.js 里面的 generate 方法
    timeout: 30
    events: # trigger 觸發器是 SQS 服務,訊息佇列有訊息時觸發該 lambda function 消費訊息
      - sqs:
          arn:
            Fn::GetAtt:
              - receiverQueue
              - Arn
resources:
  Resources:
    receiverQueue: # 定義 SQS 服務,也是 Lambda 需要依賴的服務
      Type: AWS::SQS::Queue
      Properties:
        QueueName: ${self:custom.conf.queueName}

# package:
#   exclude:
#     - node_modules/**

custom: 
  conf: ${file(conf/config.json)} # 引入外部定義的配置變數

config.json 內容僅僅定義了 queue 的名稱,只是為了說明配置的靈活性

{
  "queueName": "receiverQueue"
}

因為我們要模擬訂單的生成,這里用 UUID 來模擬訂單號,

因為我們要呼叫 AWS 服務API,所以要使用 aws-sdk,

所以要安裝這兩個 package (這兩個理由夠充分嗎?)

{
  "name": "lambda-sqs-lambda",
  "version": "1.0.0",
  "description": "demo for lambda",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "license": "MIT",
  "dependencies": {
    "uuid": "^8.1.0"
  },
  "devDependencies": {
    "aws-sdk": "^2.6.15"
  }
}

接下來,我們就可以撰寫兩個 Lambda function 的代碼邏輯了

Order Lambda Function

訂單服務很簡單,接收一個下單請求,下單成功后快速回傳給用戶,同時將訂單下單成功的訊息發送到 SQS 中,供下游發票服務開具發票使用

'use strict';

const config = require('../conf/config.json')
const AWS = require('aws-sdk');
const sqs = new AWS.SQS();
const { v4: uuidv4 } = require('uuid');

module.exports.checkout = async (event, context, callback) => {
    console.log(event)
    let statusCode = 200
    let message

    if (!event.body) {
        return {
        statusCode: 400,
        body: JSON.stringify({
            message: 'No order body was found',
        }),
        };
    }

    const region = context.invokedFunctionArn.split(':')[3]
    const accountId = context.invokedFunctionArn.split(':')[4]
    const queueName = config['queueName']

    // 組裝 SQS 服務的 URL
    const queueUrl = `https://sqs.${region}.amazonaws.com/${accountId}/${queueName}`
    const orderId = uuidv4()

    try {
      	// 呼叫 SQS 服務
        await sqs.sendMessage({
            QueueUrl: queueUrl,
            MessageBody: event.body,
            MessageAttributes: {
                orderId: {
                    StringValue: orderId,
                    DataType: 'String',
                },
            },
        }).promise();

        message = 'Order message is placed in the Queue!';

  } catch (error) {
    console.log(error);
    message = error;
    statusCode = 500;
  }

  // 快速回傳訂單 ID
  return {
    statusCode,
    body: JSON.stringify({
      message, orderId,
    }),
  };
};

Invoice Lambda Function

發票服務邏輯同樣很簡單,消費 SQS 指定佇列中的訊息,并將開具出的發票發送到客戶訂單資訊的 email 中

module.exports.generate = (event, context, callback) => {
    console.log(event)
    try {
        for (const record of event.Records) {
          const messageAttributes = record.messageAttributes;
          console.log('OrderId is  -->  ', messageAttributes.orderId.stringValue);
          console.log('Message Body -->  ', record.body);
          const reqBody = JSON.parse(record.body)
          // 睡眠 20 秒,模擬生成發票的耗時程序
          setTimeout( () => {
              console.log("Receipt is generated and sent to :" + reqBody.email)
          }, 20000)
        }
    } catch (error) {
        console.log(error);
    }
}

到此 demo 的代碼就全部實作了,從中你可以看到:

我們沒有關注 lambda 的底層服務細節,沒有關注 sqs 的服務,只是簡單的代碼邏輯實作以及服務之間的串聯定義

最后我們看一下整體的目錄結構吧:

.
├── app
│   ├── invoice.js
│   └── order.js
├── conf
│   └── config.json
├── package.json
└── serverless.yml

2 directories, 5 files

發布 Lambda 應用

在發布之前,編譯一下應用,安裝必須的 package「uuid 和 aws-sdk」

npm install

發布應用非常簡單,只需要一條命令:

sls deploy -v

運行上述命令后大概需要等帶幾十秒鐘, 在構建的最后,會列印出我們的構建服務資訊:

上圖的 endpoints 就是我們一會要訪問的 API gateway 觸發 lambda 的入口,在呼叫之前,我們先到 AWS console 看一下我們定義的服務

lambda functions

SQS-receverQueue

API Gateway

S3

從上圖的構建資訊中你應該還看到一個 S3 bucket 的名稱,我們并沒有創建 S3, 這是 SF 自動幫我們創建,用來存盤 lambda zip package 的

測驗

呼叫 API gateway 的 endpoint 來測驗 lambda

打開 SQS 服務,你會發現,接收到一條訊息:

接下來我們看看 Invoice Lambda function 的消費情況,打開 CloudWatch 查看 log:

從 log 中可以看出程式“耗費” 20 秒后列印了向客戶郵件的 log(郵件也可以借助 AWS SES 郵件服務來實作)

至此,一個完整的 demo 就完成了,實際撰寫的代碼并沒有多少,就搞定了這么緊密的串聯

洗掉服務

Lambda 是按照呼叫次數進行收取費用的,為了防止造成額外的開銷,demo 結束后通常都會將服務銷毀,使用 SF 銷毀剛剛創建的服務也非常簡單,只需要在 serverless.yml 檔案目錄執行這條命令:

sls remove

總結與感受

AWS Lambda 是 Serverless 的典型,借助 Lambda 可以實作更小粒度的“服務”,無需服務搭建也加快了開發速度,Lambda 同樣可以結合 AWS 很多其服務,接收請求,將計算結果傳遞給下游服務等,另外很多第三方合作伙伴也在加入 Lambda 的 trigger 大部隊,給 Lambda 更多觸發可能,同時,借助 CI/CD,可以快速實作功能倍訓

開通 AWS free tier,足夠你玩轉 Lambda : https://dayarch.top/p/aws-lambda-with-serverless-framework.html

個人博客:https://dayarch.top
加我微信好友, 進群娛樂學習交流,備注「進群」

歡迎持續關注公眾號:「日拱一兵」

  • 前沿 Java 技術干貨分享
  • 高效工具匯總 | 回復「工具」
  • 面試問題分析與解答
  • 技術資料領取 | 回復「資料」

以讀偵探小說思維輕松趣味學習 Java 技術堆疊相關知識,本著將復雜問題簡單化,抽象問題具體化和圖形化原則逐步分解技術問題,技術持續更新,請持續關注......


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

標籤:其他

上一篇:安裝scrapy 缺少 Microsoft Visual C++ 14.0

下一篇:python 安裝 whl檔案

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

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more