4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

地球の裏側に来た。折角なのでAWSサービスの地理的挙動を試してみる~Global Accelaratorでルーティング最適化を体験してみる~

Last updated at Posted at 2025-12-29

こんにちは。
突然ですが、今私はトリ二ダード・トバゴにいます。
日本の裏側の南米に位置し、日本からは飛行機をNYで乗り継いで、総移動時間22時間の長旅です。

↓ピアルコ国際空港
image.png

自然が好きなので大型休暇で南米の大自然に触れに来たわけですが、
来る前に「なんか地理的差異を体感できる検証とかしたら楽しそうだな、、、」と思い付いたため、
折角なので認定資格取得の中でしか触れなかったようなサービスを触ってみることにしました!
(観光に来ているので、大した検証はしません!!)

はじめに

今回はパッと思いついた3つを検証してみます。
本記事では①を実施します。

  1. Global Accelaratorを使って、共通のエンドポイントからAWSで最適化されたALBにルーティングされる挙動を試してみる。ついでにレイテンシーを比較してみる。
  2. Route53の位置情報ルーティング・地理的近接性ルーティングを利用して、日本と南米から同じドメインにアクセスした際の挙動を見てみる。
  3. CloudFrontに静的ウェブサイトをホスティングし、エッジロケーションによりアクセスが高速化する様子を見てみる

日本にいても出来るやん、、と思うかもしれませんが、
南米から実際に日本にアクセスした際にどれくらい変わるの??というのを今回は見てみようと思います!

検証

前提事項

  • 今回は東京リージョンとブラジルのサンパウロリージョンにパブリックアクセス可能なALB+Lambdaをデプロイしてみます。

  • Lambdaはアクセス元の情報とアクセス先のリージョンを返すだけのシンプルな処理+レイテンシを比較するために少しデータ量を増やして、1MBほどのデータ転送が行われるようにします。

  • 環境作成にはCloudFormationを使って両リージョンに全く同じ構成をデプロイします。

  • セキュリティやネットワーク制御はガバガバですが、今回は検証用の一時的なものなので目を瞑ることにします。

作成に使用したCloudFormation
AWSTemplateFormatVersion: "2010-09-09"
Description: "Global Accelarator test"

Parameters:
  ProjectName:
    Type: String
    Default: geolatancy
  VpcCidr:
    Type: String
    Default: 10.0.0.0/16
  PublicSubnet1Cidr:
    Type: String
    Default: 10.0.0.0/24
  PublicSubnet2Cidr:
    Type: String
    Default: 10.0.1.0/24
  AlbListenerPort:
    Type: Number
    Default: 80
  AllowedIngressCidr:
    Type: String
    Default: 0.0.0.0/0
    Description: "For demo only. Restrict if needed."

Resources:
  # -------------------------
  # VPC / Subnets
  # -------------------------
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-vpc"

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-igw"

  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-public-rt"

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PublicSubnet1Cidr
      AvailabilityZone: !Select [0, !GetAZs ""]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-public-a"

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PublicSubnet2Cidr
      AvailabilityZone: !Select [1, !GetAZs ""]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-public-b"

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref PublicRouteTable

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable

  # -------------------------
  # Security Group for ALB
  # -------------------------
  AlbSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: !Sub "${ProjectName} ALB SG"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: !Ref AlbListenerPort
          ToPort: !Ref AlbListenerPort
          CidrIp: !Ref AllowedIngressCidr
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-alb-sg"

  # -------------------------
  # Lambda
  # -------------------------
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${ProjectName}-lambda-role-${AWS::Region}-${AWS::StackName}"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

  HelloFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub "${ProjectName}-hello-${AWS::Region}"
      Runtime: nodejs20.x
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Timeout: 10
      MemorySize: 128
      Code:
        ZipFile: |
          exports.handler = async (event) => {
            const now = new Date().toISOString();
            const ua =
              (event && event.headers && (event.headers["user-agent"] || event.headers["User-Agent"])) ||
              null;

            const payloadBytes = 256 * 1024; // 256KB
            const blob = "x".repeat(payloadBytes);

            const bodyObj = {
              region: process.env.AWS_REGION,
              now,
              path: event && event.path,
              requestId: event && event.requestContext && event.requestContext.requestId,
              ua,
              payloadBytes,
              blob,
            };

            const body = JSON.stringify(bodyObj);

            return {
              statusCode: 200,
              headers: {
                "content-type": "application/json",
                "cache-control": "no-store",
              },
              body,
            };
          };

  # ✅ Allow ALB (ELBv2) to invoke Lambda (create this BEFORE TargetGroup with DependsOn)
  AllowAlbInvokeLambda:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref HelloFunction
      Principal: elasticloadbalancing.amazonaws.com
      # SourceArn is TargetGroup ARN; but TG doesn't exist yet.
      # We'll set permission without SourceArn restriction to avoid create-order deadlock.
      # This is acceptable for a short-lived lab. If you want to restrict, use custom resource.
      # SourceArn: !Ref LambdaTargetGroup

  # -------------------------
  # ALB + TargetGroup (Lambda)
  # -------------------------
  Alb:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Sub "${ProjectName}-alb-${AWS::Region}"
      Scheme: internet-facing
      Type: application
      IpAddressType: ipv4
      Subnets:
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
      SecurityGroups:
        - !Ref AlbSecurityGroup

  LambdaTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    DependsOn:
      - AllowAlbInvokeLambda
    Properties:
      Name: !Sub "${ProjectName}-tg-${AWS::Region}"
      TargetType: lambda
      Targets:
        - Id: !GetAtt HelloFunction.Arn
      HealthCheckEnabled: true

  AlbListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref Alb
      Port: !Ref AlbListenerPort
      Protocol: HTTP
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref LambdaTargetGroup

Outputs:
  AlbDnsName:
    Description: "ALB DNS Name (use as test endpoint)"
    Value: !GetAtt Alb.DNSName

  AlbArn:
    Description: "ALB ARN (use for Global Accelerator stack)"
    Value: !Ref Alb

  TestUrlHello:
    Description: "Test URL"
    Value: !Sub "http://${Alb.DNSName}/"

Global Accelaratorを作成する

続いて、Global Accelaratorを作成していきます。
ユーザがGlobal AccelaratorのエンドポイントのDNS名にアクセスすると、AWS側で最適化されたルートでより高速なルーティングを自動で行ってくれるというサービスです。

構築は以下の4ステップで行います。

  • 名前/タイプの指定
  • リスナーの追加
  • エンドポイントグループの追加
  • エンドポイントの追加

1.名前/タイプの指定

アクセラレータの名前およびアクセラレータのタイプを指定します。
今回はユーザに最も近いALBに自動でルーティングの振り分けを行ってもらいたいため、標準を選択し、アドレスタイプはIPv4を選択します。

image.png

2.リスナーの追加

ポート及びプロトコルを指定します。
今回はHTTPでALBへアクセスするため、ポートは80-80、プロトコルはTCPを選択します。
クライアントアフィニティというのは一定時間同ユーザからのアクセスを同じエンドポイントに振り分ける設定のようです。
今回はなしとします。

image.png

3.エンドポイントグループの追加

続いて、エンドポイントグループでアクセラレータからのルーティング先のリージョン及びトラフィックの重みを指定します。
今回は東京(ap-northeast-1)とサンパウロ(sa-east-1)で2つのエンドポイントグループを作成します。
トラフィックダイアルは一旦100:100とし、デフォルトで最適化されたルーティングの様子を見てみます。

image.png

4.エンドポイントの作成

続いて、前項で作成したエンドポイントグループにルーティング先のエンドポイントを指定します。
ここでは、前提事項で作成したALBのDNS名を設定します。

クライアントのIPアドレスを保持については、ALBがクライアントのIPアドレスを識別できるようにする設定です。これをオンにするとALBのアクセスログ等に表示させることが出来るようです。する設定のことです。
今回はデフォルトで有効化したままとします。

image.png
image.png

ここまで出来たら、「エンドポイントを作成」ボタンを押してエンドポイントを作成します。
有効化されてステータスがデプロイ済みとなったら作成完了です。

image.png

実際にアクセスしてみる(From 日本)

まずは日本から普通にアクセスしてみます。
(エビデンスは後から撮りなおしたので重み付け後と時間が逆になってマス💦)

image.png

日本のALBにアクセス出来ましたね!
続いて、トラフィックダイアルを南米100、日本0にしてみます。

image.png

サンパウロのALBにアクセス出来ました!
image.png

続いて、実際のレイテンシの差も定量的に比較してみます。
以下のスクリプトで、10回アクセス時の中央値と平均値を取ります。

コードを表示する
# Geo-latancy-lab.ps1
# Measure avg and median (p50) for TTFB and TOTAL against multiple endpoints.
# Requires: curl.exe (Windows 10/11)

$Count = 30

$endpoints = @(
  "Tokyo ALB,http://xxxxxxx.ap-northeast-1.elb.amazonaws.com/"
  "SaoPaulo ALB,http://xxxxxxxxx.sa-east-1.elb.amazonaws.com/"
  "Global Accelerator,http://xxxxxxxxx.awsglobalaccelerator.com/"
)

function Get-Median {
    param([double[]]$Values)

    if (-not $Values -or $Values.Count -eq 0) { return [double]::NaN }

    $sorted = $Values | Sort-Object
    $n = $sorted.Count

    if ($n % 2 -eq 1) {
        return [double]$sorted[[int]($n / 2)]
    } else {
        $a = [double]$sorted[($n / 2) - 1]
        $b = [double]$sorted[$n / 2]
        return ($a + $b) / 2.0
    }
}

foreach ($item in $endpoints) {
    $parts = $item.Split(",", 2)
    $name = $parts[0].Trim()
    $url  = $parts[1].Trim()

    Write-Host ""
    Write-Host "===== $name ====="
    Write-Host "URL: $url"
    Write-Host "Requests: $Count"

    $ttfb = New-Object System.Collections.Generic.List[double]
    $total = New-Object System.Collections.Generic.List[double]

    for ($i = 1; $i -le $Count; $i++) {
        # curl output: "<ttfb> <total>\n"
        $result = curl.exe -s -o NUL -w "%{time_starttransfer} %{time_total}`n" $url

        if ([string]::IsNullOrWhiteSpace($result)) {
            Write-Warning "Empty curl output at attempt ${i}"
            continue
        }

        $vals = $result.Trim() -split "\s+"
        if ($vals.Count -lt 2) {
            Write-Warning "Unexpected curl output at attempt ${i}: $result"
            continue
        }

        $t1 = 0.0
        $t2 = 0.0
        if (-not [double]::TryParse($vals[0], [ref]$t1)) {
            Write-Warning "Failed to parse TTFB at attempt ${i}: $result"
            continue
        }
        if (-not [double]::TryParse($vals[1], [ref]$t2)) {
            Write-Warning "Failed to parse TOTAL at attempt ${i}: $result"
            continue
        }

        $ttfb.Add($t1)
        $total.Add($t2)
    }

    $nOk = $ttfb.Count
    if ($nOk -eq 0) {
        Write-Host "No successful measurements."
        continue
    }

    $avgTtfb  = ($ttfb  | Measure-Object -Average).Average
    $avgTotal = ($total | Measure-Object -Average).Average
    $p50Ttfb  = Get-Median -Values ($ttfb.ToArray())
    $p50Total = Get-Median -Values ($total.ToArray())

    Write-Host ("OK: {0}/{1}" -f $nOk, $Count)
    Write-Host ("TTFB  : avg={0:N3}s  p50={1:N3}s" -f $avgTtfb,  $p50Ttfb)
    Write-Host ("TOTAL : avg={0:N3}s  p50={1:N3}s" -f $avgTotal, $p50Total)
}

結果は以下の通り。
東京のALBに直アクセスしたときが一番早いですね。
(アクセラレータのエンドポイントを介さずに直でアクセスするから??)
アクセラレータとサンパウロへのアクセスを比較すると、圧倒的ンアクセラレータ経由の方が早いので、
東京のALBにルーティングされていることが分かります。

===== Tokyo ALB =====
URL: http://xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.116s  p50=0.108s
TOTAL : avg=0.212s  p50=0.214s

===== SaoPaulo ALB =====
URL: http://xxxxxxxxxxxxx.sa-east-1.elb.amazonaws.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.704s  p50=0.690s
TOTAL : avg=2.031s  p50=2.000s

===== Global Accelerator =====
URL: http://xxxxxxxxxxxxxxx.awsglobalaccelerator.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.158s  p50=0.159s
TOTAL : avg=0.257s  p50=0.214s

トラフィックダイアルの重みを日本0にしたらどうなるでしょうか。

===== Tokyo ALB =====
URL: http://xxxxxxxxxxxxxxxx.ap-northeast-1.elb.amazonaws.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.110s  p50=0.105s
TOTAL : avg=0.200s  p50=0.181s

===== SaoPaulo ALB =====
URL: http://xxxxxxxxxxxxxx.sa-east-1.elb.amazonaws.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.704s  p50=0.692s
TOTAL : avg=2.100s  p50=2.010s

===== Global Accelerator =====
URL: http://xxxxxxxxxxxx.awsglobalaccelerator.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.655s  p50=0.644s
TOTAL : avg=1.205s  p50=1.187s

アクセラレータ経由のアクセス時の時間が伸びて、サンパウロにアクセスしていることが分かります。
ですが、直接サンパウロのALBにアクセスするよりも断然早いですね。

実際にアクセスしてみる(From トリニダード・トバゴ)

では、実際に南米からも同じ検証をしてみます。
まずは普通にブラウザからアクセラレータのDNS名にアクセスしてみます。

image.png

南米のALBに飛ばされました!

レイテンシも見てみます。

PS C:\Takuto-work> powershell -ExecutionPolicy Bypass -File "C:\Takuto-work\Geo-latancy-lab.ps1"

===== Tokyo ALB =====
URL: http://xxxxxxxxxxxx.ap-northeast-1.elb.amazonaws.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.566s  p50=0.547s
TOTAL : avg=1.888s  p50=1.850s

===== SaoPaulo ALB =====
URL: http://xxxxxxxxxxxxxxxx.sa-east-1.elb.amazonaws.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.465s  p50=0.450s
TOTAL : avg=1.369s  p50=1.280s

===== Global Accelerator =====
URL: http://xxxxxxxxxxxxxxxxx.awsglobalaccelerator.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.521s  p50=0.504s
TOTAL : avg=0.878s  p50=0.810s

当然ですが、東京ALBへのアクセスが最も遅いですね
サンパウロのALBに直接アクセスした際の時間のほうがアクセラレータ経由でのアクセスに比べると遅くなっている点は東京と違います。(東京は直でALB叩いた方が早かった)
サンパウロとトリニダード・トバゴで若干距離があるからでしょうか。

重みをサンパウロ0にしてみます。

image.png

ブラウザからアクセスすると、当然東京のALBにルーティングされます。

PS C:\Takuto-work> powershell -ExecutionPolicy Bypass -File "C:\Takuto-work\Geo-latancy-lab.ps1"

===== Tokyo ALB =====
URL: http://xxxxxxxxxxxxxxxxx.ap-northeast-1.elb.amazonaws.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.624s  p50=0.574s
TOTAL : avg=3.618s  p50=4.126s

===== SaoPaulo ALB =====
URL: http://xxxxxxxxxxxxxxx.sa-east-1.elb.amazonaws.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.472s  p50=0.456s
TOTAL : avg=1.529s  p50=1.386s

===== Global Accelerator =====
URL: http://xxxxxxxxxxxxxxx.awsglobalaccelerator.com/
Requests: 30
OK: 30/30
TTFB  : avg=0.594s  p50=0.567s
TOTAL : avg=1.037s  p50=0.978s

レイテンシを比較すると、両ALBに直でアクセスするよりも、アクセラレータ経由でサンパウロにアクセスしたほうが早くなっていることが分かります。
Global Accelarator恐るべし、、

まとめ

本記事では、南米(サンパウロ)から日本リージョンを含む AWS 環境へアクセスし、
Global Accelerator がレイテンシ(特に TTFB)に与える影響を実際に検証しました。

東京 ALB / サンパウロ ALB / Global Accelerator を比較し、
AWS グローバルネットワーク経由の通信が、直接ALBにアクセスするよりも安定して低遅延になる傾向を確認しました。

Global Accelerator は、
グローバルユーザー向けにアクセス速度を改善したいケースで有効な選択肢だと肌で実感できました。

なにより、普段触れないサービスについて、こうやって旅先ならではの検証をしてみるのも面白いなと思った検証でした!

おわり

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?