前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Flink异步之矛-锋利的Async I/O

Flink异步之矛-锋利的Async I/O

作者头像
大数据真好玩
发布于 2020-02-11 09:51:24
发布于 2020-02-11 09:51:24
1.3K00
代码可运行
举报
文章被收录于专栏:暴走大数据暴走大数据
运行总次数:0
代码可运行

维表JOIN-绕不过去的业务场景

在Flink 流处理过程中,经常需要和外部系统进行交互,用维度表补全事实表中的字段。

例如:在电商场景中,需要一个商品的skuid去关联商品的一些属性,例如商品所属行业、商品的生产厂家、生产厂家的一些情况;在物流场景中,知道包裹id,需要去关联包裹的行业属性、发货信息、收货信息等等。

默认情况下,在Flink的MapFunction中,单个并行只能用同步方式去交互: 将请求发送到外部存储,IO阻塞,等待请求返回,然后继续发送下一个请求。这种同步交互的方式往往在网络等待上就耗费了大量时间。为了提高处理效率,可以增加MapFunction的并行度,但增加并行度就意味着更多的资源,并不是一种非常好的解决方式。

Async I/O异步非阻塞请求

Flink 在1.2中引入了Async I/O,在异步模式下,将IO操作异步化,单个并行可以连续发送多个请求,哪个请求先返回就先处理,从而在连续的请求间不需要阻塞式等待,大大提高了流处理效率。

Async I/O 是阿里巴巴贡献给社区的一个呼声非常高的特性,解决与外部系统交互时网络延迟成为了系统瓶颈的问题。

图中棕色的长条表示等待时间,可以发现网络等待时间极大地阻碍了吞吐和延迟。为了解决同步访问的问题,异步模式可以并发地处理多个请求和回复。也就是说,你可以连续地向数据库发送用户a、b、c等的请求,与此同时,哪个请求的回复先返回了就处理哪个回复,从而连续的请求之间不需要阻塞等待,如上图右边所示。这也正是 Async I/O 的实现原理。

详细的原理可以参考文末给出的第一个链接,来自阿里巴巴云邪的分享。

一个简单的例子如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public classAsyncIOFunctionTest{
    public static void main(String[] args) throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        env.setParallelism(1);

        Properties p = new Properties();
        p.setProperty("bootstrap.servers", "localhost:9092");

        DataStreamSource<String> ds = env.addSource(new FlinkKafkaConsumer010<String>("order", new SimpleStringSchema(), p));
        ds.print();

        SingleOutputStreamOperator<Order> order = ds
                .map(new MapFunction<String, Order>() {
                    @Override
                    public Order map(String value) throws Exception {
                        return new Gson().fromJson(value, Order.class);
                    }
                })
                .assignTimestampsAndWatermarks(new AscendingTimestampExtractor<Order>() {
                    @Override
                    public long extractAscendingTimestamp(Order element) {
                        try {
                            return element.getOrderTime();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return 0;
                    }
                })
                .keyBy(new KeySelector<Order, String>() {
                    @Override
                    public String getKey(Order value) throws Exception {
                        return value.getUserId();
                    }
                })
                .window(TumblingEventTimeWindows.of(Time.minutes(10)))
                .maxBy("orderTime");

        SingleOutputStreamOperator<Tuple7<String, String, Integer, String, String, String, Long>> operator = AsyncDataStream
                .unorderedWait(order, new RichAsyncFunction<Order, Tuple7<String, String, Integer, String, String, String, Long>>() {

                    private Connection connection;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        super.open(parameters);
                        Class.forName("com.mysql.jdbc.Driver");
                        connection = DriverManager.getConnection("url", "user", "pwd");
                        connection.setAutoCommit(false);
                    }

                    @Override
                    public void asyncInvoke(Order input, ResultFuture<Tuple7<String, String, Integer, String, String, String, Long>> resultFuture) throws Exception {
                        List<Tuple7<String, String, Integer, String, String, String, Long>> list = new ArrayList<>();
                        // 在 asyncInvoke 方法中异步查询数据库
                        String userId = input.getUserId();
                        Statement statement = connection.createStatement();
                        ResultSet resultSet = statement.executeQuery("select name,age,sex from user where userid=" + userId);
                        if (resultSet != null && resultSet.next()) {
                            String name = resultSet.getString("name");
                            int age = resultSet.getInt("age");
                            String sex = resultSet.getString("sex");
                            Tuple7<String, String, Integer, String, String, String, Long> res = Tuple7.of(userId, name, age, sex, input.getOrderId(), input.getPrice(), input.getOrderTime());
                            list.add(res);
                        }

                        // 将数据搜集
                        resultFuture.complete(list);
                    }

                    @Override
                    public void close() throws Exception {
                        super.close();
                        if (connection != null) {
                            connection.close();
                        }
                    }
                }, 5000, TimeUnit.MILLISECONDS,100);

        operator.print();


        env.execute("AsyncIOFunctionTest");
    }
}

上述代码中,原始订单流来自Kafka,去关联维度表将订单的用户信息取出来。从上面示例中可看到,我们在open()中创建连接对象,在close()方法中关闭连接,在RichAsyncFunction的asyncInvoke()方法中,直接查询数据库操作,并将数据返回出去。这样一个简单异步请求就完成了。

Async I/O的原理和基本用法

简单的来说,使用 Async I/O 对应到 Flink 的 API 就是 RichAsyncFunction 这个抽象类,继层这个抽象类实现里面的open(初始化),asyncInvoke(数据异步调用),close(停止的一些操作)方法,最主要的是实现asyncInvoke 里面的方法。

我们先来看一个使用Async I/O的模板方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

// This example implements the asynchronous request and callback with Futures that have the
// interface of Java 8's futures (which is the same one followed by Flink's Future)

/**
 * An implementation of the 'AsyncFunction' that sends requests and sets the callback.
 */
classAsyncDatabaseRequestextendsRichAsyncFunction<String, Tuple2<String, String>> {

    /** The database specific client that can issue concurrent requests with callbacks */
    private transient DatabaseClient client;

    @Override
    publicvoidopen(Configuration parameters) throws Exception {
        client = new DatabaseClient(host, post, credentials);
    }

    @Override
    publicvoidclose() throws Exception {
        client.close();
    }

    @Override
    publicvoidasyncInvoke(String key, final ResultFuture<Tuple2<String, String>> resultFuture) throws Exception {

        // issue the asynchronous request, receive a future for result
        final Future<String> result = client.query(key);

        // set the callback to be executed once the request by the client is complete
        // the callback simply forwards the result to the result future
        CompletableFuture.supplyAsync(new Supplier<String>() {

            @Override
            public String get() {
                try {
                    return result.get();
                } catch (InterruptedException | ExecutionException e) {
                    // Normally handled explicitly.
                    return null;
                }
            }
        }).thenAccept( (String dbResult) -> {
            resultFuture.complete(Collections.singleton(new Tuple2<>(key, dbResult)));
        });
    }
}

// create the original stream
DataStream<String> stream = ...;

// apply the async I/O transformation
DataStream<Tuple2<String, String>> resultStream =
    AsyncDataStream.unorderedWait(stream, new AsyncDatabaseRequest(), 1000, TimeUnit.MILLISECONDS, 100);

假设我们一个场景是需要进行异步请求其他数据库,那么要实现一个通过异步I/O来操作数据库还需要三个步骤:   

1、实现用来分发请求的AsyncFunction   

2、获取操作结果的callback,并将它提交到AsyncCollector中   

3、将异步I/O操作转换成DataStream

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
其中的两个重要的参数:Timeouttimeout 定义了异步操作过了多长时间后会被丢弃,这个参数是防止了死的或者失败的请求 Capacity 这个参数定义了可以同时处理多少个异步请求。虽然异步I/O方法会带来更好的吞吐量,但是算子仍然会成为流应用的瓶颈。超过限制的并发请求数量会产生背压。

几个需要注意的点:

  • 使用Async I/O,需要外部存储有支持异步请求的客户端。
  • 使用Async I/O,继承RichAsyncFunction(接口AsyncFunction的抽象类),重写或实现open(建立连接)、close(关闭连接)、asyncInvoke(异步调用)3个方法即可。
  • 使用Async I/O, 最好结合缓存一起使用,可减少请求外部存储的次数,提高效率。
  • Async I/O 提供了Timeout参数来控制请求最长等待时间。默认,异步I/O请求超时时,会引发异常并重启或停止作业。如果要处理超时,可以重写AsyncFunction#timeout方法。
  • Async I/O 提供了Capacity参数控制请求并发数,一旦Capacity被耗尽,会触发反压机制来抑制上游数据的摄入。
  • Async I/O 输出提供乱序和顺序两种模式。 乱序, 用AsyncDataStream.unorderedWait(...) API,每个并行的输出顺序和输入顺序可能不一致。 顺序, 用AsyncDataStream.orderedWait(...) API,每个并行的输出顺序和输入顺序一致。为保证顺序,需要在输出的Buffer中排序,该方式效率会低一些。

Flink 1.9 中的优化

由于新合入的 Blink 相关功能,使得 Flink 1.9 实现维表功能很简单。如果你要使用该功能,那就需要自己引入 Blink 的 Planner。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-planner-blink_${scala.binary.version}</artifactId>
    <version>${flink.version}</version>
</dependency>

然后我们只要自定义实现 LookupableTableSource 接口,同时实现里面的方法就可以进行,下面来分析一下 LookupableTableSource的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interfaceLookupableTableSource<T> extendsTableSource<T> {
     TableFunction<T> getLookupFunction(String[] lookupKeys);
     AsyncTableFunction<T> getAsyncLookupFunction(String[] lookupKeys);
     booleanisAsyncEnabled();
}

这三个方法分别是:

  • isAsyncEnabled 方法主要表示该表是否支持异步访问外部数据源获取数据,当返回 true 时,那么在注册到 TableEnvironment 后,使用时会返回异步函数进行调用,当返回 false 时,则使同步访问函数。
  • getLookupFunction 方法返回一个同步访问外部数据系统的函数,什么意思呢,就是你通过 Key 去查询外部数据库,需要等到返回数据后才继续处理数据,这会对系统处理的吞吐率有影响。
  • getAsyncLookupFunction 方法则是返回一个异步的函数,异步访问外部数据系统,获取数据,这能极大的提升系统吞吐率。

我们抛开同步访问函数不管。对于getAsyncLookupFunction会返回异步访问外部数据源的函数,如果你想使用异步函数,前提是 LookupableTableSource 的 isAsyncEnabled 方法返回 true 才能使用。使用异步函数访问外部数据系统,一般是外部系统有异步访问客户端,如果没有的话,可以自己使用线程池异步访问外部系统。例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public classMyAsyncLookupFunctionextendsAsyncTableFunction<Row> {
    private transient RedisAsyncCommands<String, String> async;
    @Override
    publicvoidopen(FunctionContext context) throws Exception {
        RedisClient redisClient = RedisClient.create("redis://127.0.0.1:6379");
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        async = connection.async();
    }
    publicvoideval(CompletableFuture<Collection<Row>> future, Object... params) {
        redisFuture.thenAccept(new Consumer<String>() {
            @Override
            publicvoidaccept(String value) {
                future.complete(Collections.singletonList(Row.of(key, value)));
            }
        });
    }
}

一个完整的例子如下:

Main方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.typeutils.RowTypeInfo;
import org.apache.flink.api.java.utils.ParameterTool;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer011;
import org.apache.flink.table.api.EnvironmentSettings;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.java.StreamTableEnvironment;
import org.apache.flink.types.Row;
import org.junit.Test;

import java.util.Properties;

public classLookUpAsyncTest{

    @Test
    public void test() throws Exception {
        LookUpAsyncTest.main(new String[]{});
    }

    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //env.setParallelism(1);
        EnvironmentSettings settings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build();
        StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env, settings);

        final ParameterTool params = ParameterTool.fromArgs(args);
        String fileName = params.get("f");
        DataStream<String> source = env.readTextFile("hdfs://172.16.44.28:8020" + fileName, "UTF-8");

        TypeInformation[] types = new TypeInformation[]{Types.STRING, Types.STRING, Types.LONG};
        String[] fields = new String[]{"id", "user_click", "time"};
        RowTypeInfo typeInformation = new RowTypeInfo(types, fields);

        DataStream<Row> stream = source.map(new MapFunction<String, Row>() {
            private static final long serialVersionUID = 2349572543469673349L;

            @Override
            public Row map(String s) {
                String[] split = s.split(",");
                Row row = new Row(split.length);
                for (int i = 0; i < split.length; i++) {

                    Object value = split[i];
                    if (types[i].equals(Types.STRING)) {
                        value = split[i];
                    }
                    if (types[i].equals(Types.LONG)) {
                        value = Long.valueOf(split[i]);
                    }
                    row.setField(i, value);
                }
                return row;
            }
        }).returns(typeInformation);

        tableEnv.registerDataStream("user_click_name", stream, String.join(",", typeInformation.getFieldNames()) + ",proctime.proctime");

        RedisAsyncLookupTableSource tableSource = RedisAsyncLookupTableSource.Builder.newBuilder()
                .withFieldNames(new String[]{"id", "name"})
                .withFieldTypes(new TypeInformation[]{Types.STRING, Types.STRING})
                .build();
        tableEnv.registerTableSource("info", tableSource);

        String sql = "select t1.id,t1.user_click,t2.name" +
                " from user_click_name as t1" +
                " join info FOR SYSTEM_TIME AS OF t1.proctime as t2" +
                " on t1.id = t2.id";

        Table table = tableEnv.sqlQuery(sql);

        DataStream<Row> result = tableEnv.toAppendStream(table, Row.class);

        DataStream<String> printStream = result.map(new MapFunction<Row, String>() {
            @Override
            public String map(Row value) throws Exception {
                return value.toString();
            }
        });

        Properties properties = new Properties();
        properties.setProperty("bootstrap.servers", "127.0.0.1:9094");
        FlinkKafkaProducer011<String> kafkaProducer = new FlinkKafkaProducer011<>(
                "user_click_name",
                new SimpleStringSchema(),
                properties);
        printStream.addSink(kafkaProducer);

        tableEnv.execute(Thread.currentThread().getStackTrace()[1].getClassName());
    }
}

RedisAsyncLookupTableSource方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.typeutils.RowTypeInfo;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.api.TableSchema;
import org.apache.flink.table.functions.AsyncTableFunction;
import org.apache.flink.table.functions.TableFunction;
import org.apache.flink.table.sources.LookupableTableSource;
import org.apache.flink.table.sources.StreamTableSource;
import org.apache.flink.table.types.DataType;
import org.apache.flink.table.types.utils.TypeConversions;
import org.apache.flink.types.Row;

public classRedisAsyncLookupTableSourceimplementsStreamTableSource<Row>, LookupableTableSource<Row> {

    private final String[] fieldNames;
    private final TypeInformation[] fieldTypes;

    publicRedisAsyncLookupTableSource(String[] fieldNames, TypeInformation[] fieldTypes) {
       this.fieldNames = fieldNames;
        this.fieldTypes = fieldTypes;
    }

    //同步方法
    @Override
    public TableFunction<Row> getLookupFunction(String[] strings) {
        return null;
    }

    //异步方法
    @Override
    public AsyncTableFunction<Row> getAsyncLookupFunction(String[] strings) {
        return MyAsyncLookupFunction.Builder.getBuilder()
                .withFieldNames(fieldNames)
                .withFieldTypes(fieldTypes)
                .build();
    }

    //开启异步
    @Override
    publicbooleanisAsyncEnabled() {
        return true;
    }

    @Override
    public DataType getProducedDataType() {
        return TypeConversions.fromLegacyInfoToDataType(new RowTypeInfo(fieldTypes, fieldNames));
    }

    @Override
    public TableSchema getTableSchema() {
        return TableSchema.builder()
                .fields(fieldNames, TypeConversions.fromLegacyInfoToDataType(fieldTypes))
                .build();
    }

    @Override
    public DataStream<Row> getDataStream(StreamExecutionEnvironment environment) {
        throw new UnsupportedOperationException("do not support getDataStream");
    }

    public static final classBuilder{
        private String[] fieldNames;
        private TypeInformation[] fieldTypes;

        privateBuilder() {
        }

        publicstatic Builder newBuilder() {
            return new Builder();
        }

        public Builder withFieldNames(String[] fieldNames) {
            this.fieldNames = fieldNames;
            return this;
        }

        public Builder withFieldTypes(TypeInformation[] fieldTypes) {
            this.fieldTypes = fieldTypes;
            return this;
        }

        public RedisAsyncLookupTableSource build() {
            return new RedisAsyncLookupTableSource(fieldNames, fieldTypes);
        }
    }
}

MyAsyncLookupFunction

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.typeutils.RowTypeInfo;
import org.apache.flink.table.functions.AsyncTableFunction;
import org.apache.flink.table.functions.FunctionContext;
import org.apache.flink.types.Row;

import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

public classMyAsyncLookupFunctionextendsAsyncTableFunction<Row> {

    private final String[] fieldNames;
    private final TypeInformation[] fieldTypes;

    private transient RedisAsyncCommands<String, String> async;

    publicMyAsyncLookupFunction(String[] fieldNames, TypeInformation[] fieldTypes) {
        this.fieldNames = fieldNames;
        this.fieldTypes = fieldTypes;
    }

    @Override
    publicvoidopen(FunctionContext context) {
        //配置redis异步连接
        RedisClient redisClient = RedisClient.create("redis://127.0.0.1:6379");
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        async = connection.async();
    }

    //每一条流数据都会调用此方法进行join
    publicvoideval(CompletableFuture<Collection<Row>> future, Object... paramas) {
        //表名、主键名、主键值、列名
        String[] info = {"userInfo", "userId", paramas[0].toString(), "userName"};
        String key = String.join(":", info);
        RedisFuture<String> redisFuture = async.get(key);

        redisFuture.thenAccept(new Consumer<String>() {
            @Override
            publicvoidaccept(String value) {
                future.complete(Collections.singletonList(Row.of(key, value)));
            }
        });
    }

    @Override
    public TypeInformation<Row> getResultType() {
        return new RowTypeInfo(fieldTypes, fieldNames);
    }

    public static final classBuilder{
        private String[] fieldNames;
        private TypeInformation[] fieldTypes;

        private Builder() {
        }

        public static Builder getBuilder() {
            return new Builder();
        }

        public Builder withFieldNames(String[] fieldNames) {
            this.fieldNames = fieldNames;
            return this;
        }

        public Builder withFieldTypes(TypeInformation[] fieldTypes) {
            this.fieldTypes = fieldTypes;
            return this;
        }

        public MyAsyncLookupFunction build() {
            return new MyAsyncLookupFunction(fieldNames, fieldTypes);
        }
    }
}

使用Async十分需要注意的几个点:

1、 外部数据源必须是异步客户端:如果是线程安全的,你可以不加 transient 关键字,初始化一次。否则,你需要加上 transient,不对其进行初始化,而在 open 方法中,为每个 Task 实例初始化一个。

2、eval 方法中多了一个 CompletableFuture,当异步访问完成时,需要调用其方法进行处理。比如上面例子中的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
redisFuture.thenAccept(new Consumer<String>() {
            @Override
            public void accept(String value) {
                future.complete(Collections.singletonList(Row.of(key, value)));
            }
        });

3、社区虽然提供异步关联维度表的功能,但事实上大数据量下关联外部系统维表仍然会成为系统的瓶颈,所以一般我们会在同步函数和异步函数中加入缓存。综合并发、易用、实时更新和多版本等因素考虑,Hbase可能是最理想的外部维表。

参考文章:

http://wuchong.me/blog/2017/05/17/flink-internals-async-io/#

https://www.jianshu.com/p/d8f99d94b761

https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=65870673

https://www.jianshu.com/p/7ce84f978ae0

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据真好玩 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
TKE操作指南 - TKE产品介绍(一)
腾讯云容器服务(Tencent Kubernetes Engine,TKE)是高度可扩展的高性能容器管理服务,您可以在托管的云服务器实例集群上轻松运行应用程序。使用该服务,您将无需安装、运维、扩展您的集群管理基础设施,只需进行简单的 API 调用,便可启动和停止 Docker 应用程序,查询集群的完整状态,以及使用各种云服务。您可以根据资源需求和可用性要求在集群中安排容器的置放,满足业务或应用程序的特定要求。
亮哥说TKE
2019/08/12
5.2K1
TKE操作笔记02
本次笔记主要讲述了如何在腾讯云控制台创建并使用你的第一个kubernetes集群,创建过程中每个步骤的区别以及如何选择,保证自己的集群资源达到最优。
聂伟星
2020/06/02
1.6K0
Docker最全教程——从理论到实战(六)
托管到腾讯云容器服务,我们的公众号“magiccodes”已经发布了相关的录屏教程,大家可以结合本篇教程一起查阅。
心莱科技雪雁
2018/12/28
1.3K0
Docker最全教程——从理论到实战(六)
Docker最全教程——从理论到实战(六)
托管到腾讯云容器服务,我们的公众号“magiccodes”已经发布了相关的录屏教程,大家可以结合本篇教程一起查阅。
雪雁-心莱科技
2018/12/27
1.1K0
【云+社区年度征文】TKE实战排错
公司企业面对不断变化的用户需求,对于应用的快速开发上线提出了新的挑战,一方面在功能性能方面要求越来越高,另一方面对安全性、稳定性、高可用性、可扩展性也越来越苛刻。当云计算重构整体IT产业的同时,也赋予了企业崭新的增长机遇,通过充分利用云计算的能力,释放更多精力专注于自己的业务。以容器为代表的云原生技术正在推动着整个商业世界飞速发展,企业数字化转型过程中,云原生成为企业持续发展和不断创新的必然选择,一款简单易用、灵活扩展、安全可靠的容器平台是众多企业的必由之选。
KaliArch
2020/12/13
1.2K0
【云+社区年度征文】TKE实战排错
腾讯云 TKE Everywhere 特性发布,用户可在自有基础设施中托管 K8s 服务
孔令飞,腾讯云资深工程师,拥有大规模 Kubernetes 集群、微服务的研发和架构经验,目前专注于云原生混合云领域的基础架构开发。 朱翔,腾讯云容器服务高级产品经理,目前负责云原生混合云产品方案设计工作。 前言 企业数字化转型已经成为企业的核心战略。以云计算为核心的新一代 IT 技术,成为了企业数字化转型的重要支撑,上云成为企业数字化转型的必由之路。企业在上云过程中由于数据安全隐私、资源利旧、业务容灾等原因,在上云时通常会采用混合云的架构,混合云成为企业上云新常态。 近几年,随着云原生技术在云计算市场
腾讯云原生
2021/09/03
1.2K0
剑指Kubernetes 揭秘腾讯云的PaaS技术选型策略
Kubernetes 很火,一大批互联网公司早已领先一步,搭建起专有的 PaaS平台,传统企业们看到的 Kubernetes的趋势,亦不甘落后,在试水的道上一路狂奔……
用户1532637
2018/03/29
11.8K8
剑指Kubernetes 揭秘腾讯云的PaaS技术选型策略
当TKE遇上Coding, 业务如何实现快速迭
在互联网行业敏捷开发,DevOps 理念被越来越多的企业采纳, 敏捷开发和DevOps 本质上都是一种协作文化, 都是着眼于打破壁垒, 增加成员共同责任感。DevOps和Agile减少了交接,提高了向客户交付的速度。
朱瑞卿
2020/08/06
2.1K0
当TKE遇上Coding, 业务如何实现快速迭
腾讯云容器服务TKE(原CCS),为用户提供 Kubernetes1.10 服务
腾讯云容器服务是首批通过Kubernetes一次性认证的服务商,本次腾讯云容器服务再次支持kubernetes 1.10,并再次通过Kubernetes一次性认证。如需可提交工单申请kubernetes1.10版本
腾讯云容器服务团队
2018/06/21
2.5K0
在腾讯云容器服务 TKE 中实践 DevOps
jokey,腾讯云容器产品工程师,热衷于云原生领域。目前主要负责腾讯云TKE 的售中、售后的技术支持,根据客户需求输出合理技术方案与最佳实践。 概述 DevOps 理念被越来越多的企业采纳,DevOps 是 Development 和 Operations 的组合词,代表着重视「软件开发人员(Dev)」和「IT 运维技术人员(Ops)」之间沟通合作的文化;旨在透过自动化「软件交付」和「架构变更」的流程,使得构建、 测试、发布软件的过程能够更加地快捷、频繁和可靠。在云原生时代,我们更需要 Devops 思维
腾讯云原生
2020/11/05
2.6K0
未来已来:从信通院 Serverless 标准,看无服务器发展趋势
“ 无服务器架构(Serverless)是一种将应用与基础设施彻底分离的架构理念,开发人员无需关心基础设施的运维工作,只需专注于应用逻辑的开发,真正实现了弹性伸缩与按需付费。当前各大云服务商和头部互联网企业的内部业务 Serverless 化升级改造已经开始小范围试水;中小企业基于 Serverless 的业务应用也初见端倪,已然可见初具规模的企业级应用,未来可期。Serverless 生态已初具规模,可以预见,Serverless 将成为下一代云计算服务形态的趋势。 ” 在此背景下,云函数(SCF)、弹
腾讯云serverless团队
2021/08/04
1.8K0
容器技术及其应用白皮书--附录介绍
版权声明:本文为木偶人shaon原创文章,转载请注明原文地址,非常感谢。 https://blog.csdn.net/wh211212/article/details/53541688
shaonbean
2019/05/26
1.7K0
7月腾讯云容器产品技术月报 | 多款产品首秀
腾讯云服务网格Tencent Cloud Mesh,是一致、可靠、透明的云原生服务通信网络管控基础平台。基于Istio,TCM与腾讯云基础设施原生集成,提供云原生服务发现、流量管控和端到端可观测管理环境,全面覆盖应用程序的南北向与东西向通信连接,支撑业务轻松打造灵活的分布式高可用架构,高效便捷的变更发布能力和安全可控的服务通信网络。
腾讯云原生
2020/08/17
9220
容器技术邂逅DevOps,一个新生态的形成
为了帮助IT从业者职业之路拥有更多收获,在诸多C粉的殷切期待下,由CTO俱乐部打造的CTO线上讲堂自登场以来获得大家好评。本期邀请时速云联合创始人兼CTO王磊带来容器技术邂逅DevOps,一个新生态的
CSDN技术头条
2018/02/11
8790
容器技术邂逅DevOps,一个新生态的形成
4月腾讯云容器产品技术月报|五一快乐,豪礼送送送!
2022年4月 VOL:24 腾小云告诉你最前线的产品新特性, 总有一款让你心动~ 云说新品 容器产品新特性4月上新 腾讯云弹性容器服务EKS 安全稳定的无服务器 Kubernetes 服务 弹性容器服务(Elastic Kubernetes Service,EKS)是腾讯云容器服务推出的无须用户购买节点即可部署工作负载的服务模式。 EKS 创建工作负载时支持开启自动升配 EKS 支持 Job 批量调度能力,需开放白名单使用 支持工具化将 TKE 集群升级至 EKS 集群 EKS 上线
腾讯云原生
2022/05/05
9120
4月腾讯云容器产品技术月报|五一快乐,豪礼送送送!
腾讯云边缘容器 TKE Edge 国内首批通过边缘容器技术能力认证
2021年6月4日,由工信部中国信通院和开源产业联盟主办的2021“云边协同大会”在北京顺利开幕。会上公布了 国内首个“分布式云与云边协同标准体系”,作为国内顶级的云计算服务商,腾讯云的边缘容器服务 TKE Edge 产品顺利通过了边缘容器《基于云边协同的边缘容器技术能力要求》标准,成为国内首批获得该认证的厂家。 该评估的通过,证明 TKE Edge 在云端管理、节点监控、边缘自治、容器安全等方面均符合基于云边协同的边缘容器技术能力要求,满足全部包括云端统一运维、边缘节点监测、边缘节点自治、异构边缘资源适
腾讯云原生
2021/06/07
1.4K0
不努力提高效率,小姐姐都被人追走了:K8S一键部署了解一下?
随着互联网时代的不断发展,开发者可能会面临这样的困境:为了解决问题、提升开发效率而竭力研发出来的“创新”,似乎削弱了他们在公司的重要程度,甚至取代了他们原先的地位。比如,在云原生时代,部分企业更愿意选择 K8s 来解决运维、弹性的问题,而不是组建一支需要耗费大量雇佣资金、管理资金的研发团队。
吉林乌拉
2019/10/30
1.4K0
不努力提高效率,小姐姐都被人追走了:K8S一键部署了解一下?
腾讯云一口气发布四大新品,云原生时代真的来了!
6月25日,在上海召开的KubeCon 2019大会上,腾讯云正式发布了多款云原生技术产品:企业级容器服务平台TKE、容器服务网格TKE Mesh、Serverless 2.0、一站式DevOps平台。
腾讯云serverless团队
2019/07/02
1.3K0
下载达10万次的IDEA插件,K8s一键部署了解下
导读:涉及开发的技术人员,永远绕不开的就是将应用部署到相应服务器上,本文将给大家讲解:对于容器服务 ACK,怎么实现真正“一键部署”,提高开发部署效率,在 K8s 的运用上做到快人一步。
JAVA葵花宝典
2019/11/06
2K0
下载达10万次的IDEA插件,K8s一键部署了解下
腾讯云云原生混合云-TKE发行版
徐蓓,腾讯云专家工程师,深耕云计算、K8s、离在线混部领域,K8s 社区贡献者,Memory QoS with cgroups v2 KEP 作者。 李波,腾讯云后台研发工程师,负责 TKE 版本发布及k8s技术支持。 背景 TKE 发行版(TKE Kubernetes Distro)是由腾讯云 TKE 发布的 K8s 发行版本,用于帮助用户创建安全可靠的 K8s 集群。用户可依托 TKE 发行版在自建或者托管机房、物理机或者虚机上,运行与 TKE 完全一致的 K8s 服务。TKE 发行版集群可无缝与腾
腾讯云原生
2021/05/28
1.7K0
推荐阅读
相关推荐
TKE操作指南 - TKE产品介绍(一)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验