"Netty in Action" Chinese version-fifth chapter BYTEBUF

Source: Internet
Author: User
Tags extend garbage collection memory usage readable shallow copy

http://ifeve.com/netty-in-action-5/


"Netty in Action" Chinese version-fifth chapter BYTEBUF

This article is translated from the fifth chapter of "Netty in action"

Author: Norman Maurer, Marvin Allen wolfthal translator: Peach Xiao Fat This chapter contains Bytebuf-netty Data Container API Details use case memory allocation

As we mentioned earlier, the base unit of the network data is always byte. Java NiO uses Bytebuffer to make its byte container, but this class is too complex and sometimes cumbersome.

Netty replaces Bytebuffer with BYTEBUF, a powerful implementation that breaks the limits of the JDK API and provides a better API for Web developers.

In this chapter we will show the excellent function and flexibility of bytebuf compared with Bytebuffer. This also gives you a better understanding of Netty data processing in general and prepares for the sixth chapter Channelpipeline and Channelhandler discussions.
5.1 bytebuf API

Netty uses two components to provide its data processing (data handling) service-abstract class Bytebuf and interface Bytebufholder.

Here are some of the advantages of the BYTEBUF API: Extensible user-defined buffer type a built-in composite buffer type enables transparent 0 copies to extend (process) capability according to requirements (similar to JDK StringBuilder) Read-write mode switching does not need to invoke Bytebuffer's Flip () method read and write using different index support method chains (methods chaining) support reference counting (reference counting) Support object Pooling (pooling)

There are other classes for managing the allocation of Bytebuf instances, and performing a series of operations on the data in containers and containers. We will study these features in detail when studying bytebuf and Bytebufholder. 5.2 Bytebuf Class--netty data container

Because all network traffic contains the movement of byte sequences, an efficient and easy-to-use data structure is clearly necessary. Netty's bytebuf meet or exceed these needs. Let's first take a look at the bytebuf if you use an index to simplify data access. How 5.2.1 Works

BYTEBUF contains two different indexes: one for reading and the other for writing. When you read data from a bytebuf, its readerindex increments by the number of bytes read. Similarly, when you write data to a bytebuf, its writerindex increments. Figure 5.1 is a layout and statechart diagram for an empty bytebuf.

Figure 5.1 A 16-byte bytebuf with an index of 0

To understand the relationship between the two indexes, consider a situation where you read bytes until Readerindex encounters Writerindex (that is, their values are equal). At that time, you have reached the end of the readable data. Trying to read the data triggers a indexoutofboundexception, just as you would if you were trying to access data outside the tail of an array.

A method that starts with read or write in the Bytebuf class increases its corresponding index value, whereas an operation that starts with a set or a get does not. These methods, which begin with set or get, operate on a relative index value (a relative value), which is passed into these methods as input parameters.

The maximum capacity of a bytebuf can be specified, and attempting to move the write index out of the range of the capacity value triggers an exception (the default limit is Integer.max_value). 5.2.2 bytebuf Usage mode

When you use Netty, you will find some bytebuf common usage patterns. As we learn more about them, it is helpful to remember that the graph 5.1--a byte array that controls reading and writing with different indexes. Heap Memory byte buffer (HEAP buffers)

The most commonly used BYTEBUF mode stores data in the JVM's heap space. This pattern, called a byte array (backing array), provides fast allocation and redistribution (functionality) without the use of object pooling. As shown in 5.1, this is a great way for you to process legacy data (Legacy).

Code Listing 5.1 byte array

Note: if HasArray () returns false, attempting to access a byte array (such as calling the array () method) triggers the unsupportedoperationexception. This pattern (HEAP buffers) is similar to the bytebuffer used by JDK. Immediate Memory byte buffer (direct buffers)

Direct buffer is another mode of bytebuf. We always expect the memory allocated to the object to be created from the heap, but it is not necessarily that--bytebuffer class and NiO were introduced to the JDK in version 1.4, allowing the JVM's implementation to allocate memory by local invocation (native calls). This is to avoid copying the contents of the buffer to a intermediate buffer (or copy from intermediate buffer to buffer) before the call to each local I/O operation (or later)

Bytebuffer's Javadoc is clear, "direct buffer content will be in the regular (can be) garbage collection outside the heap." This explains why direct buffer is a good fit for network data transfer. If your data is placed in a heap-allocated buffer, the JVM will actually copy your heap buffer to a direct buffer before being sent to the socket.

The main disadvantage of Direct buffer is that they are more expensive to allocate and release than heap buffer. If you're using legacy code, you may have another problem: because the data is not on the heap, you have to make a copy, as shown below.

Code Listings 5.2 Direct Buffer data access

Obviously, this is more cumbersome than using a byte array, so if you know beforehand that the data in the container is accessed through an array, you might be more inclined to use heap memory. Compound byte buffer (composite buffers)

The third and final pattern, using composite buffer, is a unified view of multiple BYTEBUF instances (an aggregated view of multiple Bytebufs). With this pattern, you can add or remove bytebuf instances on demand, a feature that JDK Bytebuffer does not have at all.

The Netty uses the Bytebuf subclass Compositebytebuf to implement this pattern, putting multiple buffer into a separate, fused buffer form.

warning : A bytebuf instance in a compositebytebuf may contain both direct and non-direct allocations, and if there is only one bytebuf instance, then the Compositebytebuf is raised with HasArray () returns the HasArray () value of that bytebuf, otherwise it returns false.

To illustrate the use of composite buffer, we assume that there is a message transmitted over HTTP that contains the header and the body two parts. These two parts are generated by different application modules and merged together when messages are sent. The application can choose to use the same body for more than one message. In this case, the application creates a new header for each message.

Because we don't want to allocate two buffer for each message, the COMPOSITEBYTEBUF is the best fit. It uses the generic BYTEBUF API while eliminating unnecessary copies. Figure 5.2 is the last generated message layout.

Figure 5.2 Compositebytebuf Store a header and a body

The following code illustrates how the Bytebuffer of JDK implements this requirement. An array containing two Bytebuffer is created with the header and body of the message stored, and the third bytebuffer is used to hold a copy of all the data.

Code Listing 5.3 Implementing composite buffer mode with Bytebuffer

Allocation and copy operations, as well as array management, make this version of the implementation look inefficient and awkward. The following code is implemented with COMPOSITEBYTEBUF.

Code Listing 5.4 Implementing composite buffer mode with COMPOSITEBYTEBUF

COMPOSITEBYTEBUF may not allow data to be fetched from a byte array, then fetching data from a COMPOSITEBYTEBUF is similar to direct buffer mode, as shown below.

code listing 5.5 accessing data from a compositebytebuf

Note that Netty optimizes socket I/O operations using COMPOSITEBYTEBUF, eliminating the cost of all possible JDK buffer performance and memory usage. This optimization is in Netty's internal core code, so it's not exposed through the API, but you should be aware of the effect of this optimization.

In addition to inheriting from BYTEBUF methods, the Compositebytebuf API provides a number of additional features for COMPOSITEBYTEBUF. Please refer to Netty Javadoc for a complete list of APIs. 5.3 byte-level operation

BYTEBUF provides a number of basic methods of reading and writing to modify its data. In the next few sections we'll discuss some of the most important of these methods. 5.3.1 Random Data Fetch index

Like an ordinary Java byte array, the BYTEBUF index starts at 0: The index of the first byte is 0, and the last one is always capacity ()-1. As you can see from the following code, the encapsulation of the storage mechanism makes the content of an iterative (iterate) bytebuf very simple.

Code Listing 5.6 getting the data

Note that the method used to obtain the data uses an index as an input parameter and does not change the value of Readerindex or Writerindex. If desired, their values can be manually modified by calling Readerindex (index) or Writerindex (index). 5.3.2 Continuous Data Fetch index

Bytebuf has both read and write indexing, but JDK bytebuffer only one, so you have to call the flip () method to switch between read and write mode. As can be seen from Figure 5.3, a bytebuf is divided into three areas by its two indexes.

Figure 5.3 Bytebuf internal Division

5.3.3 Disposable Bytes (discardable bytes)

The fragment marked as discardable byte in Figure 5.3 contains bytes that have already been read. by calling Discardreadbytes (), this part of the byte can be discarded, and this part of the space is reclaimed. The initial size of this fragment is 0, exists in Readerindex, and increases with the execution of read operations (the get operation does not move Readerindex).

Figure 5.4 Is the result of the discardreadbytes () increase in the buffer in Figure 5.3. As you can see, the discardable byte fragment space is now ready to be written. Note that after Discardreadbytes () is invoked, there is no guarantee that the contents of the writable fragment (those bytes that have been discarded)

Figure 5.4 Bytebuf after the read bytes are discarded

Although you may not be tempted to often invoke discardreadbytes () to maximize writable segmentation, note that doing so is likely to result in a memory copy, because the readable byte (the portion of the figure that is the content) is moved to the head of the buffer. We recommend that you call Discardreadbytes () only when you really need it, for example, when memory is a scarce product. 5.3.4 readable byte (readable bytes)

Bytebuf's readable byte fragment stores real data, a newly allocated, repackaged (wrapped), or just-copied buffer's Readerindex default value is 0. Any method that begins with read or skip reads or skips the data at the current Readerindex value, and then increases the Readerindex value by the number of bytes read.

If the input parameter of one of the calling methods includes a target bytebuf as a write object, and the input parameter has no target index (a destination index), The writerindex of the target buffer also increases (because the target buffer is written);

Readbytes (Bytebuf dest);

When trying to read from a buffer without readable bytes from reading the data, Indexoutofboundsexception throws.

This code shows how to read all the readable bytes.

Code Listing 5.7 reads all the data

5.3.5 (writable bytes)

A writable byte fragment is a piece of memory that contains undefined content to be written. The default value for the Writerindex of a newly allocated buffer is 0. Any action method that begins with write writes the data from the current writerindex, increasing the Writerindex value by the number of bytes written. If the source of the write operation is also a bytebuf and the index of the source buffer is not specified, then the readerindex of the source buffer increases the same value. This call looks like this:

Writebytes (Bytebuf dest);

Indexoutofboundsexception throws when the data is written to a target buffer, and its capacity is exceeded.

The following code is an example of filling a buffer with a random integer until the space is exhausted. The writable () method is used to determine if there is enough space in the buffer.

Code Listing 5.8 writing data

5.3.6 Index management

The JDK's InputStream defines the method mark (int readlimit) and reset (). The two methods are used to mark the current position of the stream as a specified value, or to reset the current stream to this specified position.

Similarly, you can set and reset Bytebuf by calling Markreaderindex (), Markwriterindex (), Resetreaderindex () and Resetwriterindex () Readerindex and Writerindex. These methods are similar to InputStream, except that they do not have readlimit parameters to specify when the tag will fail.

You can also move the index to the specified location by readerindex (int) or writerindex (int). An attempt to set an index to an invalid location can result in indexoutofboundexception.

You can also set Readerindex and Writerindex to 0 by calling Clear (). Note that this does not erase anything in memory. Figure 5.5 (as shown in Figure 5.3) illustrates how clear () works.

Figure 5.5 before calling clear ()

As seen before, the BYTEBUF consists of three segments. Figure 5.6 is the bytebuf after the clear () call.

Figure 5.6 After calling clear ()

Calling clear () is much less expensive than the discardreadbytes () because it simply resets the index and does not copy any memory. 5.3.7 Index Operation

There are several ways to get an index of a value in Bytebuf. The simplest use is the indexof () method. More complex search operations can be implemented by performing those methods with Bytebufprocessor as input parameters. Bytebufprocessor This interface defines a method that

Boolean process (byte value);

This method is used to report whether the input value is in the process of being searched.

Bytebufprocessor defines a number of convenient methods for common search values. Suppose your application needs to be integrated with the so-called Flash sockets, which contains null-terminated content. Call Buffer's

Foreachbyte (Bytebufprocessor.find_nul);

Flash data can be handled more easily and efficiently, because there are fewer bounds checks to perform during processing.

The following code is an example of a search return character (\ r).

Code Listing 5.9 with Bytebufprocessor to find \ r

5.3.8-derived buffer

A derived buffer renders the contents of the bytebuf in a particular way. Duplicate () slice () slice (int, int) unpooled.unmodifiablebuffer (...) Order (Byteorder) readslice (int)

Each method returns a new BYTEBUF instance that contains its own reader,writer and tag index. As with JDK Bytebuffer, the internal storage is shared with the source bytebuf. This makes the creation of the derived buffer less expensive, but it also means that if you change the content of the derived buffer, you are also changing the contents of the source buffer instance (instance), so be careful when you use it.

bytebuf Copying If you need a copy of the existing buffer, use copy () or copy (int, int). Unlike a derived buffer, these calls return bytebuf with a copy of the data that is independent (containing independent content and indexes).

The following code shows how to manipulate the bytebuf (slice) with slice (int, int)

Code Listing 5.10 splits a bytebuf

Now let's see what the difference is between the next Bytebuf segment (segment) Copy and the sub segment.

Code Listing 5.11 Copy a bytebuf

The two usages are similar, except that the effect of changing a paragraph or a copy of the original bytebuf is different. Whenever possible, try to use slice () to avoid the overhead of copying memory. 5.3.9 Read/write operations

As we have mentioned, there are two types of read/write operations: Get () and set () operations start with a specified index, do not change the value of the index read (), and the write () operation starts with a specified index and adjusts the index value with the read/write byte number

Table 5.1 lists the most commonly used get () methods. The Reference API documentation gets the complete list.

Table 5.1 get () Action

method name description
getboolean (int) return to the specified index location Boolean
getbyte (int) returns a byte value at the specified index position
getunsignedb Yte (int) returns an unsigned byte at the specified index (the return type is short)
getmedium (int) returns 24 bits at the specified index location (medium) value
getunsignedmedium (int) returns the unsigned 24-bit (medium) value of the specified index
getInt (int) returns the int value at the specified index
getunsignedint (int) returns the unsigned int value at the specified index position (the return type is long)
getlong (int) Returns a long value of the specified index position
getshort (int) returns the short value at the specified index position
getunsignedshort (int) returns the unsigned short value at the specified index position (the return type is int)
getBytes (int, ...) the destination at which the buffer data is transferred to the specified index location

These operations basically have a corresponding set () method. These methods are listed in Table 5.2

Table 5.2 Set () Action

Method name Describe
SetBoolean (int, Boolean) Set a Boolean value at the specified index position
SetByte (int index, int value) Set the byte value at the specified index position
Setmedium (int index, int value) Set 24-bit (medium) values at the specified index position
Setint (int index, int value) Sets the int value at the specified index position
Setlong (int index, Long value) Sets a long value at the specified index position
Setshort (int index, int value) Set the short value at the specified index position

The following code is used by the get () and set () methods to see that they do not change the read and write indexes.

use of code listing 5.12 get () and set ()

Now let's look at the read () action, which acts on the current Readerindex or Writeindex. The Read () method reads data from the BYTEBUF like a stream. Table 5.3 Lists the most commonly used methods.

Table 5.3 Read () Action

Method name Describe
Readboolean () Returns a Boolean value for the current readerindex position, then Readerindex plus 1
ReadByte () Returns the byte value of the current Readerindex position, then Readerindex plus 1
Readunsignedbyte () Returns the unsigned byte of the current Readerindex position (the return type is short), then Readerindex plus 1
Readmedium () Returns the 24-bit (medium) value of the current Readerindex position, then Readerindex plus 3
Readunsignedmedium () Returns the unsigned 24-bit (medium) value of the current Readerindex position, then Readerindex plus 3
ReadInt () Returns the int value for the current readerindex position, then Readerindex plus 4
Readunsignedint () Returns the unsigned int value of the current Readerindex position (the return type is long), then Readerindex plus 4
Readlong () Returns a Long value for the current readerindex position, then Readerindex Plus 8
Readshort () Returns the short value of the current Readerindex position, then Readerindex plus 2
Readunsignedshort () Returns the unsigned short value of the current Readerindex position (the return type is int), then Readerindex plus 2
Readbytes (Bytebuf | byte[)

Destination,

int Dstindex [, int length])

The current BYTEBUF data is routed to the target bytebuf or byte[, starting at the Readerindex position (length byte, if specified). The current Bytebuf Readerindex value grows based on the number of bytes transferred

Almost every read () method has a corresponding write () method that adds data to and from a bytebuf. Note that the input parameters for the methods listed in Table 5.4 are the values to be written to bytebuf, not the index values.

Table 5.4 Write () Action

Method name Describe
Writeboolean (Boolean) Writes a Boolean value at the current writerindex position, then Writerindex plus 1
WriteByte (int) Writes the byte value at the current Writerindex position, and then Writerindex plus 1
Writemedium (int) Writes the medium value at the current writerindex position, then Writerindex plus 3
Writeint (int) Writes an int value at the current writerindex position, then Writerindex plus 4
Writelong (Long) Writes a long value at the current writerindex position, then Writerindex Plus 8
Writeshort (int) Writes the short value at the current writerindex position, then Writerindex plus 2
Writebytes (Source Bytebuf |

Byte[] [, int srcindex

, int length])

Transfers data from the specified source Bytebuf or byte[to the current bytebuf, starting at the current writerindex position. If Srcindex and length are provided in the input parameter, the length bytes are read from the Srcindex. The current Bytebuf Writerindex value grows based on the number of bytes written.

Code 5.13 is an example of these methods.

the Read () and write () actions on the code listing 5.13 Bytebuf

5.3.10 More Operations

Table 5.5 lists some of the other useful practices that BYTEBUF provides.

table 5.5 Other useful actions

Method name Describe
IsReadable () Returns true if at least one byte size of data is readable
IsWritable () Returns true if at least one byte size of data is writable
Readablebytes () Returns the number of bytes that can be read
Writablebytes () Returns the number of bytes that can be written
Capacity () Returns the number of bytes Bytebuf can hold. After calling this method, Bytebuf tries to extend the capacity until it reaches maxcapacity ()
Maxcapacity () Returns the maximum number of bytes Bytebuf can hold
HasArray () Returns True if the Bytebuf has a byte array
Array () If Bytebuf has a byte array, returns the array;

Unsupportedoperationexception

5.4 Bytebufholder Interface

We often find that in addition to the data load, we also need to store a variety of data attributes. An HTTP response is a good example of a message body (content) in bytes, a status code, a cookie, and so on.

Netty provides bytebufholder to deal with such a common situation. Bytebufholder also provides support for some of the advanced features of Netty, such as a buffer pool, where a bytebuf can be removed from a pool and then automatically released when needed (back to the pool).

Bytebufholder only a few ways to get the underlying data and reference count. Table 5.6 Lists These methods (no methods are listed that inherit from referencecounted).

table 5.6 Bytebufholder Operations

Method name Describe
Content () Returns the Bytebuff data for Bytebufholder
Copy () Returns a deep copy of Bytebufholder (deep copy), including a separate (unshared) copy of the source BYTEBUF data
Duplicate () Returns a shallow copy of Bytebufholder (shallow copy), including a copy (shared) with the source BYTEBUF data share

If you want to implement a message object and store the message Payload (payload) in a bytebuf, then Bytebufholder is a good choice. 5.5 bytebuf Distribution

In this section we describe several ways to manage bytebuf instances. 5.5.1 On Demand: interface Bytebufallocator

To reduce the overhead of allocating and freeing memory, Netty uses interface Bytebufallocator to implement an object pool that can be used to allocate bytebuf instances of all the patterns we have mentioned. The use of object pooling is related to specific applications and does not affect the usage of the Bytebuf API.

Table 5.7 lists some of the actions of Bytebufallocator

Table 5.7 Bytebufallocator method

component

The based on the specified number of for socket I/O operations
Method name description
buffer ()

Buffer (int initialcapacity);

Buffer (int initialcapacity, int maxcapacity);

return heap or direct bytebuf
heapbuffer ()

Heapbuffer (int initialcapacity)

Heapbuffer (int initialcapacity, int

maxcapacity)

back heap bytebuf
directbuffer ()

Directbuffer (int initialcapacity

Directbuffer (int initialcapacity, int

maxcapacity)

return direct bytebuf
Compositebuffer ()

Compositebuffer (int maxnumcomponents);

Compositedirectbuffer ()

Compositedirectbuffer (int maxnumcomponents);

Compositeheapbuffer ()

Compositeheapbuffer (int maxnumcomponents);

returns COOMPOSITEBYTEBUF that can be extended heap or direct buffer

iobuffer () returns a bytebuf

You can get from a channel (each channel instance is different) or from a channelhandler bound channelhandlercontext

A reference to the Bytebufallocator. The following code illustrates both of these methods.

Code Listing 5.14 gets a bytebufallocator reference

Netty offers two implementations of Bytebufallocator: Poolbytebufallocator and Unpooledbytebufallocator. The former puts the bytebuf instance into the pool, improves performance, and minimizes memory fragmentation. This implementation employs an efficient strategy for allocating memory, called Jemalloc. It has been adopted by several modern operating systems. The latter does not put bytebuf into the pool, and each time it is invoked, a new BYTEBUF instance is returned.

Although Netty uses Poolbytebufallocator by default, changing the default settings is simple, as long as you specify a different allocator via the Channelconfig API or when you bootstrap the application. Please refer to chapter eighth for more details. 5.5.2 unpooled Buffers

Sometimes you can't get a reference to Bytebufallocator. In this case, Netty has a tool class called unpooled that provides some static helper methods (helper methods) to create unpooled bytebuf instances. Table 5.8 lists some of the most important of these methods.

Table 5.8 Unpooled method

Method name Describe
Buffer ()

Buffer (int initialcapacity)

Buffer (int initialcapacity, int maxcapacity)

Back to Heap Bytebuf
Directbuffer ()

Directbuffer (int initialcapacity)

Directbuffer (int initialcapacity, int

maxcapacity)

Back to direct BYTEBUF
Wrappedbuffer () Back to wrapped Bytebuf
Copiedbuffer () Back to copied Bytebuf

The Unpooled class lets bytebuf also apply to projects without network operations that do not require other netty components, which can benefit from this high-performance, extensible buffer API. 5.5. Class 3 Bytebufutil

Bytebufutil provides a number of static helper methods for manipulating bytebuf. Because this Bytebufutil API is generic and is not associated with the memory pool, these helper methods are implemented outside of the buffer class (the translator: visible from Bytebufutil Javadoc, it inherits from Object).

Perhaps the most valuable of these static methods is Hexdump (), which prints a bytebuf content in a hexadecimal string. This is useful in a variety of situations, such as recording bytebuf content for debugging purposes. A record log in hexadecimal is usually more useful than a direct byte representation. In addition, a hexadecimal-represented version can easily be converted back to the form of the original byte representation.

Another useful method is Boolean equals (Bytebuf, bytebuf), which is used to determine whether two bytebuf instances are equal. If you implement your own BYTEBUF subclass, you may also find some other useful bytebufutil methods. 5.6 Reference count (Reference counting)

Reference counting is a technique that optimizes memory usage and performance by releasing resources from objects that are no longer referenced by other objects. Netty introduced reference counts for Bytebu and Bytebufholderf in version fourth, both of which implement the Referencecounted interface.

The idea behind the reference count is not particularly complex; it is primarily involved in tracking the number of active references to a particular object. An instance of a referencecounted implementation is usually counted starting from 1. This object is guaranteed not to be freed as long as the reference count is greater than 0. When the active reference count is reduced to 0, the object is released. Note that while the exact meaning of the release varies depending on the implementation, at the very least, an object that has been freed cannot be used again.

Reference counting is critical to the implementation of object pooling, such as letting poolbytebufallocator reduce the overhead of allocating memory. Examples are in the following two paragraphs of code.

Code Listing 5.15 reference count

Code Listing 5.16 frees the object that contains the reference count

If an object containing a reference count has been disposed, an exception illegalreferencecountexception that references the bounds is thrown when an attempt is made to get the object.

Note that a class can define its own release-count rule. For example, we can imagine a class with a release () method that always sets the reference counter to 0, regardless of the current value, so that all active references are instantly invalidated.

who will be responsible for the release. Typically, the last code to get the object should be responsible for releasing it. In the sixth chapter, we will explain the relationship between this concept and Channelhandler and channelpipeline. 5.7 Summary

This chapter is devoted to the introduction of BYTEBUF based Netty data containers. We first explain some of the advantages of bytebuf over JDK Bytebuffer. We also highlighted several different patterns of APIs and pointed out which usage scenarios are best for them.

Here are some of the highlights of this chapter: read-write separated indexes to control data access different memory management policies-byte arrays and direct buffer represent multiple BYTEBUF Unified view composite buffer data access methods: Search, segmentation, and copy Read , Write,get and set APIs Bytebufallocator object pooling and reference counts

In the next chapter, we will focus on providing you with the channelhandler of the transmission medium for your data processing logic. Because Channelhandler uses bytebuf heavily, you will see that these important parts of the entire Netty structure will come together.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.