0%

OData协定

Open Data Protocol(开放数据协议,OData)是用来查询和更新数据的一种Web协议,其提供了把存在于应用程序中的数据暴露出来的方式。OData运用且构建于很多Web技术之上,比如HTTP、Atom Publishing Protocol(AtomPub)和JSON,提供了从各种应用程序、服务和存储库中访问信息的能力。OData被用来从各种数据源中暴露和访问信息,这些数据源包括但不限于:关系数据库、文件系统、内容管理系统和传统Web站点。

OData解决的是Restful Api定义太随便的问题
比如查询人员
A团队的API 可能是这样:http://A/api/Users/001
B团队的API 可能是这样:http://A/api/Users?id=001
返回结果也可能各有加工,{status: “ok”,data: {…}}的设计实际上只是自我感觉良好

OData则约束调用接口 Users
然后返回值形如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"@odata.context": "https://localhost:44346/odata/v1/$metadata#Users",
"value": [
{
"name": "QQs",
"emailAddress": "qqs@qqs.qqs",
"logo": "img base 64",
"enable": true,
"addressId": "ca35902d-d236-4496-b649-2f7fcf531110",
"recordId": "c7612b51-ddb2-eb11-9bf6-180373e9ce7d",
"recordCreated": "2021-05-12T05:52:19.979+08:00",
"recordLastUpdated": "2021-05-12T04:48:39.377+08:00"
}
]
}

返回值中包含接口的数据上下文文档,包含属性类型定义,Users 相关Api的参数设计等
OData似乎暴露了过多的底层设计的,而这么做的目的和结果是对数据的访问不再受限于定义各种查询、过滤以及分页API(由OData库依照标准实现类似sql的查询方式)
在.net开发中,得益于entityframework强大的关联模型设计和limbda查询方式,OData方显强大

参考OData.org Getting started

安装和应用OData Library

Nuget Package Manager 安装Microsoft.AspNetCore.OData Caution! 这里是7.0版本
添加Model DBContext Controller(这块参考EntityFramework)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddOData();
}

public void Configure(IApplicationBuilder app)
{
var builder = new ODataConventionModelBuilder(app.ApplicationServices);

builder.EntitySet<Product>("Products");

app.UseMvc(routeBuilder =>
{
// and this line to enable OData query option, for example $filter
routeBuilder.Select().Expand().Filter().OrderBy().MaxTop(100).Count();

routeBuilder.MapODataServiceRoute("ODataRoute", "odata", builder.GetEdmModel());

// uncomment the following line to Work-around for #1175 in beta1
// routeBuilder.EnableDependencyInjection();
});
}

参考QQs TeamsPersistanceCenter项目

filter

  • $filter=name eq ‘QQstone’
  • $filter=type ne ‘standard’
  • $filter=contains(email, ‘163.com’)
  • $filter=quantity gt 1 and le 100
    gt(greater than) lt(less than) ge(greater than or equal to) le(less than or equal to)
    注意单引号

    select

  • $select=name,email,type

    expand

    关联查询 $expand=department

    关于分页

    https://localhost:44346/odata/v1/Users?$count=true

https://localhost:44346/odata/v1/Users?$skip=20&$top=10

trouble shooting

issue: The EntityXXX key in the URL xxxx does not match the key (00000000-0000-0000-0000-000000000000) in the request content body.

reason:put method, post body中也要包含主键 xxxx

flaw

过分暴露底层模型设计, 也许像GraphQL一样,需要在接口层以下封装一下,微软也不是什么都没做,EDM了解一下

EDM

The Entity Data Model, or EDM, is the abstract data model that is used to describe the data exposed by an OData service.

The EDM makes the stored form of data irrelevant to application design and development.

EF提供了对象描述数据结构的概念 EDM使应用(上层)设计和开发与存储形式无关
更正 EDM就是Model层映射了实体数据的class,也就是之前说的‘entity’ 于封装数据木有直接关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 private static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EnableLowerCamelCase();
builder.EntitySet<Partner>(GetEntitySetName<PartnersController>());
var entityType = builder.EntitySet<Partner>(GetEntitySetName<PartnersController>()).EntityType;

entityType.Collection.Function(nameof(PartnersController.GetPartnersBySN))
.ReturnsCollectionFromEntitySet<Partner>("Partners")
.Parameter<string>("serialNo");

builder.EntitySet<Member>(GetEntitySetName<MembersController>());
return builder.GetEdmModel();
}

Action & Function

参考Microsoft Docs

动作和函数之间的区别在于: Action可以有副作用(side effect)而Function没有,Action应用场景或应用如复杂交易、一次操作多个实体、仅更新实体部分属性、发送非实体数据等

Action:

1
2
3
4
5
6
7
8
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");

// New code:
builder.Namespace = "ProductService";
builder.EntityType<Product>()
.Action("Rate")
.Parameter<int>("Rating");

使能名为‘Rate’的Action的接口 http://localhost/Products(1)/ProductService.Rate
controller中定义Action,方法名与操作名称相同
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
[HttpPost]
public async Task<IHttpActionResult> Rate([FromODataUri] int key, ODataActionParameters parameters)
{
if (!ModelState.IsValid)
{
return BadRequest();
}

int rating = (int)parameters["Rating"];
db.Ratings.Add(new ProductRating
{
ProductID = key,
Rating = rating
});

try
{
await db.SaveChangesAsync();
}
catch (DbUpdateException e)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
}

return StatusCode(HttpStatusCode.NoContent);
}

Function:
1
2
3
builder.EntityType<Product>().Collection
.Function("ProdFunc1")
.Returns<double>();

GET http://localhost:38479/Products/ProductService.ProdFunc1
controller中用同样的名称定义API方法
1
2
3
4
5
6
[HttpGet]
public IHttpActionResult MostExpensive()
{
var product = db.Products.Max(x => x.Price);
return Ok(product);
}

Unbound Function:
Action或Function应用于单个实体或集合,称之为绑定(binding),未绑定(unbound)的Action/Function称为服务的静态操作
1
2
3
builder.Function("GetSalesTaxRate")
.Returns<double>()
.Parameter<int>("PostalCode");

1
2
3
4
5
6
7
[HttpGet]
[ODataRoute("GetSalesTaxRate(PostalCode={postalCode})")]
public IHttpActionResult GetSalesTaxRate([FromODataUri] int postalCode)
{
double rate = 5.6; // Use a fake number for the sample.
return Ok(rate);
}

containment

1
2
3
4
5
6
7
8
[EnableQuery]         
[ODataRoute("Accounts({accountId})/PayinPIs({paymentInstrumentId})")]
public IHttpActionResult GetSinglePayinPI(int accountId, int paymentInstrumentId)
{
var payinPIs = _accounts.Single(a => a.AccountID == accountId).PayinPIs;
var payinPI = payinPIs.Single(pi => pi.PaymentInstrumentID == paymentInstrumentId);
return Ok(payinPI);
}

零和博弈,非零和博弈

非零和博弈表示在不同策略组合下各博弈方的得益之和是不确定的变量,故又称之为变和博弈。 如囚徒困境,中美关系,恋爱

零和博弈表示所有博弈方的利益之和为零或一个常数,即一方有所得,其他方必有所失。如绝大多数竞技,竞选,炒股

行业或社会环境成为存量市场,内卷是人们进行零和博弈的结果。

摘自百度百科《非零和博弈》:
烈日炎炎的一个下午,约翰·纳什教授给二十几个学生上课,教室窗外的楼下有几个工人正施工,机器的响声成了刺耳的噪音,于是纳什走到窗前狠狠地把窗户关上。马上有同学提出意见:“教授,请别关窗子,实在太热了!”而纳什教授一脸严肃地回答说:“课堂的安静比你舒不舒服重要得多!”然后转过身一边嘴里叨叨着“给你们来上课,在我看来不但耽误了你们的时间,也耽误了我的宝贵时间……”,一边在黑板上写着数学公式。
正当教授一边自语一边在黑板上写公式之际,一位叫阿丽莎的漂亮女同学(这位女同学后来成了纳什的妻子)走到窗边打开了窗子,电影中纳什用责备的眼神看着阿丽莎:“小姐……”而阿丽莎对窗外的工人说道:“打扰一下,嗨!我们有点小小的问题,关上窗户,这里会很热;开着,却又太吵。我想能不能请你们先修别的地方,大约45分钟就好了。”正在干活的工人愉快地说:“没问题!”又回头对自己的伙伴们说:“伙计们,让我们先休息一下吧!”阿丽莎回过头来快活地看着纳什教授,纳什教授也微笑地看着阿丽莎,既像是讲课,又像是在评论她的做法似地对同学们说:“你们会发现在多变性的微积分中,往往一个难题会有多种解答。”
而阿丽莎对“开窗难题”的解答,使得原本的一个零和博弈变成了另外一种结果:同学们既不必忍受室内的高温,教授也可以在安静的环境中讲课,结果不再是0,而成了+2。由此我们可以看到,很多看似无法调和的矛盾,其实并不一定是你死我活的僵局,那些看似零和博弈或者是负和博弈的问题,也会因为参与者的巧妙设计而转为正和博弈。

内卷和博弈

内卷是零和博弈的状态吗?
参与者是直接地进行利益竞争吗,似乎并不是哦,内卷的起因是掌握话语权的一方——在社会生产的范畴上是资本家,在就学教育上是招生办——限制了规则,在既定的有限条件下,低阶层的参与者为了自己的收益做出与之不匹配的付出。博弈是影响决策的活动,当然就要有决策的权力和空间。

Azure官方文档token overview

JWT所述,JWT包含三个部分,一个标头,一个正文和一个签名。签名段可用于验证令牌的真实性,以便您的应用程序可以信任它。Azure AD B2C通过使用行业标准的非对称加密算法(例如RSA 256)对令牌进行签名。
header包含有关用于对令牌进行签名的密钥和加密方法的信息:

1
2
3
4
5
{
"typ": "JWT",
"alg": "RS256",
"kid": "GvnPApfWMdLRi8PDmisFn7bprKg"
}

Azure AD B2C具有一个OpenID Connect元数据EndPoint。大概长这样子:
1
https://qqstudio.b2clogin.com/qqstudio.onmicrosoft.com/B2C_1_basic_sign_up_and_sign_in/v2.0/.well-known/openid-configuration

通过此EndPoint,可以get到有关Azure AD B2C的信息。此信息包括端点,令牌内容和令牌签名密钥。
其中jwks_uri提供用于签署令牌的一组公共密钥的位置。
1
https://qqstudio.b2clogin.com/qqstudio.onmicrosoft.com/b2c_1_basic_sign_up_and_sign_in/discovery/v2.0/keys

jwks_uri如上格式,建议通过get元数据文档并解析以动态获取jwks_uri,而不要写死。

StackOverflow 上有个现成的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
"https://testb2ctenant05.b2clogin.com/testB2CTenant05.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_test",
new OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever());
CancellationToken ct = default(CancellationToken);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
var discoveryDocument = await configurationManager.GetConfigurationAsync(ct);
var signingKeys = discoveryDocument.SigningKeys;
var validationParameters = new TokenValidationParameters
{
RequireExpirationTime = true,
RequireSignedTokens = true,
ValidateIssuer = true,
ValidIssuer = discoveryDocument.Issuer,
ValidateIssuerSigningKey = true,
IssuerSigningKeys = signingKeys,
ValidateLifetime = true,

};

var principal = new JwtSecurityTokenHandler()
.ValidateToken(token, validationParameters, out var rawValidatedToken);

Jim Xu’s Answer

用例描述:

  • 使用非法字符串冒充access token,异常:decode fail
  • 使用其他来源的(比如其他talent)的token,异常:unmatch siguanture
  • 使用正确token 获得principal对象

回顾一下,对于非对称加密,签名用私钥产生,私钥绝对隐藏且不可被反推,公开公钥,任何人可以使用公钥验证签名。

云管理员,与普通IT管理员相比,不需要过多关注具体硬件软件的内容,云管理员管理着包括存储、网络连接和计算云功能在内的云服务,并对整个IT生命周期中的每项服务具有深入了解

他们接收最终用户对接入新云应用程序的请求,为其提供服务建议

Overview

There are 7 modules to learn:

  • Prerequisites for Azure administrators
  • Manage identities and governance in Azure
  • Implement and manage storage in Azure
  • Deploy and manage Azure compute resources
  • Configure and manage virtual networks for Azure administrators
  • Monitor and back up Azure Resources
    即Azure的订阅和资源,管理身份,实施和管理存储,虚拟机,虚拟网络, 监视和备份
    https://docs.microsoft.com/en-us/learn/certifications/exams/az-104

    Azure Policy

    参考利用 Azure Policy 进行云上资源实时控制及合规监控

    Azure Policy的工作原理是选择或新建一个策略或计划(计划是一组策略的集合),分配给指定范围的资源,然后定期(24小时左右)Policy会检查这些资源是否符合策略或计划,并列出不合规项。

Az104 Q5 使用resource policy修改虚拟网络的限制

类似的: 蓝图blue print,为某个订阅制订蓝图(和策略一样,azure上由很多已定义的)
Monitor里的Alert,为某个特定资源添加警报

虚拟机

可用性、可用区和可用集

可用性是可供使用的时间段的百分比,任意时间可访问的服务即100%可用性

因故障、因物理故障触发的自动迁移、定期更新都有可能造成资源可用性达不到100%

管理可用性
创建和部署高度可用的虚拟机

可用性区域:区域中的唯一物理位置,每个区域由一个或多个数据中心组成,这些数据中心配置了独立电源,冷却和网络。区域中可用性区域的物理隔离可以在发生数据中心故障的情况下保护应用程序和数据。 区域冗余服务可跨可用性区域复制应用程序和数据,以防范单点故障。

  • 更新域和容错域的组合
  • 当两个或更多个 VM 部署在一个 Azure 区域中的两个或更多个可用性区域时,可获得99.99% VM 运行时间 SLA(service-level agreement, 服务级别协议)

使用可用性区域创建vm settings—>High availability—>选择一个编号的区域 详细

而可用性集是一种逻辑分组功能,将在物理层面相分离的vm连接到一起,如果运行服务器的其中之一的物理硬件有问题,可以确信服务器的其他实例保持运行,因为它们位于不同的硬件上。使用命令创建可用性集 详细

Microsoft 为部署在可用性中的多实例 VM 提供 99.95% 的外部连接性服务级别协议 (SLA)。 这意味着,对于要应用的 SLA,必须在可用性集中至少部署两个 VM 实例。

You plan to deploy three Azure virtual machines named VM1, VM2, and VM3. The virtual
machines will host a web app named App1.
You need to ensure that at least two virtual machines are available if a single Azure datacenter
becomes unavailable.
What should you deploy?
A. all three virtual machines in a single Availability Zone
B. all virtual machines in a single Availability Set
C. each virtual machine in a separate Availability Zone
D. each virtual machine in a separate Availability Set

Answer is B.

  • 可以自己提供非官方镜像用于创建虚拟机

    It is possible to change the size of a VM after it’s been created, but the VM must be stopped first. So, it’s best to size it appropriately from the start if possible.调整vm配置需要停机

  • 几个size:普通的(B,D..)大数据存储(L-series),图形渲染(N-series),高性能(H-series)

    You can store data on the primary drive along with the OS(默认挂载/dev/sda,最大2018G), but a better approach is to create dedicated data disks(可以挂几万GiB).

  • 关于硬盘的unmanaged(以容量和IO计费)和managed(提供存储的伸缩性,提供快照和备份等)
  • ssh
    创建虚拟机时可以选择生成key pair,创建完成后下载pem文件用于连接,抑或在本地生成key pair使用其中的public key创建
    连接上VM使用下述方式添加更多的public key
    1
    2
    3
    4
    # 创建公钥私钥对
    ssh-keygen -t rsa -b 4098
    # 将公钥贴到虚拟机上
    ssh-copy-id -i ~/.ssh/id_rsa.pub azureuser@myserver
  • 虚拟机创建完成的初始网络状态是:Outbound request are allowed. Inbound traffic is only allowed from within the virtual network.即出站任意,入站限制为允许虚拟网络内的访问
  • Windows虚拟机相关:远程桌面连接(RDP 3389); 网络安全组(NSG)设置入站出站规则,软件防火墙

    The rules are evaluated in priority-order, starting with the lowest priority rule. Deny rules always stop the evaluation. The last rule is always a Deny All rule.That means to have traffic pass through the security group you must have an allow rule or it will be blocked by the default final rule. 规则使用优先级层叠,若无允许则被底层规则(the final rule)禁止

虚拟机的备份(存目)

Networking

学习目标:

  • 概念:网络协议和网络标准。
  • 网络拓扑类型(网格,总线,星形)
  • 网络设备。
  • 网络通信原则(如 TCP/IP、DNS 和端口)。
  • !以上组件在 Azure 网络上的映射和配置。

Azure虚拟网络

Bridge(网桥),将网络划分为网段,在其之间过滤和推送数据包,数据流向通过MAC地址决定,可以减少不必要的网络交通以提升网络传输性能。
HUb(指网络集线器),充当网络上的多端口中继器,用以连接多个设备并构建网络布局,集线器将以固定的速度运行即所连接的最慢的网络设备的速度
Switch(交换机),是网桥和集线器的结合

tip:进入命令行help可看到所有支持的命令,用tcping代替ping

协议:

  • 邮局协议 3(Post Office Protocol 3, POP3) 用于接收邮件
  • 简单邮件传输协议 (SMTP) 使用邮件服务器发送邮件
  • 交互式邮件访问协议 (IMAP) 管理邮箱
  • 安全套接字层 (Secure Socket Layer, SSL) 标准的加密和安全性协议,提供计算机和Internet访问目标服务器或设备之间的安全的加密连接
  • 传输层安全 (Transport Layer Security, TLS) SSL的后继者
  • 安全超文本传输协议 (HTTPS) 使用SSL或TLS加密的HTTP
  • 安全外壳 (Secure Shell, SSH)
  • Kerberos 验证协议 通过密钥加密为cs应用提供鲁棒的认证
  • 简单网络管理协议 (SNMP) 允许从网络上的设备收集数据以进行管理
  • Internet 控制消息协议 (ICMP) 允许网络的设备发送警告或错误

IPS模型:

DNS(Domain Name System)分散式查找服务,将用户可读的域名或 URL 转换为承载站点或服务的服务器的 IP 地址。

  • A SOA寻址
  • AAAA IP寻址
  • CNAME 域名别名
  • NS 名称服务器
  • MX SMTP 电子邮件

    网络安全

    学习目标
  • C/S网络模型:请求-响应;P2P(Peer-to-Peer);发布-订阅
  • 认证和授权
  • 网络防火墙类型
  • 监控项目
  • 在Azure上的映射

关于认证:

  • 密码认证
  • 双因素(two-factor)认证:如账户密码+邮箱/手机认证
  • token authentication
  • 生物识别认证(Biometric authentication):如用指纹、语音或人脸识别
  • 事务认证(Transactional authentication) 通常用于提供额外的认证保护,如在工作时间范围内允许访问
  • 图灵测试(CAPTCHA)解释看到的信息,通常是模糊的文字或场景中的特征,CAPTCHA可能会给存在视力障碍的用户带来困难

认证协议:

  • Kerberos
  • TLS/SSL

授权:
私以为其概念是对已持有的认证身份标记所赋予的权限

防范目标和措施:

  • any user, 访问控制(access control)即对用户设置访问相应资源的权限级别
  • 恶意软件,杀软
  • 应用程序漏洞
  • 行为分析,创建安全策略识别具有潜在危险的行文
  • 邮件,识别可疑邮件和发信人
  • 入侵检测(存目)

防火墙:

  • 应用程序层防火墙 如检测HTTP请求的插件或筛选器
  • 数据包筛选防火墙 如检测数据包
  • 线路级(circuit-level)防火墙 如检查TCP/UDP连接的源、目标、用户等是否符合既定规则
  • 代理服务器防火墙 以代理控制信息进出网络,因此可以监视、筛选和缓存网络上任意类型设备的internet访问
  • stateful firewalls & next-generation firewalls

通过配置与 Azure 的“站点到站点 VPN”连接,将本地网络连接到 Azure 虚拟网络。

亦可通过vpn配置实现点(client)到站点的连接

Notice:

  • 关键 Azure 服务只连接 Azure 虚拟网络,不连接公共 Internet,比如Azure SQL数据库,Azure Storage等
  • 尽可能禁用SSH/RDP 访问,应先创建点到站点 VPN 连接,然后再为远程管理启用 SSH/RDP。

Monitor:

  • SNMP 简单网络管理协议,前文已述,允许访问网络设备的信息
  • Syslog 允许设备发送事件,用于事件日志记录
  • Azure Monitor是网络监控解决方案,包含Log Analytics工具,用以查询、分析日志

    PowerShell

    学习目标
  • 使用Azure PowerShell 连接/操作 Azure资源
    Azure Portal,Azure CLI,Azure PowerShell是管理Azure资源的三种工具,相比Azure Portal页面,脚本工具因可以编写逻辑而更适合进行批量操作,以及自动化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Import-Module Az
    Connect-AzAccount
    Get-AzResourceGroup
    ... <-- 这里会列出资源组
    Get-Credential
    ... <-- 这里设置访问虚拟机的凭据
    New-AzVM -Name "testvm-eus-01" -ResourceGroupName "learn-940e9418-9b64-4c5b-a12c-a136ccb641da" -Credential (Get-Credential) -Location "East US" -Image UbuntuLTS -OpenPorts 22
    $vm = (Get-AzVM -Name "testvm-eus-01" -ResourceGroupName learn-940e9418-9b64-4c5b-a12c-a136ccb641da)
    $vm | Get-AzPublicIpAddress
    ssh QQs@13.92.231.172
    ... <-- 使用ssh连接虚拟机
    Stop-AzVM -Name $vm.Name -ResourceGroup $vm.ResourceGroupName
    Remove-AzVM -Name $vm.Name -ResourceGroup $vm.ResourceGroupName
    $vm | Remove-AzNetworkInterface –Force
    Get-AzDisk -ResourceGroupName $vm.ResourceGroupName -DiskName $vm.StorageProfile.OSDisk.Name | Remove-AzDisk -Force
    Get-AzVirtualNetwork -ResourceGroup $vm.ResourceGroupName | Remove-AzVirtualNetwork -Force
    Get-AzNetworkSecurityGroup -ResourceGroup $vm.ResourceGroupName | Remove-AzNetworkSecurityGroup -Force
    Get-AzPublicIpAddress -ResourceGroup $vm.ResourceGroupName | Remove-AzPublicIpAddress -Force
    注意 上面停止并移除虚拟机后,其他相关资源如网络接口、托管磁盘、网络安全组、公共IP另需手动删除
    似乎应该具备编写powershell脚本的能力,知乎:PowerShell有没有必要学?
    1
    2
    3
    4
    5
    6
    7
    8
    param([string]$resourceGroup) // 获取变量参数
    $adminCredential = Get-Credential -Message "Enter a username and password for the VM administrator."
    For ($i = 1; $i -le 3; $i++)
    {
    $vmName = "ConferenceDemo" + $i
    Write-Host "Creating VM: " $vmName
    New-AzVm -ResourceGroupName $resourceGroup -Name $vmName -Credential $adminCredential -Image UbuntuLTS
    }

Q: Admin1 attempts to deploy an Azure Marketplace resource by using an Azure Resource Manager template. Admin1 deploys the template by using Azure PowerShell and receives the following error message: “User failed validation to purchase resources. Error message: “Legal terms have not been accepted for this item on this subscription. To accept legal terms, please go to the Azure portal (http:// go.microsoft.com/fwlink/?LinkId=534873) and configure programmatic deployment
for the Marketplace item or create it there for the first time.”
You need to ensure that Admin1 can deploy the Marketplace resource successfully.
What should you do?
Answer is: From Azure PowerShell, run the Set-AzMarketplaceTerms cmdlet

数据和存储

数据:结构化数据、半结构化数据(也就是NoSQL数据,如Json数据,Xml数据)、非结构化数据
事务数据库:联机事务处理(Online Transaction Processing,OLTP)系统和联机分析处理(Online Analytical Processing,OLAP)系统,通常情况下,前者服务于较大量的用户,响应更快,可用性更高,处理大量数据(handle large volumns of data),后者用于处理大型复杂事务(handle large and complex transactions)
建议使用Azure Cosmos DB管理NoSQL数据,使用Azue Blob Storage管理文件数据,结构化数据使用Azure SQL Database, Azure SQL Database可以认为是云端托管的sqlserver

订阅

AZ104 Q9 Only a global administrator can add users to this tenant.
跨订阅移动资源,虚拟机、存储、虚拟网络、托管磁盘(managed disk)、Recovery Service均可移动 Microsoft Docs:跨订阅移动方案

Azure Backup

AZ104 Q7 Azure Backup 执行备份并不受限于虚拟机的os,是否在运行。
AZ104 Q8 Azure Recovery Vault 如果数据源位于多个区域中,请为每个区域创建恢复服务保管库

unachieved

You have a Microsoft 365 tenant and an Azure Active Directory (Azure AD) tenant named
contoso.com.
You plan to grant three users named User1, User2, and User3 access to a temporary Microsoft SharePoint document library named Library1. You need to create groups for the users. The solution must ensure that the groups are deleted automatically after 180 days.
Which two groups should you create? Each correct answer presents a complete solution.
A. an Office 365 group that uses the Assigned membership type
B. a Security group that uses the Assigned membership type
C. an Office 365 group that uses the Dynamic User membership type
D. a Security group that uses the Dynamic User membership type
E. a Security group that uses the Dynamic Device membership type

hint:Microsoft 365 组过期策略 answer is AC

解析JWT token —> jwt.io

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

  • “紧凑地、自包含地形式” 自包含即中间部分包含部分用户信息
  • 通过JSON形式作为web应用中的令牌,用于在各方之间安全地传输信息

结构:
以.分隔地三个部分:标头header,载荷payload,签名signature 三部分均以base64编码

标头:如下的编码描述

1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}

载荷:可以放user profile中的非敏感信息
签名:将前两部分信息连同加密salt使用密钥加密生成签名,如
HMACSHA256(base64UrlEncode(header)+’.’+base64UrlEncode(payload).secret)

解析后的json形如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"iss": "https://csdentaldevb2c.b2clogin.com/ea520207-3fcd-4afc-9b75-90139cd87407/v2.0/",
"exp": 1632306604,
"nbf": 1632303004,
"aud": "5d91d9f1-d3f0-44bb-93ab-1db127a11b35",
"idp": "LocalAccount",
"oid": "ae0dff61-7c3d-460e-87ad-f2567dd17b6f",
"sub": "ae0dff61-7c3d-460e-87ad-f2567dd17b6f",
"emails": [
"csdealer@yopmail.com"
],
"tfp": "B2C_1_CloudFx-ROPC",
"scp": "User.Standard",
"azp": "23ed21b8-c34d-4319-896e-0ced35ea6701",
"ver": "1.0",
"iat": 1632303004
}

json中的这些属性成为claim

  • iss 即issuer 令牌的发布服务
  • exp 即expiration time 有效期
  • nbf 即not valid before 生效期
  • aud 即audience 令牌的接受者,或者受众

参考 .net core 中的缓存内存

1
2
3
4
5
6
7
8
9
10
using Microsoft.Extensions.Caching.Memory;

public class HomeController : Controller
{
private IMemoryCache _cache;

public HomeController(IMemoryCache memoryCache)
{
_cache = memoryCache;
}

CacheKeys API
1
2
3
4
5
6
7
8
9
10
11
12
13
public static class CacheKeys
{
public static string Entry { get { return "_Entry"; } }
public static string CallbackEntry { get { return "_Callback"; } }
public static string CallbackMessage { get { return "_CallbackMessage"; } }
public static string Parent { get { return "_Parent"; } }
public static string Child { get { return "_Child"; } }
public static string DependentMessage { get { return "_DependentMessage"; } }
public static string DependentCTS { get { return "_DependentCTS"; } }
public static string Ticks { get { return "_Ticks"; } }
public static string CancelMsg { get { return "_CancelMsg"; } }
public static string CancelTokenSource { get { return "_CancelTokenSource"; } }
}

缓存一个时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DateTime cacheTiming;

// Look for cache key.
if (!_cache.TryGetValue(CacheKeys.Entry, out cacheEntry))
{
cacheEntry = DateTime.Now;

// Set cache options.
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromSeconds(3));

// Save data in cache.
_cache.Set(CacheKeys.Entry, cacheTiming, cacheEntryOptions);
}

取出缓存
1
var timing = _cache.Get<DateTime?>(CacheKeys.Entry);

可调过期(slide expiration)时间和绝对过期(absolute expiration)时间

关于section

EMSCRIPTEN_KEEPALIVE宏

enscripten embind

C++暴露接口的一种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <emscripten/bind.h>

using namespace emscripten;

#include "../wrapper/DoSomething.cpp"

// binding code
EMSCRIPTEN_BINDINGS(DoSomething)
{
class_<DoSomething>("DoSomething")
.constructor()
.function("SetInputData", &DoSomething::SetInputData)
.function("DoAction", &DoSomething::DoAction)
.function("GetOutput", &DoSomething::GetOutput);
}

上述代码将C++类DoSomething中的方法SetInputData,DoAction,GetOutput暴露在wasm模块中

Javascript

window.requestAnimationFrame

顾名思义用于动画帧的绘制, 类似于setInterval,传入回调函数,该回调函数将会在下一次浏览器尝试重新绘制当前帧动画时被调用

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
//迭代调用以使dom持续更新

<html>
<head>
<style>
div {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
</head>
<body>
<div></div>
</body>
<script>
let start = null;
let element = document.querySelector('div');

const step = (timestamp) => {
if (!start) start = timestamp;
let progress = timestamp - start;
element.style.left = Math.min(progress / 10, 200) + 'px';
if (progress < 2000) {
window.requestAnimationFrame(step);
}
}

window.requestAnimationFrame(step);
</script>
</html>

Performance API

performance.timing
performance.now()返回当前时刻距离 “time origin” 所经过的毫秒数,以此可以计算代码执行所花时间,精度大于Date.now()

requestIdleCallback

传入一个回调函数,在浏览器的空闲时段内调用的函数排队。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。

TypedArray

类型化数组,其实例描述底层的二进制数据缓冲区的类数组视图。

实际上并没有TypedArray这个全局属性或者构造方法,可以认为是Int8Array,Uint32Array等对象的实例化数组的统称

1
2
3
4
5
6
7
8
9
10
11
12
13
const DEFAULT_INDEX = 0;
// Way one:
const int8Arr = new Int8Array(10);
int8Arr[DEFAULT_INDEX] = 16;
console.log(int8Arr); // Int8Array [16, 0, 0, 0, 0, 0, 0, 0, 0, 0]
int8Arr[0]=256, int8Arr[1]=257;
console.log(int8Arr); // Int8Array(10) [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]

// Way two:
const buffer = new ArrayBuffer(16);
uintArray = new Uint8Array(buffer); // Uint8Array(16) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
uintArray.set([255,255,255],4)
console.log(uintArray); // Uint8Array(16) [0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Way two中,ArrayBuffer 的构造函数其参数指定了该 ArrayBuffer 所能够存放的单字节数量,因此在“转换到”对应的 TypedArray 时,一定要确保 ArrayBuffer 的大小是 TypedArray 元素类型所对应字节大小的整数倍。

TypedArray.prototype.set, 方法接受两个参数,第一个参数为将要进行数据读取的 JavaScript 普通数组;第二个参数为将要存放在类型数组中的元素偏移位置。

可以作为类型化数组的内置对象

  • Int8Array
  • Uint8Array
  • Uint8ClampedArray
  • Int16Array
  • Uint16Array
  • Int32Array
  • Uint32Array
  • Float32Array
  • Float64Array

    C/C++

    对于C++的函数重载,C++编译器通常使用名为 “Name Mangling” 的机制,在编译的可执行文件中区分同名函数

    使用extern “C” {}用以避免“Name Mangling”处理:由于在这个特殊的结构中,C++ 编译器会强制以 C 语言的语法规则,来编译放置在这个作用域内的所有 C++ 源代码。而在 C 语言的规范中,没有“函数重载”这类特性,因此也不会对函数名进行 “Name Mangling” 的处理。

    编译优化

    DCE(Dead Code Elimination)

    在诸如 Clang / GCC 等编译器中,我们通常可以为编译器指定一些有关编译优化的标记,以让编译器可以通过使用不同等级的优化策略来优化目标代码的生成。而诸如 -O0 / -O1 / -O2 一直到 -Os 与 -O4 等选项,便是这些优化标记中的一部分。

    原码 反码 补码

    原码符号位不变 逐位取反—> 反码

    反码+1 —> 补码

    访问控制列表

    ACL(Access Control List)

    堆栈机、寄存器机和累加器机

显然,.Net Core开发过程中,使用Visual Studio提供的近乎完美IDE,build和deploy都非常简单,如果说是用jenkins进行持续集成,那便相当于用脚本完成更新源码—构建—部署等过程。

jenkins ant

Apache Ant,是一个将软件编译、测试、部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发。由Apache软件基金会所提供。默认情况下,它的buildfile(XML文件)名为build.xml。——————wiki

build.xml定义了若干步骤(即target),以xml节点格式定义每个步骤的目录,执行程序,以及参数等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" ?> 
<project name="Hello World" default="execute">

<target name="init">
<mkdir dir="build/classes"/>
<mkdir dir="dist"/>
</target>
<target name="compile" depends="init">
<javac srcdir="src" destdir="build/classes"/>
</target>

<target name="compress" depends="compile">
<jar destfile="dist/HelloWorld.jar" basedir="build/classes" />
</target>

<target name="execute" depends="compile">
<java classname="HelloWorld" classpath="build/classes"/>
</target>

</project>

在Jenkins中可以配置使用Apache Ant,在构建时便可以使用build.xml来管理步骤
JenkinsAnt
源码目录build/build.xml:
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
42
43
44
45
46
47
48
<?xml version="1.0"?>

<project name="PartnerPortal" default="PartnerPortal" basedir=".">
<description>
PartnerPortal Daily Build File.
</description>

<property file="build.properties"/>

<target name="build_partner_portal" description="Build CS ScanFlow with Microsoft Visual Studio">
<echo message=""/>
<echo message="======================================================="/>
<echo message=" build CSD PP x64 "/>
<echo message="======================================================="/>
<echo message=""/>
<echo message="MSVC : ${msbuild.exe}"/>
<echo message="root : ${root_dir}"/>
<exec dir="." executable="restore_dotnet.bat" failonerror="true" />
<exec dir="." executable="${msbuild.exe}" failonerror="true">
<arg line="../CSD.PartnerPortal.sln /property:Configuration=Release"/>
</exec>
</target>

<target name="restore_envirement" description="restore dotnet">
<echo message=""/>
<echo message="======================================================="/>
<echo message=" restore dotnet "/>
<echo message="======================================================="/>
<echo message=""/>
<exec dir="." executable="restore_dotnet.bat" failonerror="true" />
</target>

<target name="publish_to_server" description="publish to server">
<echo message=""/>
<echo message="======================================================="/>
<echo message=" publish start "/>
<echo message="======================================================="/>
<echo message=""/>
<exec dir="." executable="publish.bat" failonerror="true" />
</target>

<target name ="PartnerPortal" description="Build solution">
<antcall target="restore_envirement" />
<antcall target="build_partner_portal" />
<antcall target="publish_to_server" />
</target>

</project>

build/restore_dotnet.bat:
1
dotnet restore ../CSD.PartnerPortal.sln

build/publish.bat:
1
dotnet publish --no-build -c Release "..\CSD.PartnerPortal.csproj" /p:PublishProfile="..\Properties\PUblishProfiles\CSDPPci - Web Deploy.pubxml" /p:Password=xxxxxxxxxxxxxxxxxxxxxxxxxxx

项目的Properties目录下的 .pubxml配置:
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
<?xml version="1.0" encoding="utf-8"?>

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>MSDeploy</WebPublishMethod>
<ResourceId>/subscriptions/subscriptionid01/resourceGroups/resourcegroupname01/providers/Microsoft.Web/sites/CSDPPci</ResourceId>
<ResourceGroup>resourcegroupname01</ResourceGroup>
<PublishProvider>AzureWebSite</PublishProvider>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish>http://csdppci.azurewebsites.net</SiteUrlToLaunchAfterPublish>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<ProjectGuid>2df39477-f1f3-4522-9ca7-d0eefb5b16b7</ProjectGuid>
<MSDeployServiceURL>csdppci.scm.azurewebsites.net:443</MSDeployServiceURL>
<DeployIisAppPath>CSDPPci</DeployIisAppPath>
<RemoteSitePhysicalPath />
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
<EnableMSDeployBackup>True</EnableMSDeployBackup>
<UserName>$CSDPPci</UserName>
<_SavePWD>True</_SavePWD>
<_DestinationType>AzureWebSite</_DestinationType>
<InstallAspNetCoreSiteExtension>False</InstallAspNetCoreSiteExtension>
</PropertyGroup>
</Project>

架构视图

设计文档中要附有大量、各种各样的图,目的是为了与包括开发,项目,dba等角色达成更好的沟通

  • 逻辑视图
  • 开发视图
  • 过程视图(如泳道图)
  • 物理视图
  • 场景视图

Wireframe