Enable multiple applications to share bandwidth (sample code)
Last Updated: Oct 30, 2020
This topic describes how to call the API with Alibaba Cloud SDK for Python to enable
multiple applications to share the bandwidth provided by an EIP bandwidth plan. This
reduces the costs of Internet data transfer.
Scenario
A company creates two Elastic Compute Service (ECS) instances and deploys an application
on each ECS instance. The ECS instances need to receive requests from the Internet.
The service port is port 80. The amount of bandwidth required by the two ECS instances
varies within a day:
The peak hours of ECS 1 range from 13:00:00 to 18:00:00. During this period of time,
the bandwidth required is 1,000 Mbit/s. During the remaining hours of the day, the
bandwidth required is 500 Mbit/s.
The peak hours of ECS 2 range from 19:00:00 to 23:00:00. During this period of time,
the bandwidth required is 1,000 Mbit/s. During the remaining hours of the day, the
bandwidth required is 500 Mbit/s.
If you want to purchase bandwidth for the ECS instances separately, you must purchase
two bandwidth plans with a total bandwidth of 2,000 Mbit/s. However, the ECS instances
cannot make full use of the bandwidth during off-peak hours. This causes bandwidth
resource wastes.
To resolve this problem, you can configure Destination Network Address Translation
(DNAT) for your NAT gateway and purchase EIP bandwidth plans.
DNAT maps elastic IP addresses (EIPs) to ECS instances in a virtual private cloud
(VPC). Then, the ECS instances can receive requests from the Internet.
An EIP bandwidth plan can be shared among multiple applications to reduce the costs
of Internet data transfer.
Prerequisites
Before you start, make sure that the following requirements are met:
An Alibaba Cloud account is created. If you do not have an Alibaba Cloud account,create an Alibaba account.
An AccessKey pair is created. If you do not have an AccessKey pair, go to the Security Management page and create an AccessKey pair.
A Python development environment is prepared and Alibaba Cloud SDK for Python is installed.
For more information, see Installation.
A virtual private cloud (VPC) and a VSwitch are created. For more information, see
CreateVpc.
Elastic Compute Service (ECS) instances are created and attached to the VSwitch. Applications
are deployed on the ECS instances. For more information, see CreateInstance.
Two elastic IP addresses (EIPs) are created for the NAT gateway. The EIPs must meet
the following requirements:
The EIPs and the NAT gateway to be associated with the EIPs must be in the same region.
NAT gateways are enterprise-class gateways that provide network address translation
services for Internet access. You must create a NAT gateway before you can create
DNAT entries.
Note When you create an enhanced NAT gateway, you must specify the VSwitch to which the
NAT gateway is attached. The system automatically assigns an unused private IP address
from the VSwitch to the enhanced NAT gateway.
If you want to create an enhanced NAT gateway and attach it to an existing VSwitch,
make sure that the VSwitch has unused IP addresses and the zone where the VSwitch
is deployed allows you to create enhance NAT gateways.
If no VSwitch is available, create a VSwitch in one of the zones that support enhanced
NAT gateways. Then, attach the enhanced NAT gateway to the VSwitch.
The following sample code shows how to create a NAT gateway:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkvpc.request.v20160428.CreateNatGatewayRequest import CreateNatGatewayRequest
# Create an AcsClient instance.
# yourAccessKeyId: your AccessKey ID.
# yourAccessKeySecret: your AccessKey secret.
# yourRegionId: the region ID.
client = AcsClient("yourAccessKeyId","yourAccessKeySecret","yourRegionId")
# Create a NAT gateway.
request = CreateNatGatewayRequest()
request.set_accept_format('json')
# The ID of the VPC where the NAT gateway is deployed.
request.set_VpcId("vpc-uf68wppzf839896z7****")
# The name of the NAT gateway.
request.set_Name("test")
# The description of the NAT gateway.
request.set_Description("test")
# The size of the NAT gateway.
# Valid values: Small (default), Middle, Large, and XLarge.1. The parameter is set to Small in this example. Set the parameter based on your business requirements.
request.set_Spec("Small")
# The billing method of the NAT gateway.
# Valid values: PostPaid (pay-as-you-go) and PrePaid (subscription). The default value is PostPaid.
request.set_InstanceChargeType("PrePaid")
# The billing cycle of subscriptions.
# Valid values: Month (default) and Year.
# This parameter is required when InstanceChargeType is set to PrePaid. You do not need to set this parameter when InstanceChargeType is set to PostPaid.
request.set_PricingCycle("Month")
# The subscription duration.
# When PricingCycle is set to Month, Period can be set from 1 to 9. When PricingCycle is set to Year, Period can be set from 1 to 3.
request.set_Duration("1")
# Automatic payment.
# Valid values: false and true. false: disables automatic payment. After an order is generated, you must go to the Order Center to complete the payment. true: enables automatic payment. Payments are automatically completed.
request.set_AutoPay(True)
# The ID of the VSwitch to which the NAT gateway is attached.
When you create an enhanced NAT gateway, you must specify the VSwitch to which the NAT gateway is attached. The system automatically assigns an unused private IP address from the VSwitch to the enhanced NAT gateway.
request.set_VSwitchId("vsw-uf6gnat6e5tk0gnbm****")
# The type of the NAT gateway.
# Valid values: Normal (standard NAT gateways) and Enhanced (enhanced NAT gateways).
# Enhanced NAT gateways are upgraded from the technical architecture of standard NAT gateways. Enhanced NAT gateways offer higher elasticity and stability, and enable you to better manage data transfer over the Internet.
request.set_NatType("Enhanced")
# The metering method of the NAT gateway.
# Valid values: PayBySpec (pay-by-specification) and PayByLcu (pay-by-LCU).
request.set_InternetChargeType("PayBySpec")
# Call the API and print the response.
response = client.do_action_with_exception(request)
# python2: print(response)
print(str(response, encoding='utf-8'))
The following sample code shows how to query details about the NAT gateway:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkvpc.request.v20160428.DescribeNatGatewaysRequest import DescribeNatGatewaysRequest
# Create an AcsClient instance.
# yourAccessKeyId: your AccessKey ID.
# yourAccessKeySecret: your AccessKey secret.
# yourRegionId: the region ID.
client = AcsClient("yourAccessKeyId","yourAccessKeySecret","yourRegionId")
# Query details about the NAT gateway.
request = DescribeNatGatewaysRequest()
request.set_accept_format('json')
# The ID of the NAT gateway that you want to query.
request.set_NatGatewayId("ngw-uf6htj15rgyp8ivix****")
# Call the API and print the response.
response = client.do_action_with_exception(request)
# python2: print(response)
print(str(response, encoding='utf-8'))
A NAT gateway functions as expected only after it is associated with one or more EIPs.
The following sample code shows how to associate EIPs with the NAT gateway:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkvpc.request.v20160428.AssociateEipAddressRequest import AssociateEipAddressRequest
# The IDs of the EIPs that you want to associate with the NAT gateway. This parameter is set to the IDs of EIP 1 and EIP 2 in this example.
allocationIds = ["eip-uf6pvlaprugu1azc8****", "eip-uf69ls0f3qgv0alk6****"]
# Create an AcsClient instance.
# yourAccessKeyId: your AccessKey ID.
# yourAccessKeySecret: your AccessKey secret.
# yourRegionId: the region ID.
client = AcsClient("yourAccessKeyId","yourAccessKeySecret","yourRegionId")
# Associate the EIPs with the NAT gateway.
for i in range(0, 2):
request = AssociateEipAddressRequest()
request.set_accept_format('json')
# The ID of the NAT gateway.
request.set_InstanceId("ngw-uf6htj15rgyp8ivix****")
# The IDs of the EIPs.
request.set_AllocationId(allocationIds[i])
# The type of the resource to be associated with the EIPs.
request.set_InstanceType("NAT")
# Call the API and print the response.
response = client.do_action_with_exception(request)
# python2: print(response)
print(str(response, encoding='utf-8'))
A DNAT entry maps the EIP of a NAT gateway to an ECS instance so that the ECS instance
can receive requests from the Internet. The following table shows the DNAT entries
for ECS 1 and ECS 2.
Entry name
EIP
External port
Protocol
Private IP address
Internal port
DNAT1
EIP1
80
TCP
ECS1
80
DNAT2
EIP2
80
TCP
ECS2
80
The following sample code shows how to create a DNAT entry for ECS 1:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkvpc.request.v20160428.CreateForwardEntryRequest import CreateForwardEntryRequest
# Create an AcsClient instance.
# yourAccessKeyId: your AccessKey ID.
# yourAccessKeySecret: your AccessKey secret.
# yourRegionId: the region ID.
client = AcsClient("yourAccessKeyId","yourAccessKeySecret","yourRegionId")
# Create a DNAT entry.
request = CreateForwardEntryRequest()
request.set_accept_format('json')
# The ID of the DNAT table in which you want to create the DNAT entry.
request.set_ForwardTableId("ftb-uf6hdobgppflyr2ng****")
# Specify the EIP for Internet access. This parameter is set to the IP address of EIP 1 in this example.
request.set_ExternalIp("101.xx.xx.137")
# The external port where requests from the Internet are received. Valid values: 1 to 65535. This parameter is set to 80 in this example.
request.set_ExternalPort("80")
# Specify the private IP address of the ECS instance that needs to receive requests from the Internet. This parameter is set to the private IP address of ECS 1.
request.set_InternalIp("192.xx.xx.100")
# The internal port to which the requests received on the external port are forwarded. Valid values: 1 to 65535. This parameter is set to 80 in this example.
request.set_InternalPort("80")
# The protocol used by the external and internal ports.
# Valid values: TCP, UDP, and Any. TCP: forwards TCP packets. UDP: forwards UDP packets. Any: forwards all packets.
request.set_IpProtocol("TCP")
# The name of the DNAT entry. The name is set to DNAT 1 in this example.
request.set_ForwardEntryName("DNAT1")
# Call the API and print the response.
response = client.do_action_with_exception(request)
# python2: print(response)
print(str(response, encoding='utf-8'))
The following sample code shows how to create a DNAT entry for ECS 2:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkvpc.request.v20160428.CreateForwardEntryRequest import CreateForwardEntryRequest
# Create an AcsClient instance.
# yourAccessKeyId: your AccessKey ID.
# yourAccessKeySecret: your AccessKey secret.
# yourRegionId: the region ID.
client = AcsClient("yourAccessKeyId","yourAccessKeySecret","yourRegionId")
# Create a DNAT entry.
request = CreateForwardEntryRequest()
request.set_accept_format('json')
# The ID of the DNAT table in which you want to create the DNAT entry.
request.set_ForwardTableId("ftb-uf6hdobgppflyr2ng****")
# Specify the EIP for Internet access. This parameter is set to the IP address of EIP 2 in this example.
request.set_ExternalIp("106.xx.xx.94")
# The external port where requests from the Internet are received. Valid values: 1 to 65535. This parameter is set to 80 in this example.
request.set_ExternalPort("80")
# Specify the private IP address of the ECS instance that needs to receive requests from the Internet. This parameter is set to the private IP address of ECS 2.
request.set_InternalIp("192.xx.xx.101")
# The internal port to which the requests received on the external port are forwarded. Valid values: 1 to 65535. This parameter is set to 80 in this example.
request.set_InternalPort("80")
# The protocol used by the external and internal ports.
# Valid values: TCP, UDP, and Any. TCP: forwards TCP packets. UDP: forwards UDP packets. Any: forwards all packets.
request.set_IpProtocol("TCP")
# The name of the DNAT entry. The name is set to DNAT 2 in this example.
request.set_ForwardEntryName("DNAT2")
# Call the API and print the response.
response = client.do_action_with_exception(request)
# python2: print(response)
print(str(response, encoding='utf-8'))
EIP bandwidth plans support regional bandwidth sharing and transfer. You can use EIP
bandwidth plans to reduce bandwidth usage costs.
The following sample code shows how to create an EIP bandwidth plan:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkvpc.request.v20160428.CreateCommonBandwidthPackageRequest import CreateCommonBandwidthPackageRequest
# Create an AcsClient instance.
# yourAccessKeyId: your AccessKey ID.
# yourAccessKeySecret: your AccessKey secret.
# yourRegionId: the region ID.
client = AcsClient("yourAccessKeyId","yourAccessKeySecret","yourRegionId")
# Create an EIP bandwidth plan.
request = CreateCommonBandwidthPackageRequest()
request.set_accept_format('json')
# Specify the maximum bandwidth of the EIP bandwidth plan. Valid values: 1,000 to 5,000. Unit: Mbit/s. This parameter is set to 1500 in this example. You can set the parameter based on your business requirements.
request.set_Bandwidth(1500)
# The connection type.
# Valid values: BGP and BGP_PRO. BGP represents BGP (Multi-ISP) and BGP_PRO represents BGP (Multi-ISP) Premium.
request.set_ISP("BGP")
# The name of the EIP bandwidth plan.
request.set_Name("test")
# The description of the EIP bandwidth plan.
request.set_Description("test")
# The billing method of the EIP bandwidth plan.
# Valid values: PayByBandwidth (default) and PayBy95. PayByBandwidth: The EIP bandwidth plan is charged based on bandwidth usage. PayBy95: The EIP bandwidth plan is charged based on the enhanced 95th percentile bandwidth.
request.set_InternetChargeType("PayByBandwidth")
# Call the API and print the response.
response = client.do_action_with_exception(request)
# python2: print(response)
print(str(response, encoding='utf-8'))
Step 5: Associate EIPs with the EIP bandwidth plan
You can associate EIP 1 and EIP 2 with the created EIP bandwidth plan. After the EIPs
are associated with the EIP bandwidth plan:
Services attached to the NAT gateway that is associated with the EIPs share the bandwidth
of the EIP bandwidth plan.
The predefined maximum bandwidths of the EIPs become invalid. The maximum bandwidths
of the EIPs equal the maximum bandwidth of the associated EIP bandwidth plan.
The predefined billing methods of the EIPs become invalid. The EIPs function as public
IP addresses. Data transfer and bandwidth usage are not charged for the EIPs.
The following sample code shows how to associate EIP 1 and EIP 2 with the EIP bandwidth
plan:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkvpc.request.v20160428.AddCommonBandwidthPackageIpRequest import AddCommonBandwidthPackageIpRequest
# Specify the EIPs that you want to associate with the EIP bandwidth plan. This parameter is set to EIP 1 and EIP 2 in this example.
IpInstanceIds = ["eip-uf6pvlaprugu1azc8****","eip-uf69ls0f3qgv0alk6****"]
# Create an AcsClient instance.
# yourAccessKeyId: your AccessKey ID.
# yourAccessKeySecret: your AccessKey secret.
# yourRegionId: the region ID.
client = AcsClient("yourAccessKeyId","yourAccessKeySecret","yourRegionId")
for i in range(0, 2):
# Associate the EIPs with the EIP bandwidth plan.
request = AddCommonBandwidthPackageIpRequest()
request.set_accept_format('json')
# The ID of the EIP bandwidth plan.
request.set_BandwidthPackageId("cbwp-uf6jvfp1wqps1vywa****")
# The EIPs to be associated with the EIP bandwidth plan.
request.set_IpInstanceId(IpInstanceIds[i])
# Call the API and print the response.
response = client.do_action_with_exception(request)
# python2: print(response)
print(str(response, encoding='utf-8'))
You can verify the network connectivity by using a computer to access the applications
deployed on ECS 1 and ECS 2.
Note Make sure that the security group rules of the ECS instances allow the ECS instances
to receive requests from the Internet.
Open a browser.
Enter one of the EIPs that are associated with the NAT gateway to access the application
running on an ECS instances.
The test results indicate that you can access the applications deployed on ECS 1 and
ECS 2 over the Internet. It also shows that the ECS instances share the bandwidth
of the EIP bandwidth plan and can handle traffic spikes.
Figure 1. Access the application running on ECS 1
Figure 2. Access the application running on ECS 2