简介

Nakadi 的目标是提供一个事件经纪人基础设施,以便:

  • 通过安全的 RESTful API 进行抽象事件交付

    这允许微服务团队维护服务边界,而不直接依赖于任何特定的消息代理技术。 可以为每个事件类型单独管理访问权限,并使用 OAuth 和自定义授权插件进行保护。

  • 支持事件驱动应用程序和异步微服务的方便开发

    可以使用事件类型架构定义事件类型,并通过注册表进行管理。 在发布事件类型之前,将根据模式验证所有事件。 它为数据使用者提供了数据质量和数据一致性的保证。

  • 有效的低延迟事件传递

    一旦发布者使用简单的 Http Post 发送事件,就可以通过流式 HTTP 连接推送到消费者,从而实现接近实时的事件处理。消费者连接具有保持活力控制并支持使用订阅管理流偏移量。

特性

Stream

  • 类似 Kafka 队列上的 REST 抽象
  • 事件类型的CRUD
  • 事件批量发布
  • Low-level API(消费)
    • 手动的客户端分区管理
    • 不支持提交
  • High-level API(订阅)
    • 在消费者客户端之间自动重新分配分区
    • 支持提交,移动服务器端游标

Schema

  • 模式注册表

  • 模式进化

  • 事件类型类别

    categories: 每个事件类别为一个事件类型启用不同的功能,特别是它们的模式和验证规则

    • Business 作为业务流程的一部分或驱动业务流程的事件,如客户订单中的状态转换。
    • Data Change 表示对记录或其他项或新项的更改的事件。 更改事件与创建、更新、删除或快照操作相关联。
    • Undefined 适用于生产者完全自定义的事件的自由格式类别。
  • 分区策略(Random/Hash/User Defined)

    • Random 分区是随机选择的,事件将均匀地分布在分区之间。 Nakadi 使用的默认选项是 Random。
    • Hash 通过对事件类型的 partition_key_fields中定义的字段值进行哈希处理来选择分区。 在实践中,这意味着那些大致相同的逻辑实体和具有相同的分区键值的事件将被发送到相同的分区。
    • user_defined 分区由生产者在发送事件时设置。 此选项仅适用于 businessdata change 类别。
  • 事件强化策略

  • 事件验证(通过模式)

Security

  • OAuth2 认证
  • 事件类型授权
  • 黑名单

Operations

  • Timelines
    • 允许透明地将生产和消费切换到不同的集群(tier、region、 AZ) ,而不会移动实际数据和任何服务降级
    • 为其他流媒体技术和引擎的实现提供了可能(比如 AWS Kinesis,Google pub / sub 等等)

概念

Nakadi API 允许通过 HTTP 发布和消费事件。

理解事件的一个好方法是,它们类似于流处理或队列系统中的消息,但具有可以理解和验证的定义结构。 包含描述事件的信息的对象称为事件类型。

要发布和消费事件,拥有事件的应用程序必须首先向 Nakadi 注册一个新的事件类型。 事件类型包含诸如其名称、应用程序、分区和丰富数据的策略以及 JSON 模式等信息。 Nakadi 支持列出所有可用事件类型的事件类型注册表 API。

一旦创建了事件类型,称为流的资源就可用于该事件类型。 流将接受来自生产者的类型的事件,并且一个或多个消费者可以从中读取。 Nakadi 可以验证发送到流的每个事件。

事件类型的流可以划分为一个或多个分区。 每个事件被精确地放置到一个分区中。 每个分区代表一个有序的日志——一旦一个事件被添加到一个分区中,它的位置永远不会改变,但是没有跨分区的全局排序。

消费者可以使用分配给每个分区的游标读取事件并跟踪它们在流中的位置。 消费者还可以使用光标从特定位置的流中读取数据。 多个使用者可以从同一个流中读取,允许不同的应用程序同时读取流。

事件应用分类

  • Event Type Owners 事件类型所有者通过事件类型注册表与 Nakadi 交互,以基于模式定义事件类型并创建事件流。

  • Event Producers 生产者将符合事件类型模式的事件发布到事件类型的流。

  • Event Consumers 消费者从事件流中读取事件,多个消费者可以从同一流中读取数据。

Cursors, Offsets, Partitiions(游标, 偏移量, 分区)

默认情况下,事件资源将从事件类型的所有分区和流的末端(或“尾端”)消耗。 要只选择特定的分区和流中要开始的位置,可以在请求中提供 X-Nakadi-Cursors 标头:

1
2
curl -v http://localhost:8080/event-types/order.ORDER_RECEIVED/events \
-H 'X-Nakadi-Cursors: [{"partition": "0", "offset":"12"}]'

标头值是游标的 JSON 数组。 数组中的每个游标描述流的分区和从中流出的偏移量。 请注意,同一个分区中的事件保持了它们的总体顺序。

光标的偏移量值允许您选择要从流中的哪个位置使用。 这可以是任何已知的偏移量值,也可以是将从头开始启动流的专用值 BEGIN。 例如,从分区0开始读:

1
2
curl -v http://localhost:8080/event-types/order.ORDER_RECEIVED/events \
-H 'X-Nakadi-Cursors:[{"partition": "0", "offset":"BEGIN"}]'

Event Stream Keepalives 事件流保活

如果没有事件需要发送,Nakadi 将通过定期发送一个没有事件但包含指向当前偏移量的指针的批处理来保持流连接打开。 例如:

1
2
3
4
5
6
7
8
9
10
curl -v http://localhost:8080/event-types/order.ORDER_RECEIVED/events 


HTTP/1.1 200 OK

{"cursor":{"partition":"0","offset":"6"},"events":[{"order_number": "ORDER_003", "metadata": {"eid": "4cc6d2f0-eb01-11e5-b606-1c6f65464fc6", "occurred_at": "2016-03-15T23:58:15+01:00"}}]}
{"cursor":{"partition":"0","offset":"6"}}
{"cursor":{"partition":"0","offset":"6"}}
{"cursor":{"partition":"0","offset":"6"}}
{"cursor":{"partition":"0","offset":"6"}}

注意:该示例为 Low-level API 已被否决,并将从未来的 Nakadi 版本中删除。 请考虑使用高级别的 API。

Timelines

时间线的创建是使用 Zookeeper 通过一系列的锁(Locks)和屏障(Barriers)来协调的。

  1. 初始状态

每次启动 Nakadi 应用程序时,它都会尝试创建以下 ZK 结构。为了不覆盖初始结构,由于并发性,每个实例在执行之前都需要获取锁 /nakadi/timelines/lock

1
2
3
4
5
6
7
timelines:
lock: - lock for timeline versions synchronization
version: {version} monotonically incremented long value (version of timelines configuration)
locked_et: -
nodes: nakadi nodes
node1: {version} Each nakadi node exposes the version used on this node
node2: {version}
  1. et_1 创建时间线

当创建一个新的时间线时,第一步是通过在 /timelines/locked_et/et_1 上创建一个临时节点来获得更新时间线的锁。

1
2
3
4
5
6
7
8
timelines:
lock: -
version: 0
locked_et:
et_1: -
nodes:
node1: 0
node2: 0
  1. 通知所有 Nakadi 节点相关更改:版本屏障

协调创建时间线的实例修改版本节点,所有 Nakadi 实例都在监听变化,因此当发生变化时,它们会得到通知。

1
2
3
4
5
6
7
8
timelines:
lock: -
version: 1 # this is incremented by 1
locked_et:
et_1: -
nodes:
node1: 0
node2: 0
  1. 等待所有节点对新版本作出反应

每个 Nakadi 实例监视 /nakadi/timelines/version/ 的值。 当它发生更改时,每个实例检查所有锁定的事件类型,并通过在本地释放或阻塞发布者来做出相应的反应。一旦每个实例更新了它本地的锁定事件类型列表,它就会添加自己的版本,让时间线创建者发起者知道它可以处理。

1
2
3
4
5
6
7
8
9
timelines:
lock: -
version: 1
locked_et:
et_1: -
nodes:
node1: 1 # each instance updates its own version
node2: 1

  1. 更改数据库

一旦所有实例都作出反应,创建过程继续进行,发起者在 timeline 表中插入必要的数据库条目,并对现有存储进行快照显示可用的最新偏移量。 它还在新存储中创建一个主题。 请注意,如果从未使用过时间线分区,则存储的偏移量为 -1。 如果只有一个事件,则偏移量为 0,依此类推。

  1. 移除锁并再次通知所有实例

按照初始状态创建时间线的相同逻辑,锁将被删除,版本将被修改。 所有 Nakadi 实例的处理是移除本地锁并在必要时切换时间线。

1
2
3
4
5
6
7
timelines:
lock: -
version: 2
locked_et:
nodes:
node1: 1
node2: 1

在每个实例处理之后,它看起来应该像:

1
2
3
4
5
6
7
timelines:
lock: -
version: 2
locked_et:
nodes:
node1: 2 # each instance updates its own version
node2: 2
  • 至此,一个新的时间线创建成功。

部署

下载源码

1
git clone https://github.com/zalando/nakadi.git

Docker Compose

1
2
cd nakadi
docker-compose up

启动成功后,各服务端口:

  • 8080 - API Server
  • 5432 - PostgreSQL
  • 9092, 29092 - Kafka
  • 2181 - Zookeeper

API 示例

  • 创建事件类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    curl -X POST \
    http://172.16.18.143:8080/event-types \
    -H 'Content-Type: application/json' \
    -d '{
    "name": "order.ORDER_RECEIVED",
    "owning_application": "order-service",
    "category": "undefined",
    "schema": {
    "type": "json_schema",
    "schema": "{ \"additionalProperties\": true }"
    }
    }'

    API 用法

  • 添加订阅

    1
    2
    3
    4
    5
    6
    7
    curl -X POST \
    http://172.16.18.143:8080/subscriptions \
    -H 'Content-Type: application/json' \
    -d '{
    "owning_application": "abc",
    "event_types": ["order.ORDER_RECEIVED"]
    }'

    API 用法

  • 发布消息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    curl -X POST \
    http://172.16.18.143:8080/event-types/order.ORDER_RECEIVED/events \
    -H 'Content-Type: application/json' \
    -d '[
    {
    "order_number": "24873243241"
    },
    {
    "order_number": "24873243242"
    }
    ]'

    API 用法

  • 订阅消费

    1
    curl -X GET http://172.16.18.143:8080/subscriptions/{subscription_id}/events

    API 用法

部署 UI(可选)

https://github.com/zalando-nakadi/nakadi-ui

Docker

1
docker run -it -d -p 3000:3000 -e NAKADI_API_URL=http://172.16.18.1:8080 -e BASE_URL=http://172.16.18.143:3000 nakadi/nakadi-ui:latest

(待续)

环境: Unbuntu 16.04 TLS Server

先决条件

Docker: Ubuntu 1604 TLS Server 安装 Docker CE

安装 Compose

下载

1
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

部署

1
sudo chmod +x /usr/local/bin/docker-compose

验证

1
docker-compose --version

参考

官方安装 Docker Compose

Official Site: http://dubbo.apache.org

Introduce

Apache Dubbo 是一个高性能的、基于 JAVA 的开源 RPC 框架。

Feature List

  • Transparent interface based RPC

    Dubbo 提供了基于 RPC 的高性能接口,这对用户是透明的。

  • Automatic service registration and discovery

    Dubbo 支持多种服务注册中心,能够实时监测服务的在线离线。

  • Runtime traffic routing

    Dubbo 可以在运行时进行配置,这样流量可以根据不同的规则进行路由,使得支持如蓝绿部署、数据中心感知路由等功能变得容易。

  • Intelligent load balancing

    Dubbo 支持多种开箱即用的负载均衡策略,这种策略能够感知下游服务状态,以减少延迟并提高系统吞吐量。

  • High extensibility

    Dubbo 的微内核及插件设计确保了它能够很容易地通过第三方实现跨核心特性扩展,如协议传、输和序列化。

  • Visualized service governance

    Dubbo 为服务治理和维护提供了丰富的工具,如查询服务元数据,健康状态和统计。

Introduce

Apache OFBiz 是一套非常灵活的业务应用程序,可以在任何行业中使用。 通用体系结构允许开发人员轻松地扩展或增强它以创建自定义特性。

官网:https://ofbiz.apache.org/

名词:OFBiz: Open for business

Prerequisites

  • JDK 1.8

    java -version

    1
    2
    3
    java version "1.8.0_201"
    Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
    Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
  • Gradle/Gradlew

    gradle -v

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ------------------------------------------------------------
    Gradle 5.1
    ------------------------------------------------------------

    Build time: 2019-01-02 18:57:47 UTC
    Revision: d09c2e354576ac41078c322815cc6db2b66d976e

    Kotlin DSL: 1.1.0
    Kotlin: 1.3.11
    Groovy: 2.5.4
    Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018
    JVM: 1.8.0_201 (Oracle Corporation 25.201-b09)
    OS: Mac OS X 10.15.2 x86_64

Download

  • Resource

https://www.apache.org/dyn/closer.lua/ofbiz/apache-ofbiz-16.11.06.zip

  • Unzip
1
unzip apache-ofbiz-16.11.06.zip

Build & Run

  • CD
1
cd apache-ofbiz-16.11.06
  • Build
1
gradle cleanAll loadDefault
  • Run
1
gradle ofbiz
  • Stop
1
gradle ofbiz --shutdown

Browser

  • 会计模块路由
1
https://localhost:8443/accounting

Username & Password: admin/ofbiz

Modules and Features

Accounting(会计)

  • Standard Double entry General Ledger
  • Supports multiple organisations, account hierarchies and segmentation
  • Accounts Receivable (AR), Accounts Payable (AP), Invoices, Payments, Statements and Aging
  • Agreement contracts and Credit management
  • Asset Management including Depreciation
  • Budgeting Management
  • Support for payment gateways and payment processing
  • Financial Reporting
  • Fully integrated with Order Management, Inventory, Purchasing and Manufacturing out of the box

Manufacturing(制造业)

  • Bill of Materials
  • Jobshop, Manufacturing Routings and Tasks
  • Production Planning and MRP
  • Production and Job Costing
  • Equipment Billing
  • Raw Material Procurement
  • Manufacturing Reporting

Human Resources(人力资源)

  • Company and Department Structure
  • Manage Job Positions, Skills and Performance Reviews
  • Manage Recruitment Process, Applications, Interviews
  • Salaries and Payments
  • Employment Contracts
  • Employee Expenses
  • Training

Inventory Management(库存管理)

  • Manage and setup single, multiple warehouses
  • Inventory Locations
  • Serialized on non serialized Inventory
  • Lot Management
  • Shipment Integration
  • Picklist and Package Management
  • Receiving
  • Returns

Catalog Management(目录管理)

  • Support unlimited stores, catalogs, categories, and products
  • Handles a range of products (physical, digital, downloadable products, variant, configurable)
  • Gift Certificates and gift cards
  • Price rules for customer or group-specific pricing
  • Online store promotion engine
  • Integration with major payment gateway providers
  • Fully integrated online and Point of Sales (POS) stores out-of-the-box
  • Keyword search capability in all the applications using hibernate search

CRM & Order Management(客户关系管理 & 订单管理)

  • Lead and Sales Opportunity Management
  • Sales ForecastsManage sales opportunities
  • Shared Sales Team Documents, Calendar and Tasks
  • Email Integration
  • Customer Service and Case Managment
  • Quotes, Order Entry and Order Management
  • Manage marketing campaign including tracking code reporting

e-Commerce/e-Shop(电子商务/电子商店)

  • Unlimited stores, catalogs, categories and products
  • Cross-sell and upsell products
  • Supports physical, digital, downloadable, variant and configurable products
  • Gift Certificates and Gift Cards
  • Pricing rules and Discounts
  • Online store promotion engine
  • Integrations with payment gateways
  • Product searching
  • Customer portal

安装

Docker

1
2
3
4
5
6
7
8
9
sudo docker run --detach \
--hostname gitlab.example.com \
--publish 9443:443 --publish 9080:80 --publish 9022:22 \
--name gitlab \
--restart always \
--volume /opt/gitlab/config:/etc/gitlab \
--volume /opt/gitlab/logs:/var/log/gitlab \
--volume /opt/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest

DNS Or hosts

配置域名解析或在客户端配置主机别名。

主机别名示例:

1
172.16.18.143 gitlab.example.com

访问

首次登录

  1. 浏览器打开: http://gitlab.example.com:9080
  2. 重置管理员root密码(e.g. admin123)
  3. 登录

启用双重认证(可选)Two-Factor Authentication

在个人设置中启用双重认证,手机端使用 FreeOTP 生成认证码。

功能

  • User
  • Group
  • Repository
  • TLS & SSH
  • Settings

  • 「枪炮、经济与霸权」
  • 「三联生活周刊」全年杂志
  • 「罗伯特议事规则」第 11 版 (未完)

Install

Docker(2 container)

1
2
3
docker run -d -it -p 5701:5701 -e MANCENTER_URL='http://172.16.18.143:8200/hazelcast-mancenter' -e JAVA_OPTS='-Dhazelcast.local.publicAddress=172.16.18.143:5701 -Dhazelcast.rest.enabled=true' hazelcast/hazelcast:3.12.4

docker run -d -it -p 5702:5701 -e MANCENTER_URL='http://172.16.18.143:8200/hazelcast-mancenter' -e JAVA_OPTS='-Dhazelcast.local.publicAddress=172.16.18.143:5702 -Dhazelcast.rest.enabled=true' hazelcast/hazelcast:3.12.4
  • -Dhazelcast.rest.enabled=true启用 REST API

Management

Docker Run

1
docker run -dit -p 8200:8080 hazelcast/management-center:latest

Visit

1
http://192.168.11.10:8200/hazelcast-mancenter

Client

REST

  • Put Key-Value to Map
1
curl -v -X POST -H "Content-Type: text/plain" -d "bar" http://127.0.0.1:5701/hazelcast/rest/maps/mapName/foo
  • Get Value From Map By Key
1
curl -X GET http://127.0.0.1:5701/hazelcast/rest/maps/mapName/foo

理解 Keystore & Truststore

Keystore 用于存储私钥和身份证书,特定程序应该向双方(服务器或客户机)提供这些证书以进行验证。顾名思义,Key 是证书,Store 是存储库,Keystore 便是存放证书的存储库;在 SSL 连接期间提供认证。

Truststore 用于存储来自认证机构(CA)的证书,这些证书验证在 SSL 连接中由服务器提供的证书。顾名思义,Trust 是信任,Store 是存储库,Truststore 便是存放受信任的证书库。

自签证书示例

  1. Generate ca.key & ca.crt
1
2
openssl genrsa -aes256 -passout pass:shankai@ca -out ca.key 4096
openssl req -new -x509 -days 3650 -subj "/C=CN/ST=SHAANXI/L=XI'AN/O=shankai/OU=dev/CN=shankai.city" -passin pass:shankai@ca -key ca.key -out ca.crt
  1. Generate server.key & server.crt

以 keycloak 服务为例

  • extfile: keycloak.ext
1
2
3
4
5
6
7
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = sso.shankai.city
  • generate
1
2
3
4
openssl genrsa -out keycloak.key 2048
openssl req -new -key keycloak.key -subj "/C=CN/ST=SHAANXI/L=XI'AN/O=shankai/OU=dev/CN=sso.shankai.city" -out keycloak.csr

openssl x509 -req -in keycloak.csr -passin pass:shankai@ca -CA ca.crt -CAkey ca.key -CAcreateserial -out keycloak.crt -days 1825 -sha256 -extfile keycloak.ext
  1. Format Convert [optional]
  • crt -> p12, p12 -> jks
1
2
3
4
5
openssl pkcs12 -export -out keycloak.p12 -in keycloak.crt -inkey keycloak.key -password pass:shankai@2021
keytool -importkeystore -srcstorepass shankai@2021 -deststorepass shankai@2021 -destkeypass shankai@2021 -srckeystore keycloak.p12 -srcstoretype PKCS12 -destkeystore keycloak.jks -deststoretype JKS

openssl pkcs12 -export -out ca.p12 -in ca.crt -inkey ca.key -passin pass:shankai@ca -password pass:shankai@2021
keytool -importkeystore -srcstorepass shankai@2021 -deststorepass shankai@2021 -destkeypass shankai@2021 -srckeystore ca.p12 -srcstoretype PKCS12 -destkeystore truststore.jks -deststoretype JKS

证书工具

  • openssl
  • keytool

证书格式

常见格式

证书生成与格式转换

Openssl

pfx -> pem

1
2
3
4
5
openssl pkcs12 -clcerts -nokeys -out one123456.pem -in one123456.pfx
openssl pkcs12 -nocerts -out one123456.key.pem -in one123456.pfx

openssl pkcs12 -clcerts -nokeys -out two123456.pem -in two123456.pfx
openssl pkcs12 -nocerts -out two123456.key.pem -in two123456.pfx

crt + key -> p12

1
2
openssl pkcs12 -export -in dop.crt -inkey dop.key -out dop.p12 -name dop -password pass:abcdef
openssl pkcs12 -export -in wiki.crt -inkey wiki.key -out wiki.p12 -name wiki -password pass:abcdef

Keytool

cer -> jks

1
2
3
4
5
keytool -importcert -file CFCA_RSA_TEST_OCA21.cer -keystore cfca.jks -alias cfca

keytool -importcert -file ca.cer -keystore cfca.jks -alias cfca

keytool -import -alias cfcaalias -file cfca.cer -keystore trusted.keystore

crt -> jks

keytool -import -alias alias -file ca.crt -keypass keypass -keystore ca.jks -storepass 123456 -noprompt

p12 -> jks

1
keytool -importkeystore -srckeystore ca.p12 -srcstoretype PKCS12 -destkeystore ca.jks -deststoretype JKS

客户端认证

curl

1
2
3
curl -k -v --cert ./tls.crt --key ./tls.key https://qmsauthn.paas.service.sd/login

curl -k -v --cert ./authn.crt --key ./authn.key https://qmsauthn.pditdop:6443/login

Install

环境:Ubuntu 16.04
用户:root
官方手册: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/

准备

1
2
3
4
5
6
7
8
wget -qO - https://www.mongodb.org/static/pgp/server-4.0.asc | apt-key add -

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list

apt-get install apt-transport-https

apt-get update

安装

安装最新

1
apt-get install -y mongodb-org

安装指定版本

1
apt-get install -y mongodb-org=4.0.11 mongodb-org-server=4.0.11 mongodb-org-shell=4.0.11 mongodb-org-mongos=4.0.11 mongodb-org-tools=4.0.11

Docker

1
docker run --name mongo-dev -d -p 27017:27017 mongo:latest

Docker Compose docker-compose.yml docker-compose up -d

1
2
3
4
5
6
7
8
9
10
11
version: '3'
services:
mongo:
image: mongo:4.4.6
ports:
- 27017:27017
container_name: mongodb
restart: always
network_mode: test
volumes:
- /data/mongo_data:/data/db

Usage

连接

远程连接示例

1
mongo --host qloudmongodb.pditdapps:27017 -u "qloudwiki" -p "qloudwiki" --authenticationDatabase "wiki"

数据库

xxx 为数据库名称

  • 数据库列表

show dbs

  • 切换数据库

use xxx

用户

用户列表

1
show users

创建用户

1
2
3
4
5
6
7
db.createUser(
{
user: "{username}",
pwd: "{password}",
roles: [ { role: "dbAdmin", db: "{dbname}" } ]
}
)

删除用户

1
db.dropUser('{username}')

集合

xxx 为集合名称

集合列表

show collections

查询

db.xxx.find()

删除

db.xxx.drop()

环境准备

  • nodejs:v10.16.0
  • npm:6.9.0

生成证书

1
2
3
4
5
6
keytool -genkeypair -alias vsd -validity 7200 -keyalg RSA -keysize 4096 -storetype JKS -keystore vsd.keystore -storepass vsd@2019 -keypass vsd@2019 -dname "CN=v.s.d, OU=dtts, O=dtts"

keytool -v -importkeystore -srckeystore vsd.keystore -srcalias vsd -srcstorepass vsd@2019 -srckeypass vsd@2019 -destkeystore vsd.p12 -deststoretype PKCS12 -deststorepass vsd@2019 -destkeypass vsd@2019

openssl pkcs12 -in vsd.p12 -nocerts -nodes -out vsd.key.pem -passin pass:vsd@2019
openssl pkcs12 -in vsd.p12 -clcerts -nokeys -out vsd.cert.pem -passin pass:vsd@2019

安装依赖

1
npm install express https http fs body-parser

创建文件

vsd.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var express = require('express');
var https = require('https');
var http = require('http');
var fs = require('fs');
var bodyParser = require('body-parser');

// This line is from the Node.js HTTPS documentation.
var options = {
key: fs.readFileSync('qmsauthn.key.pem'),
cert: fs.readFileSync('qmsauthn.cert.pem')
};

// Create a service (the app object is just a callback).
var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
// in latest body-parser use like below.
app.use(bodyParser.urlencoded({ extended: true }));

// get api
app.get('/api/v1', (req, res) => {
res.status(200).send({
success: 'true',
message: 'todos retrieved successfully',
})
});

// post api (Content-Type: application/x-www-form-urlencoded)
app.post('/api/v2', (req, res) => {
console.log(req.body);
res.status(200).send({
success: 'true',
message: 'todos retrieved successfully',
})
});

// Create an HTTP service.
http.createServer(app).listen(80);
// Create an HTTPS service identical to the HTTP service.
https.createServer(options, app).listen(443);

访问

http

1
curl -i http://v.s.d/api/v1
1
2
3
4
curl -X POST \
http://v.s.d/api/v2 \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d aa=111