Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scala Matsuri 2017

Scala Matsuri 2017

yoshiyoshifujii

February 25, 2017
Tweet

More Decks by yoshiyoshifujii

Other Decks in Programming

Transcript

  1. Let's Build a Serverless Architecture in Scala! Yoshitaka Fujii (@yoshiyoshifujii)


    2017 ScalaMatsuri
 Saturday, February 25th
 16:30 - 17:10 Conference Room 1
  2. Who am I ? • Yoshitaka Fujii (@yoshiyoshifujii) • Joined

    MOTEX in April, 2014 • Software Engineer • Scala(19 months) • Scala Kansai summit 2016 staff. ࣗݾ঺հɻΤϜΦʔςοΫεגࣜձࣾɻ4DBMBྺϲ݄ɻ4DBMBؔ੢αϛοτͰελοϑ͍͖ͤͯͨͩ͞·ͨ͠ɻ
  3. Serverless Architecture • using FaaS • a significant reduction in

    costs • scalability • the lack of operating and maintaining infrastructure αʔόϨεΞʔΩςΫνϟͱ͸ɺ'BB4Λ׆༻ͨ͠γεςϜɻίετͷେ෯ͳ࡟ݮɻεέʔϥϏϦςΟɻΠϯϑϥͷӡ༻؅ཧ͕ෆཁɻ
  4. Function as a Service • AWS Lambda • Google Cloud

    Function • Microsoft Azure Functions
  5. AWS Lambda • AWS Lambda is a compute service that

    lets you run code without provisioning or managing servers. • executes your code only when needed. • scales automatically, a few requests per day to thousands per second. • Node.js, Java, C# and Python "84-BNCEB͸αʔόʔΛϓϩϏδϣχϯάͨ͠Γ؅ཧ͠ͳͯ͘΋ίʔυΛ࣮ߦͰ͖ΔίϯϐϡʔςΟϯάαʔϏεͰ͢ɻඞཁͳ ͱ͖ʹίʔυΛ࣮ߦ͠ɺࣗಈతʹεέʔϧ͠·͢ɻ
  6. AWS Lambda Events • API Gateway (HTTP Requests) • Kinesis

    Streams • DynamoDB • S3 • Schedule (CloudWatch) • SNS • IoT ͜ΕΒͷ"84αʔϏεͷΠϕϯτʹԠͯ͡"84-BNCEBΛ࣮ߦͰ͖·͢ɻࠓճ͸ɺओʹ"1*(BUFXBZͱ,JOFTJT4USFBNTʹ͍ͭͯ औΓ্͛·͢ɻ
  7. Amazon API Gateway • Amazon API Gateway is a fully

    managed service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale. • Low-Cost and Efficient.
 (only for calls made to your APIs and data transfer out) • Performance at Any Scale • Run Your APIs Without Servers ϑϧϚωʔδυαʔϏεͰɺ։ൃऀ͸ͲͷΑ͏ͳεέʔϧͰ͋ͬͯ΋ɺ؆୯ʹ"1*ͷ࡞੒ɺ഑෍ɺอकɺ؂ࢹɺอޢ͕ߦ͑·͢ɻ
  8. Amazon Kinesis Streams • Use Amazon Kinesis Streams to collect

    and process large streams of data records in real time. • rapid and continuous data intake and aggregation. • Accelerated log and data feed intake and processing. • Real-time metrics and reporting. • Real-time data analytics. • Complex stream processing. "NB[PO,JOFTJT4USFBNTΛ࢖༻ͯ͠ɺσʔλϨίʔυͷେྔͷετϦʔϜΛϦΞϧλΠϜͰऩू͠ɺॲཧ͠·͢ɻߴ଎͔ͭܧଓత ʹσʔλͷऔΓࠐΈͱू໿Λߦ͏͜ͱ͕Ͱ͖·͢ɻ
  9. Amazon API Gateway client AWS Lambda Amazon S3 Amazon DynamoDB

    Amazon Kinesis AWS Lambda AWS Lambda Amazon Elasticsearch Service Context + Token Principal + Policy Policy is cached Denied 403 Allowed Auth function Consumers function System diagrams
  10. Amazon API Gateway client AWS Lambda Amazon S3 Amazon DynamoDB

    Amazon Kinesis AWS Lambda Amazon Elasticsearch Service Policy is cached Large scale system client client client client client AWS Lambda AWS Lambda AWS Lambda AWS Lambda AWS Lambda AWS Lambda AWS Lambda AWS Lambda AWS Lambda AWS Lambda AWS Lambda େن໛ͳγεςϜΛ૝ఆ͍ͯ͠·͢ɻ
  11. Large scale system • More functional requirements. • AWS Lambda

    wants to be a simple function. • 1 Lambda per method request.
 GET:/hello => getHello
 POST:/hello => postHello • develop and deploy efficiently େن໛ͳγεςϜ͸ɺػೳཁ͕݅ଟ͍ɻ"84-BNCEB͸γϯϓϧͳ'VODUJPOΛอ͍ͪͨɻϝιουϦΫΤετʹ͖ͭ-BNCEBΛ ͭɻ·ͨޮ཰ྑ͘։ൃͱσϓϩΠΛ͍ͨ͠ɻ
  12. RequestStreamHandler.java public interface RequestStreamHandler { /** * Handles a Lambda

    Function request * @param input The Lambda Function input stream * @param output The Lambda function output stream * @param context The Lambda execution environment context object. * @throws IOException */ public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException; } "84-BNCEBͷެ։ΠϯλϑΣʔεͰ͢ɻ͜ͷத਎Λ࣮૷͢Δͱ೚ҙͷॲཧ͕࣮ߦͰ͖·͢ɻ
  13. RequestHandler.java public interface RequestHandler<I, O> { /** * Handles a

    Lambda Function request * @param input The Lambda Function input * @param context The Lambda execution environment context object. * @return The Lambda Function output */ public O handleRequest(I input, Context context); } *0Λ೚ҙͷܕͰ࣮૷Ͱ͖·͕͢ɺ+BWB#FBOͳΫϥε΋͘͠͸ɺϓϦϛςΟϒͳܕͷΈʹͳ͓ͬͯΓɺ+BWBͷ੍໿Λड͚ͨΓ͢Δͷ Ͱɺ͋·ΓΦεεϝ͠·ͤΜɻ
  14. build.sbt lazy val root = (project in file(".")). settings( name

    := "aws-lambda-scala", organization := "com.example", scalaVersion := "2.12.1", libraryDependencies ++= Seq( "com.amazonaws" % "aws-lambda-java-core" % "1.1.0" ) )
  15. src/main/scala/com/example/Hello.scala class HelloHandler extends RequestStreamHandler { @throws(classOf[java.io.IOException]) override def handleRequest(input:

    InputStream, output: OutputStream, context: Context): Unit = { val bytes = toByteArray(input) output.write(bytes) } def toByteArray(input: InputStream) = Stream.continually(input.read).takeWhile(_ != -1).map(_.toByte).toArray }
  16. AWS CLI - lambda create function $ aws lambda create-function

    \ --region us-east-1 \ --function-name aws-lambda-scala \ --zip-file fileb://aws-lambda-scala-assembly-0.1.0-SNAPSHOT.jar \ --role arn:aws:iam::${AWS Account ID}:role/lambda_basic_execution \ --handler com.example.HelloHandler::handleRequest \ --runtime java8 \ --timeout 15 \ --memory-size 512
  17. AWS CLI - lambda create function { "LastModified": "2017-01-02T12:34:56.789+0000", "FunctionName":

    "aws-lambda-scala", "Runtime": "java8", "Version": "$LATEST", "Role": "arn:aws:iam::${AWS Account ID}:role/lambda_basic_execution", "CodeSha256": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Handler": "com.example.HelloHandler::handleRequest", "Timeout": 15, "Description": "", "MemorySize": 512, "FunctionArn": "arn:aws:lambda:us-east-1:${AWS Account ID}:function:aws-lambda-scala", "CodeSize": 5264477 }
  18. AWS CLI - lambda invoke $ aws lambda invoke \

    --region us-east-1 \ --function-name aws-lambda-scala \ --payload 123 \ --invocation-type RequestResponse /tmp/response { "StatusCode": 200 } 123
  19. Amazon API Gateway client AWS Lambda Amazon S3 Amazon DynamoDB

    Amazon Kinesis AWS Lambda AWS Lambda Amazon Elasticsearch Service Context + Token Principal + Policy Policy is cached Denied 403 Allowed Auth function Consumers function System diagrams
  20. Labor … • It is hard to run Lambda. •

    I will `assembly` one by one and upload it. • It is troublesome to configure the API Gateway on the console. -BNCEBͰ࣮ߦ͢Δ·Ͱ͕େมɻBTTFNCMZͯ͠Ξοϓϩʔυͯ͠Λ܁Γฦ͞ͳ͍ͱ͏·͘ಈ͔͘෼͔Βͳ͍ɻίϯιʔϧ্Ͱ"1* (BUFXBZͷઃఆΛߦ͏ͷ͸໘౗ɻ
  21. sbt-aws-serverless plugin • sbt plugin to deploy code to Amazon

    API Gateway and AWS Lambda. • https://github.com/yoshiyoshifujii/sbt-aws-serverless ࣗલͰ։ൃͨ͠TCUQMVHJOΛ࢖͍·͢ɻ"1*(BUFXBZ΍-BNCEBʹσϓϩΠ͢ΔQMVHJOͰ͢ɻ
  22. serverless framework • To be honest this way is better.

    • However, blue green deployment is difficult. ਖ਼௚ɺTFSWFSMFTTGSBNFXPSLΛ࢖͏ͷ͕ྑ͍ͱࢥ͍·͢ɻͨͩɺϒϧʔάϦʔϯσϓϩΠ͕Ͱ͖ͳ͍ҹ৅Ͱ͢ɻ
  23. Amazon API Gateway 4UBHF 4UBHF7BSJBCMFT UFTU FOWUFTU QSPE FOWQSPE %FQMPZNFOU

    3FTPVSDFT -BNCEB"3/  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@ AWS Lambda "MJBT 1VCMJTI7FSTJPOT EFW -"5&45 UFTU@  QSPE@  Blue-Green deployment - 1st release Amazon DynamoDB 5BCMF BDDPVOUUFTU BDDPVOUQSPE
  24. Amazon API Gateway 4UBHF 4UBHF7BSJBCMFT UFTU FOWUFTU QSPE FOWQSPE %FQMPZNFOU

    3FTPVSDFT -BNCEB"3/  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@ AWS Lambda "MJBT 1VCMJTI7FSTJPOT EFW -"5&45 UFTU@  QSPE@  UFTU@  Blue-Green deployment - 2nd release test Amazon DynamoDB 5BCMF BDDPVOUUFTU BDDPVOUQSPE
  25. Amazon API Gateway 4UBHF 4UBHF7BSJBCMFT UFTU FOWUFTU QSPE FOWQSPE %FQMPZNFOU

    3FTPVSDFT -BNCEB"3/  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@ AWS Lambda "MJBT 1VCMJTI7FSTJPOT EFW -"5&45 UFTU@  QSPE@  UFTU@  QSPE@  Amazon DynamoDB 5BCMF BDDPVOUUFTU BDDPVOUQSPEVDUJPO Blue-Green deployment - 2nd release
  26. in this case • Release the test environment as it

    is. • Quickly return to the previous version. • A/B Testing. • Canary Release.
 https://martinfowler.com/bliki/CanaryRelease.html ͜ͷํࣜͳΒɺςετͨ͠؀ڥΛͦͷ··ϦϦʔεͰ͖Δɻ͙͢ʹલͷόʔδϣϯʹ໭͢͜ͱ͕Ͱ͖Δɻ"#ςετ΍ɺΧφϦΞɾϦ Ϧʔεʹ࢖͑Δɻ
  27. Giter8 • https://github.com/yoshiyoshifujii/sbt-aws-serverless-ddd.g8 $ sbt new yoshiyoshifujii/sbt-aws-serverless-ddd.g8 name [My Something

    Project]: version [0.1.0-SNAPSHOT]: organization [com.example]: package [com.example]: (JUFSͰαϯϓϧϓϩδΣΫτΛެ։͠·ͨ͠ɻ
  28. DDD - Hexagonal architecture • Implementing Domain-Driven Design - 2013/2/16

    • Vaughn Vernon • Mitigate vendor lock-in. %%%ͷϔΩαΰφϧΞʔΩςΫνϟΛ࠾༻͢ΔɻϕϯμʔϩοΫΠϯΛ؇࿨Ͱ͖Δɻ
  29. Amazon API Gateway client AWS Lambda Amazon S3 Amazon DynamoDB

    Amazon Kinesis AWS Lambda AWS Lambda Amazon Elasticsearch Service Context + Token Principal + Policy Policy is cached Denied 403 Allowed Auth function Consumers function System diagrams Make this part
  30. build.sbt - dependsOn lazy val domain = (project in file("./modules/domain")).

    lazy val infraDynamo = (project in file("./modules/infrastructure/dynamodb")). dependsOn(domain). lazy val infraKinesis = (project in file("./modules/infrastructure/kinesis")). dependsOn(domain). lazy val appHello = (project in file("./modules/application/hello")). dependsOn(infraLambda, infraDynamo, infraKinesis). ϚϧνϓϩδΣΫτͷґଘؔ܎ΛґଘϞσϧͷ௨Γʹઃఆɻ
  31. Project tree • Sources under modules. • application is a

    module of Lambda. • Make the Infrastructure as finely as possible. • Reduce module size. ϓϩδΣΫτߏ੒ɻιʔε͸NPEVMFTσΟϨΫτϦͷ഑Լʹஔ͘ɻBQQMJDBUJPO͕-BNCEBͷϞδϡʔϧʹͳΔɻ*OGSBTUSVDUVSF͸ݶ Γͳ͘খ͘͞࡞Δɻ-BNCEBͷϞδϡʔϧαΠζΛখ͘͢͞ΔͨΊɻ
  32. domain • POSO (Plain old Scala object) • Do not

    specify anything for libraryDependencies. EPNBJO૚ɻ1040Ͱ࡞ΔɻMJCSBSZ%FQFOEFODJFTʹԿ΋ࢦఆ͠ͳ͍ɻ
  33. Account case class AccountId(value: String) extends ValueObject[String] case class Account(

    id: AccountId, version: Option[Version], email: String, password: String, name: String) extends Entity[AccountId]
  34. AccountRepository trait AccountRepository { def save(account: Account): Either[DomainError, Account] def

    get(id: AccountId): Either[DomainError, Option[Account]] def findBy(email: String): Either[DomainError, Option[Account]] def findAll: Either[DomainError, Seq[Account]] }
  35. AccountEventPublisher case class AccountModified( accountId: AccountId, email: String, password: String,

    name: String) trait AccountEventPublisher { def publish(modified: AccountModified): Either[DomainError, AccountModified] }
  36. infrastructure • implementation of Repository or Domain Event. • DI

    with Cake pattern. • It has no direct inheritance relation. JOGSBTUSVDUVSF૚ɻ3FQPTJUPSZ΍%PNBJO&WFOUͷ࣮૷Λ࣋ͭɻ$BLFQBUUFSOͰ%*͞ΕΔɻ௚઀ͷܧঝؔ܎Λ࣋ͨͳ͍ɻ
  37. AccountRepositoryOnDynamoDB trait AccountRepositoryOnDynamoDB { def save(account: Account): Either[DomainError, Account] =

    ??? def get(id: AccountId): Either[DomainError, Option[Account]] = ??? def findBy(email: String): Either[DomainError, Option[Account]] = ??? def findAll: Either[DomainError, Seq[Account]] = ??? }
  38. Base trait Base extends BaseStreamHandler { val accountRepository: AccountRepository val

    accountEventPublisher: AccountEventPublisher override def handle(input: Input): Try[String] = Try { JsObject( "message" -> JsString("hello world!!") ).compactPrint } }
  39. App class App extends Base { override val accountRepository =

    new AccountRepository with AccountRepositoryOnDynamoDB override val accountEventPublisher = new AccountEventPublisher with AccountEventPublisherOnKinesis }
  40. Amazon API Gateway client AWS Lambda Amazon S3 Amazon DynamoDB

    Amazon Kinesis AWS Lambda AWS Lambda Amazon Elasticsearch Service Context + Token Principal + Policy Policy is cached Denied 403 Allowed Auth function Consumers function System diagrams Make this part
  41. build.sbt - dependsOn lazy val domain = (project in file("./modules/domain")).

    lazy val infraDomain = (project in file("./modules/infrastructure/domain")). dependsOn(domain). lazy val appAccountModified = (project in file(“./modules/application/accountmodified”)). dependsOn(infraLambdaConsumer, infraDomain). ґଘؔ܎͸ɺ"1*(BUFXBZͱ΄΅ಉ͡ɻ
  42. sbt deploy prod $ sbt \ -DAWS_ACCOUNT_ID=<AWS Account ID> \

    -DAWS_ROLE_ARN=arn:aws:iam::<AWS Account ID>:role/<Role NAME> \ -DAWS_BUCKET_NAME=<BUCKET NAME> > deploy v1 API Gateway created: xxxxxxxxxx API Gateway put: xxxxxxxxxx Lambda deployed: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth Lambda published: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth:1 Lambda Alias: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth:prod Authorizer: auauau Lambda deployed: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello Lambda published: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello:1 Lambda Alias: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello:prod_1 Create Deployment: {Id: dddddd,Description: 0.1.0-SNAPSHOT,CreatedDate: Sat Feb 25 12:34:56 JST 2017,}
  43. Amazon API Gateway 4UBHF 4UBHF7BSJBCMFT UFTU FOWUFTU QSPE FOWQSPE %FQMPZNFOU

    3FTPVSDFT -BNCEB"3/  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@ AWS Lambda "MJBT 1VCMJTI7FSTJPOT EFW -"5&45 UFTU@  QSPE@  Blue-Green deployment - 1st release Amazon DynamoDB 5BCMF BDDPVOUUFTU BDDPVOUQSPE
  44. sbt deploy test $ sbt \ -DAWS_ACCOUNT_ID=<AWS Account ID> \

    -DAWS_ROLE_ARN=arn:aws:iam::<AWS Account ID>:role/<Role NAME> \ -DAWS_BUCKET_NAME=<BUCKET NAME> > deploy test API Gateway created: xxxxxxxxxx API Gateway put: xxxxxxxxxx Lambda deployed: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth Lambda published: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth:2 Lambda Alias: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth:test Authorizer: auauau Lambda deployed: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello Lambda published: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello:2 Lambda Alias: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello:test_2 Create Deployment: {Id: dddddd,Description: 0.1.0-SNAPSHOT,CreatedDate: Sat Feb 25 12:34:56 JST 2017,}
  45. Amazon API Gateway 4UBHF 4UBHF7BSJBCMFT UFTU FOWUFTU QSPE FOWQSPE %FQMPZNFOU

    3FTPVSDFT -BNCEB"3/  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@ AWS Lambda "MJBT 1VCMJTI7FSTJPOT EFW -"5&45 UFTU@  QSPE@  UFTU@  Blue-Green deployment - 2nd release test Amazon DynamoDB 5BCMF BDDPVOUUFTU BDDPVOUQSPE
  46. sbt deployCopy test to prod $ sbt \ -DAWS_ACCOUNT_ID=<AWS Account

    ID> \ -DAWS_ROLE_ARN=arn:aws:iam::<AWS Account ID>:role/<Role NAME> \ -DAWS_BUCKET_NAME=<BUCKET NAME> > deployCopy test prod Lambda Alias: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth:prod Lambda Alias: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello:prod_2 Stage: prod
  47. Amazon API Gateway 4UBHF 4UBHF7BSJBCMFT UFTU FOWUFTU QSPE FOWQSPE %FQMPZNFOU

    3FTPVSDFT -BNCEB"3/  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@  IFMMP IFMMP\TUBHF7BSJBCMFTFOW^@ AWS Lambda "MJBT 1VCMJTI7FSTJPOT EFW -"5&45 UFTU@  QSPE@  UFTU@  QSPE@  Amazon DynamoDB 5BCMF BDDPVOUUFTU BDDPVOUQSPEVDUJPO Blue-Green deployment - 2nd release
  48. sbt deployDev $ sbt \ -DAWS_ACCOUNT_ID=<AWS Account ID> \ -DAWS_ROLE_ARN=arn:aws:iam::<AWS

    Account ID>:role/<Role NAME> \ -DAWS_BUCKET_NAME=<BUCKET NAME> > deployDev dev API Gateway created: xxxxxxxxxx API Gateway put: xxxxxxxxxx Lambda deployed: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth Lambda Alias: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-auth:dev Authorizer: auauau Lambda deployed: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello Lambda Alias: arn:aws:lambda:us-east-1:aaaaaaaaaaaa:function:$name-app-hello:dev Create Deployment: {Id: ddddd,Description: 0.1.0-SNAPSHOT,CreatedDate: Sat Feb 25 12:34:56 JST 2017,}
  49. sbt deployList $ sbt \ -DAWS_ACCOUNT_ID=<AWS Account ID> \ -DAWS_ROLE_ARN=arn:aws:iam::<AWS

    Account ID>:role/<Role NAME> \ -DAWS_BUCKET_NAME=<BUCKET NAME> > deployList dev ============================================================================================================ xxxxxxxxxx ============================================================================================================ | Stage Name | Last Updated Date | Deployment Id | Description | |----------------------|--------------------------------|-----------------|--------------------------------| | dev | Mon Feb 20 21:30:07 JST 2017 | qirn6v | null | | v1 | Mon Feb 20 21:23:41 JST 2017 | 8tb1zr | null | ===================================================================================== xxxxxxxxxx ===================================================================================== | Created Date | Deployment Id | Description | |--------------------------------|-----------------|--------------------------------| | Mon Feb 20 21:30:07 JST 2017 | ddddd2 | 0.1.0-SNAPSHOT | | Mon Feb 20 21:23:41 JST 2017 | ddddd1 | 0.1.0-SNAPSHOT |
  50. sbt invoke $ sbt \ -DAWS_ACCOUNT_ID=<AWS Account ID> \ -DAWS_ROLE_ARN=arn:aws:iam::<AWS

    Account ID>:role/<Role NAME> \ -DAWS_BUCKET_NAME=<BUCKET NAME> > invoke prod ============================================================ GET:https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/prod/hellos ============================================================ 200 {"message":"hello world!!"}
  51. Summary • Scala is easy to combine DDD and Serverless.

    • Easy to share processing with multiple projects. • Cheap, scalable and easy to operate. 4DBMB͸%%%ͱ4FSWFSMFTTΛ૊Έ߹ΘͤΔͱ΍Γ΍͍͢ɻϚϧνϓϩδΣΫτͰॲཧΛڞ௨Խ͠΍͍͢ɻ҆ͯ͘εέʔϥϒϧͰӡ༻ ָ͕ɻ