Serverless Single Page Apps:Fast, Scalable, and Available(读书笔记)

Serverless Single Page Apps Fast, Scalable, and Available

Intro[编辑]

  1. Avoid Yaks(yak shaving)
  2. Move Faster with Tests(work with confidence)
  3. TDD:Red-Green-Refactor

Starting Simple[编辑]

  1. Benefits of a Serverless Design
    1. 无服务器维护开销,focused on app
    2. Easy to Scale(?)
    3. Highly Available
    4. Low Cost(不过这只是相对的,带宽IO和存储会随着用户数上升的)
    5. (Micro)Service Friendly
    6. Less Code
  2. Limitations
    1. Vendor Lock-In
    2. Odd Logs
    3. Different Security Model
    4. Different Identity Model
    5. Loss of Control
    6. Big Scale: Big Money?
  3. 本书项目:https://github.com/benrady/learnjs
  4. Running Locally
    1. learnjs $ ./sspa server
    2. https://github.com/livereload/LiveReload 有这个必要吗
  5. Deploying to Amazon S3
    1. $ sudo pip install awscli
    2. $ aws configure --profile admin (需要access key和secret key)
    3. Attach Policy(设置该用户能够访问哪些aws服务)
    4. Creating an S3 Bucket
      1. learnjs $ ./sspa create_bucket learnjs.benrady.com
      2. $ ./sspa deploy_bucket learnjs.benrady.com
        1. 这里用户的域名是怎么关联到实际的虚拟主机 http://learnjs.benrady.com.s3-website-us-east-1.amazonaws.com的?
        2. 哦,创建一个CNAME项。。。

Routing Views with Hash Events[编辑]

  1. Build seams into the design
  2. Jasmine http://jasmine.github.io
  3. Running Tests in Production(一个不错的想法!)
  4. var learnjs = {};
    learnjs.showView = function(hash) {
    var problemView = $('<div class="problem-view">').text('Coming soon!');
    $('.view-container').empty().append(problemView);
  5. Adding Routes
  6. Adding View Parameters
    1. spy?这使用的是ES6 Proxy技术实现的吗?
      1. spyOn(learnjs, 'problemView'); ... expect(learnjs.problemView).toHaveBeenCalledWith('42');
  7. 测试:Fast, Informative, Reliable, and Exhaustive
  8. Favor testability over encapsulation!
  9. 测试hashchange事件:
    1. learnjs.appOnReady();
    2. spyOn(learnjs, 'showView');
    3. $(window).trigger('hashchange');
    4. expect(learnjs.showView).toHaveBeenCalledWith(window.location.hash);
  10. 实现onhashchange:window.onhashchange = function() { learnjs.showView(window.location.hash); };
    1. SPA的核心还是很简单的~
  11. Next Steps:
    1. Jasmine Matchers
    2. Jasmine-jQuery
    3. Test Doubles
    4. Routing Libraries https://github.com/flatiron/director http://visionmedia.github.io/page.js/
    5. JavaScript Testing Alternatives
    6. Hash Change Events
      1. window.history.push/popState

Essentials of SPA[编辑]

  1. var view = $('.templates .problem-view').clone(); //不过这里实际上并不是HTML5模板元素;
    CSS:.templates { display: none; }
  2. 定义data model:
    1. low object mapping impedance
    2. HTML5 data attributes
  3. Creating an Application Shell
    1. This flash of markup is annoying at best, and confusing at worst.
  4. Using Custom Events
    1. $('.view-container>*').trigger(name, args);
    2. view.bind('removingView', function() { ... })
  5. Next Steps
    1. Web Accessibility
    2. Creating a Home Screen Icon
    3. CSS Animations
    4. Form Validation

使用Amazon Cognito作为身份服务[编辑]

  1. Creating an Identity Pool(基本上可以理解为匿名用户?)
    1. learnjs $ ./sspa create_pool conf/cognito/identity_pools/learnjs
      1. ==> learnjs/4001/conf/cognito/identity_pools/learnjs/pool_info.json
        "IdentityPoolId": "us-east-1:71958f90-67bf-4571-aa17-6e4c1dfcb67d",
        "SupportedLoginProviders": { "accounts.google.com": "ABC123ADDYOURID.apps.googleusercontent.com", ...
    2. IAM Roles and Policies(?app用户并不是直接使用aws服务,而是通过app代理来间接使用aws吧?)
      1. assume_role_policy.json(内容略)
      2. Cognito uses Amazon's Security Token Service (STS) to generate temporary AWS credentials for our users.
        1. "Arn": "arn:aws:iam::730171000947:role/learnjs_cognito_authenticated" ?
  2. Fetching a Google Identity
    1. You might find Google’s process for adding a Sign-In button a bit...intrusive.(必须在页面上插入一个UI按钮)
    2. <script src="https://apis.google.com/js/platform.js" async defer></script>
    3. <meta name="google-signin-client_id" content="ABC123ADDYOURID.apps.googleusercontent.com"/>
    4. 定义JSONP回调:function googleSignIn() { ... }
    5. 最后:<span class="g-signin2" data-onsuccess="googleSignIn"></span>
  3. Requesting AWS Credentials
    1. 理论上说来,Cognito可以管理一个全局的identity池,而不是app特定的。。。(因为OAuth2本身是全局的)
    2. function googleSignIn(googleUser) {
      var id_token = googleUser.getAuthResponse().id_token;
      ... //请求将得到的token加入到身份池,然后app得到一个Cognito user ID(注意,这里体现的DDD的领域转换原则)
    3. Refreshing Tokens:gapi.auth2.getAuthInstance().signIn(...) --> ...
      1. => var deferred = new $.Deferred(); ... //这里的代码感觉有点过时了,ES6 Promise现在应该可以用了
  4. Creating a Profile View(略,配图似乎有点问题?)
  5. Next Steps
    1. Developer-Authenticated Identities

存储数据in DynamoDB[编辑]

  1. 一维主键:hash primary key
    1. 两维:hash attribute + range(排序)
  2. 属性名 <= 255 bytes
  3. DynamoDB supports a range of types for attribute values
    1. In addition, you can have attributes with document types, like Lists and Maps(属性值可以嵌套?K-V Store变成了文档数据库?)
  4. ... but out of the box it's essentially a big hash map.
  5. Strong vs. Eventual Consistency
  6. conf/dynamodb/tables/learnjs/config.json
    1. 3个顶级属性:AttributeDefinitions, KeySchema, and ProvisionedThroughput
      1. read/write unit:每秒<4KB的读(写<1KB??)
      2. app开发者需确保key在hash空间均匀分布,否则可能ProvisionedThroughputExceededException
    2. dynamodb create-table
  7. Secondary Indexes and Query vs. Scan
    1. 二级索引:global and local
  8. Authorizing DynamoDB Access:conf/dynamodb/tables/learnjs/role_policy.json
    1. 感觉这里基于aws Web服务来写Web应用就是戴着一堆镣铐在跳舞(处处是配额限制、安全过滤等等)
  9. 写文档:new AWS.DynamoDB.DocumentClient().put(item)
  10. Data Access and (服务器端)Validation
    1. By expanding the conditions clause in our IAM policy,
    2. We can only enforce rules about the type of request, where it's from, who made it, and things like that.
      1. 不能验证数据本身的格式 => 可使用Lambda来创建定制的Web服务...

用Lambda来构建微服务[编辑]

  1. With Lambda, Amazon has jumped firmly onto the microservices bandwagon.
  2. 写一个带2个参数的函数,保存为.js,然后与其node依赖打包为zip,上传,OK。
  3. Accessing the underlying Linux environment from your Lambda service is not only permitted but encouraged
  4. exports.echo = function(json, context) { context.succeed(["Echo: " + JSON.stringify(json)]); }
  5. Limits
    1. Each Lambda function gets 512MB of ephemeral disk space on the filesystem, located at /tmp
    2. 默认并发请求:100?
    3. a single execution cannot take more than 300 seconds
  6. How we pay?
    1. gigabyte-second
    2. For example, 128MB内存、100ms运行、100,000次调用, 则125GBS, 约$0.02
    3. Making asynchronous requests in parallel, rather than serially(程序越并行执行越节省!)
  7. Deploy First
    1. currently uses Node.js v4.3.2
    2. learnjs $ ./sspa build_bundle
    3. learnjs $ ./sspa create_service conf/lambda/functions/echo
    4. 创建IAM role learnjs_lambda_exec,以允许lambda访问DynamoDB:
      1. $ aws --profile admin iam list-policies //列出所有预定义的策略;
      2. $ aws --profile admin iam attach-role-policy \
        --role-name learnjs_lambda_exec \
        --policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
  8. 编写
    1. LastEvaluatedKey:超过1MB响应限制(分页)——但是这次每次请求服务都会来全表scan,没有cache层吗?
    2. learnjs $ ./sspa deploy_bundle
  9. 调用
    1. new AWS.Lambda().invoke(params); //FunctionName: 'learnjs_popularAnswers', Payload: JSON.stringify({problemNumber: problemId})
  10. Using the Amazon API Gateway
    1. Add API endpoints

Serverless Security[编辑]

  1. Securing Your AWS Account!
    1. Disabling Any Root Access Keys
    2. Managing Users with Profiles
    3. Securing AWS Credentials
      1. 本地文件系统加密?OSX FileVault、Ubuntu EncryptedHome
    4. Set Up Multifactor Authentication
  2. Query Injection Attacks
  3. Cross-Site Scripting(XSS)Attacks(导致向目标网站页面注入恶意JS)
    1. Sandboxing JavaScript Using Web Workers
      1. worker.js:postMessage(eval(e.data));
  4. Cross-Site Request Forgery(请求伪造,泄露敏感数据)
    1. 要求请求必须是POST,且满足特定编码格式?
    2. Cross-Origin Requests and the Same-Origin Policy(POST请求的url必须与当前origin一致)
  5. Wire Attacks and Transport Layer Security
    1. Sidejacking Attacks(==> 全站https?)
  6. Denial-of-Service Attacks
    1. Protecting S3 with CloudFront
    2. Distributed Denial-of-Service(DDoS)
      1. => CloudWatch?
  7. Next Steps
    1. Using Signed URLs

Scaling Up[编辑]

  1. Monitor Web Services(CloudWatch的内部原理是什么?http前端反向代理?)
    1. Send the alert to Amazon's Simple Notification Service (SNS)
      1. $ aws --profile admin sns create-topic --name EmailAlerts
      2. $ aws --profile admin sns subscribe \
        --topic-arn « your_topic_arn » \
        --protocol email \
        --notification-endpoint you@example.com
      3. $ aws --profile admin cloudwatch put-metric-alarm ...
  2. Unexpected Expenses*
  3. Analyze S3 Web Traffic
    1. Logging S3 Requests(创建bucket):
      1. $ aws --profile admin s3 mb s3://learnjs-logging.benrady.com
      2. $ aws s3api put-bucket-acl --bucket learnjs-logging.benrady.com --grant-write URI=http://acs.amazonaws.com/groups/s3/LogDelivery --grant-read-acp URI=...
      3. $ aws s3api put-bucket-logging --generate-cli-skeleton > conf/s3/ « your.bucket.name » /logging.json
      4. $ aws --profile admin s3api put-bucket-logging --cli-input-json "file://conf/s3/learnjs.benrady.com/logging.json"
      5. $ aws s3 sync s3://learnjs-logging.benrady.com/ logs
    2. 分析S3 access logs
      1. Response Code Frequency:$ cat logs/* | cut -d ' ' -f 13 | sort | uniq -c
      2. Popular Resources:$ cat logs/2016-01-1[123]* | cut -d ' ' -f 11 | sort | uniq -c| sort -rn
      3. Usage by Time of Day:
        $ cat logs/* | awk '{ print $3 }' | tr ':' ' ' | awk '{ print $2 ":" $3}' | sort | uniq -c
  4. Optimize for Growth
    1. learnjs $ aws s3api put-object --profile admin --acl 'public-read' --bucket learnjs.benrady.com --cache-control 'max-age=31536000' --key vendor.js --body public/vendor.js
      1. 不过,感觉这个针对特定url path的静态缓存策略不是很灵活啊?
    2. Invalidating Caches with Versioned Filenames
  5. Costs of the Cloud
    1. ... This means the loading cost of our app, including request and transfer fees, will be $0.24 for every 10,000 users
    2. To put this in perspective, the AWS Free Tier for DynamoDB lets us perform up to 2.1 million writes per day at no cost.
    3. Microservice Costs
      1. the Amazon Free Tier provides for 400,000 gigabyte-seconds of execution at no cost.(但不包括额外的read capacity)
  6. !Buying capacity based on average usage means your app will be broken half of the time.
  7. Creating a Client Logging Web Service
    1. 捕获window.onerror,发送到CloudWatch(注意,你不能信任这些log,因为它们有可能是hacker伪造的?)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值