【1024开发者峰会】2020第二届全球移动开发者技术峰会即将开启

活动MobTech 发表了文章 • 0 个评论 • 74 次浏览 • 2020-09-24 11:42 • 来自相关话题

阔别一年,我们回来了~2020第二届全球移动开发者技术峰会即将开启改变世界的方式有很多种,但利用科技的方式很酷!手握科技变革的钥匙,拥有改变世界的力量。他们就是——开发者。 Linux之父——李纳斯·托沃兹 仅利用业余时间,创造出全球最流行... ...查看全部

阔别一年,我们回来了~2020第二届全球移动开发者技术峰会即将开启

改变世界的方式有很多种,

但利用科技的方式很酷!

手握科技变革的钥匙,

拥有改变世界的力量。

他们就是——开发者。

 

Linux之父——李纳斯·托沃兹

 图片1.png

仅利用业余时间

创造出全球最流行的操作系统内核之一

 

世界开了个窗口“男团”——

约翰·凯默尼、托马斯·库茨

 图片2.png

BASIC编程语言发明者。

 

互联网之父——蒂姆·伯纳斯·李

图片3.png 

万维网发明人。

2004年,英女皇伊丽莎白二世

颁发大英帝国爵级司令勋章。

 

算法和程序设计技术的先驱者

——唐纳德·克努特

 图片4.png

计算机排版系统 TEX 和

METAFONT 的发明者,

写出了在技术领域和《相对论》齐名的

《计算机程序设计的艺术》

 

C语言之父——丹尼斯·里奇

 

开发者最常用的编程语言之一

而这位大神也用实力

奠定了现代程序语言基础

 

JAVA之父——詹姆斯·高斯林

 

“一次编写,到处运行”

是对JAVA语言的真实写照

被用于数十亿移动设备

和互联网服务器之上


时至今日,

我们使用的电脑、互联网、

以及各种 IT 电子设备与服务

都离不开这些伟大的先驱者。

 

而当下MobTech袤博能做

就是肩负起为开发者解压的责任,

利用先进的科技技术及应用,

提升开发者的工作效率,

使得他们拥有更多宝贵的时间

深耕顶级技术研发,以及更好地投入生活。

 

为延续

2019全球移动开发者技术峰会热情,

重燃开发者们的创造激情,

图片5.png

图片6.png

图片7.png

图片8.png图片9.png 

 

所以,今年我们又来了!

 

活动简介

图片10.png

金牌出品

 图片11.png

特邀嘉宾

 图片12.png

活动流程

 图片13.png

精美礼物

 图片14.png

合作伙伴

 图片15.png

报名通道

 图片16.png

1024日,来北京面基吧!


开源 | 如何实现一个iOS AOP框架?

技术交流王叫兽 发表了文章 • 0 个评论 • 68 次浏览 • 2020-09-23 17:33 • 来自相关话题

Aspect使用了OC的消息转发流程,有一定的性能消耗。本文作者使用C++设计语言,并使用libffi进行核心trampoline函数的设计,实现了一个iOS AOP框架——Lokie。相比于业内熟知的Aspects,性能上有了明显的提升。本文将分享Lokie... ...查看全部

Aspect使用了OC的消息转发流程,有一定的性能消耗。本文作者使用C++设计语言,并使用libffi进行核心trampoline函数的设计,实现了一个iOS AOP框架——Lokie。相比于业内熟知的Aspects,性能上有了明显的提升。本文将分享Lokie的具体实现思路。

u=197328961,4288333579&fm=26&gp=0.jpg

前言

不自觉的想起自己从业的这十几年,如白驹过隙。现在谈到上还熟悉的的语言以ASM/C/C++/OC/JS/Lua/Ruby/Shell等为主,其他的基本上都是用时拈来过时忘,语言这种东西变化是在太快了, 不过大体换汤不换药,我感觉近几年来所有的语言隐隐都有一种大统一的走势,一旦有个特性不错,你会在不同的语言中都找到这种技术的影子。所以我对使用哪种语言并不是很执着,不过C/C++是信仰罢了 : )


Lokie

工作中大部分用OC和Ruby、Shell之类的东西,前段时间一直想找一款合适的iOS下能用的AOP框架。iOS业内比较被熟知的应该就是Aspect了。但是Aspect性能比较差,Aspect的trampoline函数借助了OC语言的消息转发流程,函数调用使用了NSInvocation,我们知道,这两样都是性能大户。有一份测试数据,基本上NSInvocation的调用效率是普通消息发送效率的100倍左右。事实上,Aspect只能适用于每秒中调用次数不超过1000次的场景。当然还有一些其他的库,虽然性能有所提升,但不支持多线程场景,一旦加锁,性能又有明显的损耗。


找来找去也没有什么趁手的库,于是想了想,自己写一个吧。于是Lokie便诞生了。


Lokie的设计基本原则只有两条,第一高效,第二线程安全。为了满足高效这一设计原则,Lokie一方面采用了高效的C++设计语言,标准使用C++14。C++14因引入了一些非常棒的特性比如MOV语义,完美转发,右值引用,多线程支持等使得与C++98相比,性能有了显著的提升。另一方面我们抛弃了对OC消息转发和NSInvocation的依赖,使用libffi进行核心trampoline函数的设计,从而直接从设计上就砍倒性能大户。此外,对于线程锁的实现也使用了轻量的CAS无锁同步的技术,对于线程同步开销也降低了不少。


通过一些真机的性能数据来看,以iPhone 7P为例, Aspect百万次调用消耗为6s左右,而相同场景Lokie开销仅有0.35s左右, 从测试数据上来看,性能提升还是非常显著的。


我是个急性子,看书的时候也是喜欢先看代码。所以我先帖lokie的开源地址:


https://github.com/alibaba/Lokie


喜欢翻代码的同学可以先去看看。


Lokie的头文件非常简单, 如下所示只有两个方法和一个LokieHookPolicy的枚举。


#import <Foundation/Foundation.h>
typedef enum : NSUInteger {
    LokieHookPolicyBefore = 1 << 0,
    LokieHookPolicyAfter = 1 << 1,
    LokieHookPolicyReplace = 1 << 2,
} LokieHookPolicy;
@interface NSObject (Lokie)
+ (BOOL) Lokie_hookMemberSelector:(NSString *) selecctor_name
                           withBlock: (id) block
                              policy:(LokieHookPolicy) policy;
+ (BOOL) Lokie_hookClassSelector:(NSString *) selecctor_name
                                  withBlock: (id) block
                                     policy:(LokieHookPolicy) policy;
-(NSArray*) lokie_errors;
@end


这两个方法的参数是一样的,提供了对类方法和成员方法的切片化支持。


  • selector_name:是你感兴趣的selector名称,通常我们可以通过NSStringFromSelector 这个API来获取。


  • block:是要具体执行的命令,block的参数和返回值我们稍后讨论。


policy:指定了想要在该selector执行前,执行后执行block,或者是干脆覆盖原方法。


监控效果


拿一个场景来看看Lokie的威力。比如我们想监控所有的页面生命周期,是否正常。


比如项目中的 VC 基类叫 BasePageController,designated initializer 是 @selector(initWithConfig)。


我们暂时把这段测试代码放在application: didFinishLaunchingWithOptions中,AOP就是这么任性!这样我们在app初始化的时候对所有的BasePageController对象生命周期的开始和结束点进行了监控,是不是很酷?


Class cls = NSClassFromString(@"BasePageController");
[cls Lokie_hookMemberSelector:@"initWithConfig:"
                    withBlock:^(id target, NSDictionary *param){
                        NSLog(@"%@", param);
                        NSLog(@"Lokie: %@ is created", target);
} policy:LokieHookPolicyAfter];
[cls Lokie_hookMemberSelector:@"dealloc" withBlock:^(id target){
        NSLog(@"Lokie: %@ is dealloc", target);
} policy:LokieHookPolicyBefore];


block的参数定义非常有意思, 第一个参数是永恒的id target,这个selector被发送的对象,剩下的参数和selector保持一致。比如 "initWithConfig:" 有一个参数,类型是NSDNSDictionary *, 所以我们对 initWithConfig: 传递的是^(id target, NSDictionary *param),而dealloc是没有参数的,所以block变成了^(id target)。换句话说,在block回调当中,你可以拿到当前的对象,以及执行这个方法的参数上下文,这基本上可以为你提供了足够的信息。


对于返回值也很好理解,当你使用LokieHookPolicyReplace对原方法进行替换的时候,block的返回值一定和原方法是一致的。用其他两个flag的时候,无返回值,使用void即可。


另外我们可以对同一个方法进行多次hook,比如像这个样子:


Class cls = NSClassFromString(@"BasePageController");
 [cls Lokie_hookMemberSelector:@"viewDidAppear:" withBlock:^(id target, BOOL ani){
        NSLog(@"LOKIE: viewDidAppear 调用之前会执行这部分代码");
 }policy:LokieHookPolicyBefore];
 [cls Lokie_hookMemberSelector:@"viewDidAppear:" withBlock:^(id target, BOOL ani){
        NSLog(@"LOKIE: viewDidAppear 调用之后会执行这部分代码");
 }policy:LokieHookPolicyAfter];

细心的你有木有感觉到,如果我们用个时间戳记录前后两次的时间,获取某个函数的执行时间就会非常容易。


前面两个简单的小例子算是抛砖引玉吧, AOP在做监控、日志方面来说功能还是非常强大的。


实现原理


整个AOP的实现是基于iOS的runtime机制以及libffi打造的trampoline函数为核心的。所以这里我也聊聊iOS runtime的一些东西。这部分对于很多人来说,可能比较熟悉了。



OC runtime里有几个基础概念:SEL, IMP, Method。


SEL



typedef struct objc_selector  *SEL;
typedef id  (*IMP)(id, SEL, ...);
struct objc_method {
    SEL method_name;
    char *method_types;
                IMP method_imp;
} ;
typedef struct objc_method *Method;


objc_selector这个结构体很有意思,我在源码里面没有找到他的定义。不过可以通过翻阅代码来推测objc_selector的实现。在objc-sel.m当中,有两个函数代码如下:


const char *sel_getName(SEL sel) {
    if (!sel) return "<null selector>";
    return (const char *)(const void*)sel;
}

sel_getName这个函数出镜率还是很高的,从它的实现来看,sel和const char *是可以直接互转的,第二个函数看的则更加清晰:



static SEL __sel_registerName(const char *name, int copy) ;
//! 在 __sel_registerName 中有通过const char *name 直接得到 SEL 的方法
...
if (!result) {
    result = sel_alloc(name, copy);
}
...
//! sel_alloc的实现
static SEL sel_alloc(const char *name ,bool copy)
{
    selLock.assertWriting();
    return (SEL)(copy ? strdupIfMutable(name):name);
}

看到这里,我们基本上可以推测出来objc_selector的定义应该是类似与以下这种形式:



typedef struct {
     char  selector[XXX];
     void *unknown;
      ...
}objc_selector;


为了提升效率, selecor的查找是通过字符串的哈希值为key的,这样会比直接使用字符串做索引查找更加高效。

//!objc4-208  版本的哈希算法
static CFHashCode _objc_hash_selector(const void *v) {
    if (!v) return 0;
    return (CFHashCode)_objc_strhash(v);
}
static __inline__ unsigned int _objc_strhash(const unsigned char *s) {
    unsigned int hash = 0;
    for (;;) {
  int a = *s++;
  if (0 == a) break;
  hash += (hash << 8) + a;
    }
    return hash;
}



//! objc4-723 版本的hash算法
static unsigned _mapStrHash(NXMapTable *table, const void *key) {
    unsigned    hash = 0;
    unsigned char *s = (unsigned char *)key;
    /* unsigned to avoid a sign-extend */
    /* unroll the loop */
    if (s) for (; ; ) {
  if (*s == '\0') break;
  hash ^= *s++;
  if (*s == '\0') break;
  hash ^= *s++ << 8;
  if (*s == '\0') break;
  hash ^= *s++ << 16;
  if (*s == '\0') break;
  hash ^= *s++ << 24;
    }
    return xorHash(hash);
}
static INLINE unsigned xorHash(unsigned hash) {
    unsigned xored = (hash & 0xffff) ^ (hash >> 16);
    return ((xored * 65521) + hash);
}


至于为什么会专门搞出一个objc_selector, 我想官方应该是想强调SEL和const char 是不同的类型。


 IMP


IMP的定义如下所示:


#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
#endif

LLVM 6.0 后增加了 OBJC_OLD_DISPATCH_PROTOTYPES,需要在 build setting 中将 Enable Strict Checking of objc_msgSend Calls 设置为NO才可以使用  objc_msgSend(id self, SEL op, ...)。有些同学在调用objc_msgSend的时候,编译器会报如下错误,就是这个原因了。


Too many arguments to function call, expected 0, have 2


IMP 是一个函数指针,它是最终方法调用是的执行指令入口。


objc_method可以说是非常关键了,它也是OC语言可以在运行期进行method swizzling 的设计基石, 通过objc_method 把函数地址,函数签名以及函数名称打包做个关联, 在 真正执行类方法的时候,通过selector名称,查找对应的IMP。同样,我们也可以通过在运行期替换某个selector 名称与之对应的IMP来完成一些特殊的需求。


消息发送机制


这三个概念明确了之后,我们继续聊下消息发送机制。我们知道当向某个对象发送消息的时候,有一个关键函数叫objc_msgSend, 这个函数里到底干了些什么事情, 我们简单聊一聊。


//! objc_msgSend 函数定义
id objc_msgSend(id self, SEL op, ...);


这个函数内部是用汇编写的,针对不同的硬件系统提供了相应的实现代码。不同的版本实现应该是存在差异, 包括函数名称和实现(我查阅的版本是 objc4-208)。


objc_msgSend首先第一件事就是检测消息发送对象self是否为空,如果为空,直接返回,啥事不做。这也就是为什么对象为nil时,发送消息不会崩溃的原因。做完这些检测之后,会通过self->isa->cache去缓存里查找selector对应的Method, (cache里面存放的是Method ),查找到的话直接调用Method->method_imp。没有找到的话进入下一个处理流程,调用一个名为class_lookupMethodAndLoadCache的函数。



这个函数的定义如下所示:

IMP _class_lookupMethodAndLoadCache (Class  cls, SEL sel) 
{
    ...
        if (methodPC == NULL)
        {
            //!  这里指定消息转发入口
            // Class and superclasses do not respond -- use forwarding
            smt = malloc_zone_malloc (_objc_create_zone(), sizeof(struct objc_method));
            smt->method_name    = sel;
            smt->method_types   = "";
            smt->method_imp     = &_objc_msgForward;
            _cache_fill (cls, smt, sel);
            methodPC = &_objc_msgForward;   
    }
    ...
}

消息转发机制这部分动态方法解析,备援接收者,消息重定向应该是很多面试官都喜欢问的环节 : ) ,我想大家肯定是比较熟悉这部分内容,这里就不再赘述了。


trampline函数的实现


接下来的内容,我们简单介绍下,从汇编的视角出发,如何实现一个trampline函数,完成c函数级别的函数转发。以x86指令集为例,其他类型原理也相似。


从汇编的角度来看,函数的跳转,最直接的方式就是插入jmp指令。x86指令集中,每条指令都有自己的指令长度,比如说jmp指令, 长度为5,其中包含一个字节的指令码,4个字节的相对偏移量。假定我们手头有两个函数A和B, 如果想让B的调用转发到A上去, 毫无疑问,jmp指令是可以帮上忙的。接着我们要解决的问题是如何计算出这两个函数的相对偏移量。这个问题我们可以这样考虑, 但cpu碰到jmp的时候,它的执行动作为ip = ip + 5 + 相对偏移量。


为了更加直接的解释这个问题,我们看看下面的额汇编函数(不熟悉汇编的同学不用担心, 这个函数没有干任何事情,只是做一个跳转)。


你也可以跟我一起来做,先写一个jump_test.s,定义了一个什么事情都没做的函数。


先看看汇编代码文件:(jump_test.s)翻译成C函数的话,就是void jump_test(){ return ; }。

.global _jump_test 
_jump_test:
    jmp   jlable    #!为了测试jmp指令偏移量,人为的给加几个nop
    nop
    nop 
    nop 
jlable:
    rep;ret

接着,我们在创建一个C文件:在这个文件里,我们调用刚才创建的jump_test函数。

#include <stdio.h>
extern void jump_test();
int main(){
    jump_test();
}


最后就是编译链接了, 我们创建一个build.sh生成可执行文件portal 。

#! /bin/sh
cc -c  -o main.o main.c 
as -o jump_test.o jump_test.s 
cc -o  portal main.c jump_test.o

我们使用 lldb 加载调试刚才生成的prtal文件,并把断点打在函数 jump_test 上。

lldb ./portal
b jump_test
r


在我机器上,是如下的跳转地址, 你的地址可能和我的不太一样,不过没关系,这并不影响我们的分析。

Process 22830 launched: './portal' (x86_64)
Process 22830 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000f9f portal`jump_test
portal`jump_test:
->  0x100000f9f <+0>: jmp    0x100000fa7               ; jlable
    0x100000fa4 <+5>: nop    
    0x100000fa5 <+6>: nop    
    0x100000fa6 <+7>: nop


演示到这里的时候,我们成功的从汇编的视角,看到了一些我们想要的东西。


首先看看当前的 ip 是 0x100000f9f, 我们汇编中使用的jlable此时已经被计算,变成了新的目标地址(0x100000fa7)。我们知道,新的 ip 是通过当前 ip 加偏移算出来的, jmp的指令长度是5,前面我们已经解释过了。所以我们可以知道下面的关系:


new_ip = old_ip + 5 + offset;

把从 lldb 中获取的地址放进来,就变成了:

0x100000fa7 = 0x100000f9f + 5 + offset ==> offset = 3.


回头看看汇编代码, 我们在代码中使用了三个nop, 每个nop指令为1个字节, 刚好就是跳转到三个nop指令之后。做了个简单的验证之后,我们把这个等式做个变形,于是得到 offset = new_ip - old_ip - 5; 当我们知道 A函数和B函数之后,就很容易算出jmp的操作数是多少了。


讲到这里,函数的跳转思路就非常清晰了,我们想在调用A的时候,实际跳转到B。比如我们有个C api, 我们希望每次调用这个api的时候,实际上跳转到我们自定义的函数里面, 我们需要把这个api的前几个字节修改下,直接jmp到我们自己定义的函数中。前5个字节第一个当然就是jmp的操作码了,后面四个字节是我们计算出的偏移量。


最后给出一个完整的例子。汇编分析以及C代码一并打包放上来。

#include <stdio.h>
#include <mach/mach.h>
int  new_add(int a, int b){
    return a+b;
}
int add(int a, int b){
    printf("my_add org is called!\n");
    return 0;
}
typedef struct{
  uint8_t jmp;
  uint32_t off;
} __attribute__((packed)) tramp_line_code;
void dohook(void *src, void *dst){
    vm_protect(mach_task_self(), (vm_address_t)src, 5, 0, VM_PROT_ALL);
    tramp_line_code jshort;
    jshort.jmp = 0xe9;
    jshort.off = (uint32_t)(long)dst - (uint32_t)(long)src - 0x5;
    memcpy(my_add, (const void*)&jshort, sizeof(tramp_line_code));
    vm_protect(mach_task_self(), (vm_address_t)src, 5, 0, VM_PROT_READ|VM_PROT_EXECUTE);
}
int main(){
    dohook(add, new_add);
    int c = add(10, 20); //!  该函数默认实现是返回 0, hook之后,返回 30
    printf("res is %d\n", c);
    return 0;
}

编译脚本(系统 macOS):

gcc -o portal ./main.c
执行: ./portal
输出: res is 30


至此, 函数调用已经被成功转发了。


本文作者:阳逍 阿里技术 

融云 CTO 杨攀: Geek Online 2020 编程挑战赛 让开发者站上 C 位

活动梅川酷子 发表了文章 • 0 个评论 • 117 次浏览 • 2020-09-21 14:27 • 来自相关话题

近日,首届 Geek Online 2020 编程挑战赛正式启动,作为挑战赛主办方的融云,希望借此机会与开发者一起,共同挖掘 RTC 和 IM 技术的创新应用场景,发现更多通信云领域的落地实践。据了解,此次编程挑战赛采用线上形式,开发者通过使用融云 ... ...查看全部

近日,首届 Geek Online 2020 编程挑战赛正式启动,作为挑战赛主办方的融云,希望借此机会与开发者一起,共同挖掘 RTC 和 IM 技术的创新应用场景,发现更多通信云领域的落地实践。据了解,此次编程挑战赛采用线上形式,开发者通过使用融云 IM+RTC SDK 进行创新应用开发,参赛作品通过 GitHub 提交,秉承开源、公平、公正的原则,从作品完整度、创新性以及商业价值三方面进行评选,致敬开发者精神。

c1b9f25c8aea944c7856a7110dfc54a.jpg

01 疫情推动音视频技术的应用场景发展

过去,音视频技术应用最广的两个场景集中在娱乐视频直播以及视频会议。在今年疫情的推动下,催生出更多的音视频应用场景,尤其以在线教育以及远程办公两大领域的使用最为广泛。

借助音视频技术,用户体验的方式从线下转移到线上,省去了路程奔波的时间,减少线下的空间成本,同时利用相关技术可以在线上获取到更好的互动体验,带来了远程体验的普及,让线上交流由被动变为主动。

后疫情时代,远程在线的沟通方式逐渐受到大家的认可,除了在线教育和远程办公外,其它线下场景也逐步线上化,例如用户可以远程开通银行卡,法庭可以在线上进行审判等等,通过各种远程无接触的服务,大家享受着音视频技术带来的便捷性。

因此,疫情不仅推动音视频技术的应用场景发展,相对应,音视频技术也逐渐成为了各行业、各产品作为支撑业务形态所必备的基础能力。

02 Geek Online 编程挑战赛上线开拓更多业务场景

为了挖掘更多更优秀的产品应用场景,融云发起了 Geek Online 2020 编程挑战赛,以“后疫情时代,通信云技术的创新及实践”为主题,鼓励开发者挖掘更多即时通讯和音视频技术的应用场景。挑战赛已于 8 月 24 日开始报名,赛程近 2 个月,10 月 17 日进行线上决赛,并计划于 10 月 31 日在 WICC 2020 互联网通信云大会现场颁奖

在谈到举办编程挑战赛的初衷时,融云 CTO 杨攀告诉笔者,融云服务的对象就是开发者群体,融云的使命是与开发者共成长。过去,融云与开发者建立了多种沟通渠道,包括线上的工单、电话、技术群、文档,以及线下的技术沙龙和 WICC 峰会。而编程挑战赛是想让开发者之间进行更好地交流互动,让开发者站在舞台中央,表达他们创新的想法和点子,也是融云与开发者互动模式的迭代。

微信图片_20200921142307.png

据了解,此次挑战赛的参赛作品须集成融云官网最新版本的即时通讯 SDK 或实时音视频(直播)SDK,应用可以实现一个具体场景或解决一个具体问题,并提交作品的全部源码、编译好的真机安装包,以及必要的说明文档(README.md),源码部分均以 MIT 开源协议对外开放。

本次挑战赛的作品评选会根据作品完成度(60%)、潜在商业价值(20%)、创意度(20%)等三个维度由专家进行点评打分。在杨攀看来,优秀的作品应该更加具有创意和想法。在作品具有一定完整度的前提下,是否具有创意的场景,同时也富有商业价值,是整个作品的加分项。“我认为大家并不需要追求项目的代码量,不在于规模,而在于开发者做的事情要有创意、有想法,可以直击人心,这样更容易获得更多评委的加分。”

03 致敬开发者精神 为开发者提供专业服务

值得注意的是,此次 Geek Online 2020 编程挑战赛有两个方面区别于其他开发者大赛,即作品提交渠道以及比赛服务模式。

首先,参赛作品并不是在融云官网提交,而是要求在 GitHub 上提交。杨攀解释道,众所周知,GitHub 是全球最大的开源社区,编程挑战赛的作品在 GitHub 提交是想要向开发者精神致敬,要求所有作品开源,以便能接受所有开发者的检验,让整个赛事更加公平公正。

此外,过去很多开发者大赛都是自助模式,即由比赛组委会公布完赛题、时间、赛程安排、作品要求、奖项等大赛内容之后,开发者便可以按照官方提供的文档,自行研究工具的使用,完成后在线提交作品。而融云的做法却截然不同,融云会给所有的开发团队提供专门的支持。杨攀表示,一是让服务团队及研发团队可以为参赛队伍提供一对一的支持服务,以便他们能够在有限的时间内完成更好的作品;另一方面,也是想借此机会,让研发团队与开发者进行更深入地交流,聆听并收集开发者的想法和反馈,以助于融云的产品迭代演进。

在挑战赛奖励方面,除了奖金和奖杯以外,融云还会引入投资机构,如果开发团队的作品在完整度、商业价值等方面均受到了认可,融云会作为桥梁,将其对接给投资机构。此外,如果团队选手愿意以个人身份加入融云,也会开放融云招聘的绿色通道。优胜者还会受邀到 WICC 2020 全球互联网通信云大会现场参加颁奖典礼,与受邀参会的众多专家面对面学习交流

微信图片_20200921142258.png

▲ 扫码免费报名

04 赋能开发者 以硬实力赢取信赖

在即时通讯以及音视频领域,不乏很多有竞争实力的企业,大到云计算服务提供商,小到初创企业,在通信云赛道上,可谓“百家争鸣”。而融云又有哪些核心竞争力,可以在行业内脱颖而出,赢得众多开发者的信赖呢?

据杨攀介绍,即时通讯技术相对比较封闭和私有,业界开源的通信协议只有 XMPP。由于该协议是在 1999 年开源,在协议设计之处并未预知到未来移动互联网时代的网络复杂情况,因此这一开源协议在如今使用会存在很多问题,例如通信质量,系统支持人数限制等等。融云的核心研发团队来自于飞信,具有丰富的通信技术经验,自主设计了通讯协议,保证了平台通讯的基础质量。如今,融云的日活跃用户数量达到 7000 多万,在国内仅次于微信、QQ 等巨头产品,足见其技术实力。

在音视频领域,谷歌于 2010 年收购 VoIP 软件开发商 Global IP Solutions 而获得 WebRTC 技术,并于 2011 年开源该项目,但是谷歌只开源了部分功能,即端到端的通信,支持两个人之间的传输音视频流,无法支持多人沟通场景,此外,在更加复杂的网络环境中,经常会遇到丢包、带宽不够等情况,因此,服务提供商就需要在遵守公共开源的协议下进行调优。于是,融云在音视频的用户规模、网络质量、通信链路以及接口等方面进行了开发和优化,保证了音视频的质量以及技术的易用性。

虽然业界有标准的协议以及开源的框架,但是,对于音视频和即时通讯领域的自研开发还是有门槛的。杨攀表示,首先是成本问题,包括团队成员的组建和投入,需要组织大量人力来完成;其次是时间的投入,在如今互联网竞争激烈的时代,时间不等人,需要快速开发出稳定可用的产品或功能;第三,规模问题,当用户量激增或业务扩张时,系统不稳定有可能导致功能不可用,从而流失用户。融云基于多年的积累,满足市面上绝大部分的客户需求,并将开发者需要的功能和能力封装成接口,甚至提供了标准化的 UI 界面,帮助开发者快速完成自己的产品功能研发。

通信云技术发展多年,未来会有哪些发展趋势呢?杨攀表示,通信云的发展过程是相对循序渐进的。随着 5G 的到来,互联网通信基础设施质量也逐步提升,更多的变化则是场景的创新应用,功能丰富度,以及产品接口的易用性。未来,融云也会重点以平台为依托,在场景应用、产品功能、基础设施和接口等方面,全方位提升能力,赋能开发者。

预见·后大数据时代——AWS & Unitimes深圳大数据交流会来啦!

活动Unitimes科技 发表了文章 • 0 个评论 • 67 次浏览 • 2020-09-17 17:05 • 来自相关话题

随着移动互联网、物联网、云计算等产业的深入发展,大数据产业规模也正不断扩大,其体量呈现爆发式增长态势。在掌握大数据技术的同时,如何把握大数据产业的趋势,将成为本次meetup探讨的内容。本次meetup主题为「预见·后大数据时代」,由AWS和Unitimes联... ...查看全部
AWS*Unitimes_活动行海报.png


随着移动互联网、物联网、云计算等产业的深入发展,大数据产业规模也正不断扩大,其体量呈现爆发式增长态势。在掌握大数据技术的同时,如何把握大数据产业的趋势,将成为本次meetup探讨的内容。本次meetup主题为「预见·后大数据时代」,由AWS和Unitimes联合主办。活动将邀请来自一线的大数据专家现场分享实现大数据管理的技术,并与观众共同剖析大数据产业新一轮的挑战与风口。


01 时间地点

活动时间:2020年9月25日18:00 - 21:00

活动地点:深圳湾科技生态园2栋C座3楼新品发布中心


02 日程安排

18:00 - 19:30   签到+晚餐

19:30 - 20:05   演讲:现代数据仓库与数据湖构建

20:05 - 20:30   演讲:隐私计算:数据价值实现的突破口

20:30 - 21:00   圆桌讨论:大数据产业新一轮的挑战与风口


03 嘉宾介绍

打包文件-04.png


翁建清

AWS资深解决方案架构师


AWS 资深解决方案架构师,具有20年IT从业经验,涉及移动互联网、企业、金融、政府等行业,曾任职咨询总监、CIO、企业架构师等岗位,具有多年丰富的各类项目经验,尤其在数据仓库、大数据、数据应用场景等方面具有丰富的实战经验,目前专注于企业整体上云的架构规划、设计和实施,同时也是AWS大数据社区的专家成员。


打包文件-05.png


李升林

矩阵元首席架构师


北京航空航天大学硕士;拥有20余年电信、移动互联网、金融系统架构和大型研发团队技术管理经验;历任中国电信研究院高级开发工程师、卓望数码技术(中国移动控股子公司)系统架构专家;专注于高性能分布式系统、区块链、云平台等架构技术和密码学算法研究。


04 温馨提示

1、本次活动免费

2、请报名的小伙伴如实提供email和手机号码,我们会在活动开始前一天发送短信和邮件确认。

3、本次meetup提供晚餐,工作人员会根据报名人数提前准备晚餐,如已报名,请勿缺席。

4、本活动欢迎大家带自己的同事和朋友一起参加,为了确保良好的听课环境以及晚餐份额足够,请提前为他们报名。

5、注册报名成功后,可扫描下方二维码或添加微信Unitimes2019,回复“AWS”进活动交流群。

截屏2020-09-16 13.30.42.png


05 主办方

AWS*Unitimes-04.png

06 社区支持

截屏2020-09-17 16.37.13.png



懂程序员的产品经理是什么样子?

技术交流王叫兽 发表了文章 • 0 个评论 • 74 次浏览 • 2020-09-16 10:36 • 来自相关话题

在互联网行业,产品经理和程序员之间的关系很微妙。表面看上去水火不容,在一方的眼里看另外一方总是有这样那样的问题,相互吐槽。但现实是,大家都知道和对方在同一条船上。产品没做好的话,除了公司利益受损,产品经理和程序员也会各回各家各找各妈,重新找新工作去。产品做得好... ...查看全部

在互联网行业,产品经理和程序员之间的关系很微妙。表面看上去水火不容,在一方的眼里看另外一方总是有这样那样的问题,相互吐槽。但现实是,大家都知道和对方在同一条船上。

产品没做好的话,除了公司利益受损,产品经理和程序员也会各回各家各找各妈,重新找新工作去。

产品做得好的话,双方和睦相处、其乐融融?那是不可能的,这个辈子都不可能和睦相处。矛盾会更加严重……(都觉得自己功不可没)

所以Z哥就想来聊聊产品经理和程序员之间的协作问题。不管你是产品经理还是程序员,都应该找到与对方打交道的好方法。好的方法必然是寻求双赢的,而不是一个零和博弈。

这个主题会分别从不同的两个视角展开,今天我们先聊程序员视角,本来想两个视角一起聊,发现内容太多,写到一半还是拆了,先把一个视角写了。

如果你是程序员可以看看以下这些描述是你眼中的产品经理么?

如果你是产品经理可以看看从程序员起家的Z哥给出的一些建议。

程序员吐槽产品经理最多的原因主要是以下几个(以下内容可能会引起程序员们的极度舒适~):

  1. 开发过程中频繁修改需求。

  2. 验收过程中要求做比较大的修改。

  3. 说不清楚需求的价值

  4. 替程序员评估工作量

  5. 需求整理的不够细。

其中,频繁修改需求是程序员们最反感的,这是毋庸置疑的。

从产品经理的角度来说,虽然无法100%在开发过程中不修改需求,但是如果前期的工作做得足够充分,与业务方的沟通足够到位,至少去掉“频繁”两个字还是很有可能的。我甚至遇到过一些产品经理,在自己对业务都是一知半解的时候就开始整需求了,这必然会导致后续频繁的需求变更。

第二,验收过程中要求做比较大的修改。此时往往会伴随一句短语——“这不是我要的”。每当程序员听到这6个字的时候,脑子里是一万头草泥马奔过……

产生这个情况的原因有很多。可能是程序员理解偏差,也有可能是产品觉得功能效果不佳。但是大多数时候,产生这个情况的根本原因还是在需求评审阶段的沟通不够充分,双方之间并没有达成真正的共识。

但是如果要说什么时候双方的矛盾最激烈,那还不是修改需求的时候,而是需求评审的时候。

此时,很容易看到的一个景象是“讨价还价”。产品经理站在「价值」一方,程序员站在「成本」一方。当程序员们追问某个他们不认同的功能时,如果产品经理无法阐述出该功能令人信服的价值,那么必然受到吐槽。这是原因三。

原因四,有些产品经理是从程序员转过去的,之前做过一两年的开发工作。这个时长的经验其实是很危险的,很容易陷入到「达克效应」的第一阶段:高估自己的技术能力,低估他人的技术能力和工作难度。这会导致不管是明面上还是私底下会不自然地去评估程序员的工期是否合理,甚至会在需求评审的时候替程序员预估时间,如果高于自己的预估,便会认为他们偷懒。

最后一点。相信每个人程序员都提出过这样的问题“这里如果……,那么要怎么处理?”。这种就是需求考虑不够细致的体现。不过,要做好这点的确挺难的,这也是产品经理花费时间最多的地方。

聊了这么多场景,作为产品经理应该如何应对呢?

从思路上分为以下几步。

01

先明确大方向,并与程序员达成一致。

正如前面所提到的,产品经理站在「价值」方,程序员站在「成本」方,这注定了他们是对立的。最坏的结果就是双方互掐,就算相对好的结果也只是相互妥协做一个半吊子的功能(用系统的人不太舒服)。

但如果你的视野更大,格局更高,就会发现,如果以「投入产出比」角度来切入,双方不但都能理解,而且很容达成共识,毕竟花最小的成本干价值最大的活,是个正常人都能理解和认可不是么。

所以,可以在日常工作中不断的强化这个共识。一旦出现争执,就从这个角度来做最终决定,甚至基于这慢慢地还能建立起相互的信任,程序员真正拥有了产品思维,产品经理真正懂了程序员的难处。

02

将产品经理范畴内的事情做到极致。

所谓术业有专攻,与其相互吐槽,不如多花点时间把对方吐槽的地方做到极致。

03

有时候你虽然做的很好,想的也很仔细,但是还是会出现无法说服程序员认可你方案的情况。这是因为我们每个人本身都会存在「确认偏误」现象。

确认偏误是指搜寻,解释,偏爱和回想确认或支持一个人先前信念或价值观的信息的倾向。会导致对个人信念的过度自信,并且在面对相反的证据时可以保持或加强信念。

维基百科

所以,运用一些沟通技巧显得至关重要。只要一件事不是单凭一个人就能完成,你就得考虑如何提高协作效率。而产品经理和程序员的协作中,沟通又是最重要的。

下面展开说说具体可以做的一些事。主要是思路中的2和3。

01 提高专业性

我观察过一个现象,需求变更比较多的产品经理,他们的工作习惯往往是直接抄起原型工具就画原型,或者有很多工作时间在原型工具里。

这样非常容易陷入到一个思维惯性里面去,就是过于关注交互层面的事情,而轻视了背后业务流程的设计,甚至是业务的合理性。

我认为产品经理做事的时候一定要以User Story为核心来展开,先构思好一个User Story,然后就是把它真实发生的各种细节阐述清楚。做这事的过程先后分为以下四步:

  1. 定义User Story

  2. 定义交付标准

  3. 提供低保真原型

  4. 编写Use Case

这里面最费时费力的就是第四环节。并且,你想把User Story阐述清楚离不开一个专业的 Use Case编写。我之前收藏了一个非常专业的Use Case模版,是从知乎上的张恂老师那看到的,你感受一下。

用例名称:提问 
层次:!(用户目标层) 
范围:问答网站(以下简称系统) 
主用角:注册用户(以下简称用户) 
其他干系者:...
后态: 
前态:用户已登录。 
触发事件:用户选择提问。 
基本流:1. 系统显示新建问题框。 
输入问题 { 
2. 用户输入问题陈述(字数限制?);系统即时验证输入的有效性,并提示已有答案的类似问题(数量?)以免重复提问。 
3. 用户设定该问题的相关话题。 
4. 可选项 
用户可补充输入问题说明(背景、条件等详细信息)。 
5. 可选项 
…… 
6. 用户提交问题。 

7. 系统验证该问题的有效性。 
8. 系统发布该问题,并显示该问题页面。 
 扩展流:用户放弃提问:...
https://www.zhihu.com/question/48899115/answer/113274323 张恂老师的回答。

作为产品经理的你,如果想要减少被程序员吐槽需求不够细,或者降低开发过程中变更需求的频次,把use case用心做好是必不可少的。

02 沟通方面

与程序员的沟通方面,我总结了五动作,分别是「齐、拉、捧、说、谦」,可以根据情况组合出击。

「齐」就是视角对齐的意思。在聊需求之前,先交代需求的背景、意义。特别在中途需求变更的时候,这点非常重要。

继续搬出之前用过好几次的图。

640.jpg

如果视角不同,你说接下去还怎么聊?

「拉」是拉拢的意思。亚里士多德说过:

我们无法通过智力去影响别人,而情感却能做到这一点。

亚里士多德

所以,在沟通的时候要把程序员当作自己人看待,而不是敌对。比如,可以多用“我们”,“一起”等词语,进入一个协商的氛围。举个例子:“我们一起来看下这个问题”。少用”我觉得“、”我认为“;

「捧」是吹捧的意思,但并不是简单的拍马屁。

人都是有多面性的,针对不同的情况和场景,可能会表现出不同的特质,这会影响到双方的沟通。比如有的人在生活中很温和,但在工作时非常严苛,要求很高,这就是激发了不同的特质。

类似的,为了激活程序员的积极性,你可以在当下需要他发挥的地方吹捧一下。比如,你觉得某个程序员做的东西质量一般,小问题比较多。那么你在和他聊的时候特地捧一句,“我知道做程序员的都或多或少有完美主义倾向,对细节很关注。我这个功能设计的细节可是想了好久呢,不过对你来说应该很容易搞定吧。”

「说」是说服的意思。想要让对方从心底里的认同你,单凭打感情牌可不行。所以需要多用数据和用户反馈来提高你观点的可信度。

重视数据的产品经理有可能是优秀的产品经理,但不重视数据的产品经理一定不是优秀的产品经理。因为要看得懂数据的前提是得懂业务,并且还不能仅仅懂个皮毛。比如,

你得知道哪些环节产生的数据是关键。

多个数据之间的间接关系和影响是什么。

你设计的每一个功能会如何影响这些数据。

……

心里一直有着这些概念,程序员还会吐槽你提的需求价值低?

「让」是谦让的意思。俗话说,“三个臭皮匠顶一个诸葛亮”。可以给程序员留有表达他们观点的空间。

原因有两点。

大多数的产品设计背后有很多的知识是通用知识,每个人的生活经历都能成为经验。而每个人的生活经历又是不同的。

专业不同,哪怕站的视角相同,看到的同一个事物也会有些差别。用高端的说法叫“看到的本质不同”。基于这个本质出发,提出的观点可能会让你眼前一亮。

以上就是「齐、拉、捧、说、谦」五点。最后再送给你一句话:非必要情况,一定不要用“这是老板的要求“!,重复,重复。重要的事情说三遍。

还有一些比较成熟的方法体系也能改善产品和开发之间共识达成问题。比如,在领域驱动设计范畴中Event Storming。它就非常适合在前期的需求评审环节去使用。

感兴趣的可以自行了解。

好了,总结一下。

这篇呢,Z哥和你分享了我对产品经理如何更好地与程序员达成共识这件事的看法。

思路上分为三步:

  1. 先明确大方向,并与程序员达成一致。

  2. 将产品经理范畴内的事情做到极致

  3. 运用一些沟通技巧解决「确认偏误」现象。

关于第二点,给出的具体措施是。以User Story为核心,做好Use Case的编写工作,而不是花很多时间在原型上。

关于第三点,总结了五个动作,分别是「齐、拉、捧、说、谦」,可以根据情况组合出击。

希望对你有所帮助。

作者:Z哥,公众号“跨界架构师” 

如何做一个懂产品的程序员?

技术交流王叫兽 发表了文章 • 0 个评论 • 74 次浏览 • 2020-09-16 10:32 • 来自相关话题

两个相爱相杀的岗位,想要更好的达成共识、更好的合作,自然不仅仅是一方的事情。这次Z哥先会带你看看产品经理眼中的程序员是什么样子。然后给出一些我的建议。直接进入正题吧。从产品视角是怎么看程序员的呢?我根据我自己的经历以及与其他产品经理的交流下来看,吐槽的主要是以... ...查看全部

timg.jpg

两个相爱相杀的岗位,想要更好的达成共识、更好的合作,自然不仅仅是一方的事情。这次Z哥先会带你看看产品经理眼中的程序员是什么样子。然后给出一些我的建议。

直接进入正题吧。

从产品视角是怎么看程序员的呢?我根据我自己的经历以及与其他产品经理的交流下来看,吐槽的主要是以下几点:

  1. 这个功能实现不了。

  2. 希望所有产品都不要改版,一次性把现在或未来要做的开发完。

  3. 只关心要写多少代码,不在乎产品体验。

  4. 写完程序从不自测,直接丢给别人测试。

  5. 过分追寻新技术潮流,完全不考虑对产品带来什么价值。

第一点,的确存在一些由于技术限制导致实现成本无限大的需求,比如手机屏幕背景色根据手机壳颜色切换……

但是,国内的技术环境不像老美那的技术味道重,大多还是商业导向的,很少企业里需要用到高精尖的技术,所以,真正实现不了的功能微乎其微。

对于大多数的功能需求来说,无非是一个成本大小、价值高低的问题。从立场上看,程序员自然是站在「成本」一方的,但对大多数人来说,决定这个成本的主要因素往往是自己工作的难度和耗时,费时费力的功能就容易得到“实现不了”的结果。

第二点对大多数产品经理来说是他们的对立面。因为大多数产品经理最喜欢“走一步算一步”地高频迭代,甚至是有一个想法就开始干。而程序员则喜欢来一个大而全的,并且内容要非常详细的,心里的想法是,这样的话我一开始就可以设计一个完美架构来支撑它。

而且,内容越详细,产品经理就越不敢乱调整需求,毕竟“证据在手”嘛:D。

第三点在大多数程序员身上都能看到。毕竟做程序员的还是理科男偏多,对需要有同理心、需要靠感受的事情的确弱了一些。

第四点的原因主要有两个。

一个是对自己的代码过度自信导致,我自己深有体会。我还记得有一次我交付一个功能,那个功能我单元测试都写了不少,对质量很有信心,觉得就算有bug也都是比较深层的bug。结果没想到……第一天就测出来好几个低级的bug。

另一个原因是反正有测试人员在,等他们测出问题我再改不是更轻松。惰性使然,从个人角度的确如此。但是从团队角度来看,徒增了不少的沟通成本。

第五点的原因也有两个。

一个是行业里的新技术迭代的确太快,怕不学新技术被淘汰。

另一个原因是,只有用上新技术才能有谈资,显得自己与众不同、有成就感。

以上就是对这五点的简单分析,那么如何改善呢?继续往下看。

下面这些方法都是我亲测有效的,强烈推荐你也试试。这里的序号与前面被吐槽的五点一一对应。

01  说实现不了之前,先三思

根据先后可以做以下3个思考:

是觉得这个功能没有价值不想做吗?

真的实现不了?我想全了吗?

这些方案里,有成本比价值低的吗?

第一个问题先确定必要性。我们不是说不能推需求,而是要推掉低价值、无价值的需求。当然有没有价值不一定你说了算,但至少这才能算是拒绝的理由。

第二个问题,努力拓宽自己的边界、舒适区。如果我们总是习惯性地从大脑的记忆中找解决方案,那么将会永远在舒适区止步不前。

第三个问题,拒绝需求虽然不用动之以情,但一定需要晓之以理。当你能清楚的阐述利弊、收益比,拒绝需求自然不是一件需要相互扯皮的事情。

经过了这三个问题的思考,不管最终能不能实现,相信可以很好的与产品经理达成共识。

02  明白需求本身也是成本

过度地苛求需求要细、要完整、要全面,这个本身也是在增加产品经理需要投入的时间。你的开发成本是成本,产品经理的也是。

与其等一个“XXXX最终绝对不改版”,不如从已经达成共识的部分开工,在这个过程中再与产品经理「共创」,多一起沟通打磨,此时再让产品完善PRD等文档,形成最终版。

03  刻意练习,多换位到用户视角

平时多去体验一下自家的产品以及竞品,把整个过程中的感受记录下来。比如,哪里感到不太顺手、哪里感受到了小惊喜、哪里感到特别烦人等等。结果不重要,重要的是这个过程,慢慢锻炼自己作为用户的感知力。

有些程序员看起来经常把用户体验挂在嘴上,其实提出来的很多反而是脱离大众习惯的“个性化”需求,就是因为平时缺少对同行、外界的关注。

04  交付的东西是自己的「招牌」

“有人的地方就有江湖,有江湖的地方就有称号”。如果长期报以等测出来bug再去修的心态,你在别人心中的称号就是负面的。

轻则影响自己的口碑,影响与他人之间的协作关系;重则失去未来的晋升机会。一个对自己的东西都不负责的人,如何负责更多的人、更大的事情呢?

在这件事上,除了多自测外,作为过来人,我建议每一个程序员认真对待单元测试。特别把核心、复杂的方法单元测试给做上,这对交付功能的质量的提升非常明显。

05  不产生价值的新技术是“垃圾”

拥抱新技术是值得鼓励的。但是单纯的为了体验某新技术而去使用它,这不但给团队在挖坑,也在给自己挖坑。

比如你花了不少的时间在项目里用了某个新技术,但是对团队没有带来什么价值,你说后续公司还会继续投入资源加大新技术的使用吗?大概率并不会。那么之前了解到的一些知识,就会随着时间的推移而淡忘,投入的时间大多数浪费掉了。

所以,对待新技术Z哥的观点是。对于无法在工作中找到价值点的新技术浅尝辄止即可。相反,遇到可以产生价值的新技术,请全身心投入进去,而不是仅仅在应用层面捣腾,不去深入细节。之前发过一篇讲解新技术选用的文章《程序员与新技术之间的「爱」与「恨」》,可以点击文末的链接阅读。

很多程序员对待新技术的习惯是,打一枪换一个地方,经过了几年,发现技术实力还在原地打转,不免有些可惜。

另外,推荐大家可以阅读一两本心理学、行为学相关的书,特别是我们做程序员的。

这不但可以提高自己对用户体验的感觉,还能提高对人性的洞察力,包括对自我的认知。是一项不管在生活中还是工作中都非常有用的技能。

好了,总结一下。

这篇呢,Z哥和你分享了我对程序员如何更好地与产品经理达成共识这件事的看法。主要是以下五点建议:

1.说实现不了之前,先三思。

2.明白需求本身也是成本。

3.刻意练习,多换位到用户视角。

4.交付的东西是自己的「招牌」

5.不产生价值的新技术是“垃圾”

希望对你有所帮助。


作者:Z哥,公众号“跨界架构师” 

为什么有 HTTPS?因为 HTTP 不安全!

技术交流王叫兽 发表了文章 • 0 个评论 • 58 次浏览 • 2020-09-15 17:24 • 来自相关话题

为什么有 HTTPS?因为 HTTP 不安全! 现在的互联网已经不再是 " 田园时代 "," 黑暗森林 " 已经到来。上网的记录会被轻易截获,网站是否真实也无法验证,黑客可以伪装成银行网站,盗取真实姓名、密码、银行卡等敏... ...查看全部

u=1241929776,2696424852&fm=26&gp=0.jpg

为什么有 HTTPS?因为 HTTP 不安全! 现在的互联网已经不再是 " 田园时代 "," 黑暗森林 " 已经到来。上网的记录会被轻易截获,网站是否真实也无法验证,黑客可以伪装成银行网站,盗取真实姓名、密码、银行卡等敏感信息,威胁人身安全和财产安全。

上网的时候必须步步为营、处处小心,否则就会被不知道埋伏在哪里的黑客所 " 猎杀 "。

HTTPS 如何实现安全通信?如何构建出固若金汤的网络城堡?主要涉及的知识点如下:

了解什么是 HTTPS

什么样的才是安全的通信

对称加密与非对称加密、摘要算法、数字签名、完整性校验到底是什么

迁移 HTTPS 的必要性

什么是安全

做事要稳,老司机【码哥字节】开车要安全!不管是戴杜蕾斯还是安全气囊," 安全至关重要 "!

在通信过程中,具备以下特性则认为安全:机密性、完整性、不可否认、身份认证。

机密性

数据必须保密,只能有信任的人读取,其他人是不可见的秘密。诸葛亮的密报总不能让司马懿知道呀,不然还玩个蛋。通俗的说:就是不能让不相关的人看到不该看的东西。

完整性

也叫作一致性,也就是数据在传输过程中没有被非法篡改,内容不能多也不能少,一五一十的保持原状。

打个比方,原本张无忌说:" 赵敏,么么哒。",传信的飞鸽被周芷若抓到了,截取了消息,改成了 " 赵敏,去死吧!"。这么子搞,倚天屠龙记可能就会被改写了。

不可否认

也就做不可抵赖,不能否认已经发生过的事情。所谓 " 君子一言,驷马难追 "。" 老懒 " 这种事情不能发生。

就像尹志平亲密接触了小龙女,事后一直隐瞒否认,装作不知道,这是万万不可的。所以最终就嗝屁了。

身份验证

也就是确认对方的真实身份," 证明你是真的是你 ",保证消息发送到可信的人,而不是非法之徒。

比如令狐冲写了一份情书给任盈盈:" 盈盈,冲哥哥爱你哟 ",但是岳不群看到快递小哥,冒充是令狐冲,截取了情书后回复:" 傻逼,白日做梦 "。令狐冲不知道这是岳不群的回复,以为是任盈盈的,笑傲江湖又要重写了……

所以同时具备了机密性、完整性、身份认证、不可够人四个特性,通信双方的安全才有保证,才是真正的安全。

什么是 HTTPS

到这里,终于轮到 HTTPS 上台了,也就是它为 HTTP 增加了刚刚说的四大安全特性。

HTTPS 其实是一个 " 非常简单 " 的协议,规定了新的协议名 "https",默认端口号 443,至于其他的什么请求 - 应答模式、报文结构、请求方法、URI、头字段、连接管理等等都完全沿用 HTTP,没有任何新的东西。唯一的差别就是端口号不同、去掉明文传输。

那 HTTPS 凭啥就变得安全了呢?

就是因为他在 TCP/IP 与 HTTP 之间加上了 SSL/TLS ,从原来的 HTTP over TCP/IP 变成了 HTTP over SSL/TLS,让 HTTP 运行在 安全的 SSL/TLS 协议上,安全开车。

http 与 https

所以重点就是去掌握 SSL/TLS 到底是什么玩意成就了安全。

SSL/TLS

SSL 即安全套接层(Secure Sockets Layer),在 OSI 模型中处于第 5 层(会话层),由网景公司于 1994 年发明,有 v2 和 v3 两个版本,而 v1 因为有严重的缺陷从未公开过。

SSL 发展到 v3 时已经证明了它自身是一个非常好的安全通信协议,于是互联网工程组 IETF 在 1999 年把它改名为 TLS(传输层安全,Transport Layer Security),正式标准化,版本号从 1.0 重新算起,所以 TLS1.0 实际上就是 SSLv3.1。

TLS 由记录协议、握手协议、警告协议、变更密码规范协议、扩展协议等几个子协议组成,综合使用了对称加密、非对称加密、身份认证等许多密码学前沿技术。

浏览器与服务器在使用 TLS 建立连接的时候实际上就是选了一组加密算法实现安全通信,这些算法组合叫做 " 密码套件(cipher suite)"。

套件命名很有规律,比如 "ECDHE-RSA-AES256-GCM-SHA384"。按照 密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法 " 组成的 .

所以这个套件的意思就是:使用 ECDHE 算法进行密钥交换,使用 RSA 签名和身份验证,握手后使用 AES 对称加密,密钥长度 256 位,分组模式 GCM,消息认证和随机数生成使用摘要算法 SHA384。

对称加密与非对称加密

前面提到四个实现安全的必要条件,先说 机密性,也就是消息只能给想给的人看到并且看得懂。

实现机密性的手段就是 加密(encrypt),也就是将原本明文消息使用加密算法转换成别人看不懂的密文,只有掌握特有的 密钥 的人才能解密出原始内容。就好像是诸葛亮将发给关二爷密报的内容通过一种转换算法转成其他的内容,司马懿看不懂。关二爷持有解密该内容的关键钥匙。

钥匙也就是 密钥(key),未加密的消息叫做 明文 (plain text/clear text),加密后的内容叫做 密文(cipher text),通过密钥解密出原文的过程叫做 解密(decrypt),而加解密的整个过程就是 加密算法。

由于 HTTPS、TLS 都运行在计算机上,所以 " 密钥 " 就是一长串的数字,但约定俗成的度量单位是 " 位 "(bit),而不是 " 字节 "(byte)。比如,说密钥长度是 128,就是 16 字节的二进制串,密钥长度 1024,就是 128 字节的二进制串。

加密算法通常有两大类:对称加密和非对称加密。

对称加密

加密和解密使用的密钥都是同一个,是 " 对称的 "。双方只要保证不会有泄露其他人知道这个密钥,通信就具有机密性。


对称加密算法常见的有 RC4、DES、3DES、AES、ChaCha20 等,但前三种算法都被认为是不安全的,通常都禁止使用,目前常用的只有 AES 和 ChaCha20。


AES 的意思是 " 高级加密标准 "(Advanced Encryption Standard),密钥长度可以是 128、192 或 256。它是 DES 算法的替代者,安全强度很高,性能也很好,而且有的硬件还会做特殊优化,所以非常流行,是应用最广泛的对称加密算法。

加密分组模式

对称算法还有一个 " 分组模式 " 的概念,目的是通过算法用固定长度的密钥加密任意长度的明文。

最新的分组模式被称为 AEAD(Authenticated Encryption with Associated Data),在加密的同时增加了认证的功能,常用的是 GCM、CCM 和 Poly1305。

非对称加密

有对称加密,为何还搞出一个非对称加密呢?

对称加密确实解决了机密性,只有相关的人才能读取出信息。但是最大的问题是:如何安全的把密钥传递对方,专业术语 " 密钥交换 "。

这个很容易理解,对称加密的密钥在飞鸽传书过程中被打鸟的敌军捕获窃取,那

么就能随意加解密收发作战密报数据了,诸葛亮的密报没有机密可言。

所以非对称加密诞生了。

由两个密钥组成,分别是 公钥(public key) 和 " 私钥(private key)",两个密钥是不一样的,这也就是不对称的由来,公钥可以任何人使用,私钥则自己保密。

这里需要注意的是:公钥和私钥都可以用来加密解密,公钥加密的密文只能用私钥解密,反之亦然。

服务端保存私钥,在互联网上分发公钥,当访问服务器网站的时候使用授予的公钥加密明文即可,服务端则使用对应的私钥来解密。敌军没有私钥也就无法破解密文了。


非对称加密


TLS 中常见的加密算法有 DH、RSA、ECC、DSA 等。其中的 RSA 最常用,它的安全性基于 " 整数分解 " 的数学难题,使用两个超大素数的乘积作为生成密钥的材料,想要从公钥推算出私钥是非常困难的。

ECC(Elliptic Curve Cryptography)是非对称加密里的 " 后起之秀 ",它基于 " 椭圆曲线离散对数 " 的数学难题,使用特定的曲线方程和基点生成公钥和私钥,子算法 ECDHE 用于密钥交换,ECDSA 用于数字签名。

比起 RSA,ECC 在安全强度和性能上都有明显的优势。160 位的 ECC 相当于 1024 位的 RSA,而 224 位的 ECC 则相当于 2048 位的 RSA。因为密钥短,所以相应的计算量、消耗的内存和带宽也就少,加密解密的性能就上去了,对于现在的移动互联网非常有吸引力。

现在我们为了机密性从对称加密到非对称加密,而非对称加密还解决了密钥交换不安全的问题。那么是否可以直接使用非对称加密来实现机密性呢?

答案是否定的!

因为非对称加密运算速度比较慢。所以需要两者结合,混合模式实现机密性问题,同时又有很好的性能。

加密流程如下所示:

先创建一个随机数的对称加密密钥,会话密钥(session key);

使用会话密钥加密需要传输的明文消息,因为对称加密性能较好,接着再使用非对称加密的公钥对会话密钥加密,因为会话密钥很短,通常只有 16 字节或 32 字节,所以加密也不会太慢。这里主要就是解决了非对称加密的性能问题,同时实现了会话密钥的机密交换。

另一方接收到密文后使用非对称加密的私钥解密出上一步加密的 会话密钥,接着使用会话密钥解密出加密的消息明文。


混合加密


总结一下就是使用非对称加密算法来加密会话密钥,使用对称加密算法来加密消息明文,接收方则使用非对称加密算法的私钥解密出会话密钥,再利用会话密钥解密消息密文。

这样混合加密就解决了对称加密算法的密钥交换问题,而且安全和性能兼顾,完美地实现了机密性。

后面还有完整性、身份认证、不可否认等特性没有实现,所以现在的通信还不是绝对安全。

摘要算法与完整性

摘要算法的主要目的就是实现完整性,通过常见的散列函数、哈希函数实现。

我们可以简单理解成这事一种特殊的压缩算法,将任意长度的明文数据处理成固定长度、又是独一无二的 " 摘要 " 字符串,就是该数据的指纹。

同时摘要算法是单向加密算法,没有密钥,加密后的数据也无法解密,也就是不能从 " 摘要 " 推导出明文。

比如我们听过或者用过的 MD5(Message-Digest 5)、SHA-1(Secure Hash Algorithm 1),它们就是最常用的两个摘要算法,能够生成 16 字节和 20 字节长度的数字摘要。

完整性实现

有了摘要算法生成的数字摘要,那么我们只需要在明文数据附上对应的摘要,就能保证数据的完整性。

但是由于摘要算法不具有机密性,不能明文传输,否则黑客可以修改消息后把摘要也一起改了,网站还是鉴别不出完整性。

所以完整性还是要建立在机密性上,我们结合之前提到的混合加密使用 " 会话密钥 " 加密明文消息 + 摘要,这样的话黑客也就无法得到明文,无法做修改了。这里有个专业术语叫 " 哈希消息认证码(HMAC)"。


哈希消息认证码(HMAC)


比如诸葛亮使用上面提到的混合加密过程给关二爷发消息:" 明天攻城 " + "SHA-

2 摘要 ",关二爷收到后使用密钥将解密出来的会话密钥解密出明文消息,同时对明文消息使用解密出来的摘要算法进行摘要计算,接着比对两份 " 摘要 " 字符串是否一致,如果一致就说明消息完整可信,没有被敌军修改过。

消息被修改是很危险的,要以史为鉴,比如赵高与李斯伪造遗诏,直接把扶苏给送西天了,这太可怕了。

总结下就是通过摘要比对防止篡改,同时利用混合加密实现密文与摘要的安全传输。

数字签名和 CA

到这里已经很安全了,但是还是有漏洞,就是通信的两头。黑客可以伪装成网站来窃取信息。而反过来,他也可以伪装成你,向网站发送支付、转账等消息,网站没有办法确认你的身份,钱可能就这么被偷走了。

现在如何实现身份认证呢?

现实生活中,解决身份认证的手段是签名和印章,只要在纸上写下签名或者盖个章,就能够证明这份文件确实是由本人而不是其他人发出的。

非对称加密依然可以解决此问题,只不过跟之前反过来用,使用私钥再加上摘要算法,就能够实现 " 数字签名 ",同时实现 " 身份认证 " 和 " 不可否认 "。

就是把公钥私钥的用法反过来,之前是公钥加密、私钥解密,现在是私钥加密、公钥解密。但又因为非对称加密效率太低,所以私钥只加密原文的摘要,这样运算量就小的多,而且得到的数字签名也很小,方便保管和传输。

重点就是使用非对称加密的 " 私钥 " 加密原文的摘,对方则使用非对称加密的公钥解密出摘要,再比对解密出的原文通过摘要算法计算摘要与解密出的摘要比对是否一致。这样就能像签署文件一样证明消息确实是你发送的。


签名验签


只要你和网站互相交换公钥,就可以用 " 签名 " 和 " 验签 " 来确认消息的真实性,因为私钥保密,黑客不能伪造签名,就能够保证通信双方的身份。

到这里似乎已经大功告成,可惜还不是。

综合使用对称加密、非对称加密和摘要算法,我们已经实现了安全的四大特性,是不是已经完美了呢?

不是的,这里还有一个 " 公钥的信任 " 问题。因为谁都可以发布公钥,我们还缺少防止黑客伪造公钥的手段,也就是说,怎么来判断这个公钥就是你或者张三丰的公钥呢?

这个 " 第三方 " 就是我们常说的 CA(Certificate Authority,证书认证机构)。它就像网络世界里的公安局、教育部、公证中心,具有极高的可信度,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的。

CA 对公钥的签名认证也是有格式的,不是简单地把公钥绑定在持有者身份上就完事了,还要包含序列号、用途、颁发者、有效时间等等,把这些打成一个包再签名,完整地证明公钥关联的各种信息,形成 " 数字证书 "(Certificate)。

OpenSSL

它是一个著名的开源密码学程序库和工具包,几乎支持所有公开的加密算法和协议,已经成为了事实上的标准,许多应用软件都会使用它作为底层库来实现 TLS 功能,包括常用的 Web 服务器 Apache、Nginx 等。

由于 OpenSSL 是开源的,所以它还有一些代码分支,比如 Google 的 BoringSSL、OpenBSD 的 LibreSSL,这些分支在 OpenSSL 的基础上删除了一些老旧代码,也增加了一些新特性,虽然背后有 " 大金主 ",但离取代 OpenSSL 还差得很远。

总结下就是:OpenSSL 是著名的开源密码学工具包,是 SSL/TLS 的具体实现。

迁移 HTTPS 必要性

如果你做移动应用开发的话,那么就一定知道,Apple、Android、某信等开发平台在 2017 年就相继发出通知,要求所有的应用必须使用 HTTPS 连接,禁止不安全的 HTTP。

在台式机上,主流的浏览器 Chrome、Firefox 等也早就开始 " 强推 "HTTPS,把 HTTP 站点打上 " 不安全 " 的标签,给用户以 " 心理压力 "。

Google 等搜索巨头还利用自身的 " 话语权 " 优势,降低 HTTP 站点的排名,而给 HTTPS 更大的权重,力图让网民只访问到 HTTPS 网站。

这些手段都逐渐 " 挤压 " 了纯明文 HTTP 的生存空间," 迁移到 HTTPS" 已经不是 " 要不要做 " 的问题,而是 " 要怎么做 " 的问题了。HTTPS 的大潮无法阻挡,如果还是死守着 HTTP,那么无疑会被冲刷到互联网的角落里。

顾虑

阻碍 HTTPS 实施的因素还有一些这样、那样的顾虑,我总结出了三个比较流行的观点:" 慢、贵、难 "。

而 " 慢 " 则是惯性思维,拿以前的数据来评估 HTTPS 的性能,认为 HTTPS 会增加服务器的成本,增加客户端的时延,影响用户体验。

其实现在服务器和客户端的运算能力都已经有了很大的提升,性能方面完全没有担心的必要,而且还可以应用很多的优化解决方案。

所谓 " 贵 ",主要是指证书申请和维护的成本太高,网站难以承担。

这也属于惯性思维,在早几年的确是个问题,向 CA 申请证书的过程不仅麻烦,而且价格昂贵,每年要交几千甚至几万元。

但现在就不一样了,为了推广 HTTPS,很多云服务厂商都提供了一键申请、价格低廉的证书,而且还出现了专门颁发免费证书的 CA,其中最著名的就是 "Let ’ s Encrypt"。

所谓的 " 难 ",是指 HTTPS 涉及的知识点太多、太复杂,有一定的技术门槛,不能很快上手。

总结

从什么是安全我们延展出 HTTPS,解释了什么是 HTTPS,以及与 HTTP 的区别。HTTPS 主要就是通过 SSL/TLS 实现安全,而安全我们又接触了什么是对称加密与非对称加密,非对称加密性能较弱,所以我们使用非对称加密来加密对称加密的 " 会话密钥 ",利用会话密钥加密明文解决了性能问题。

通过混合加密实现了机密性,利用摘要算法实现了完整性,通过数字签名使用非对称加密的 " 私钥 " 加密原文的摘要,对方则使用非对称加密的公钥解密出摘要,再比对解密出的原文通过摘要算法计算摘要与解密出的摘要比对是否一致实现了身份认证与不可否认。


文章来源于码哥字节 ,作者 MageByte 技术团队

Redis 在 MySql 中的优化历程

技术交流梅川酷子 发表了文章 • 0 个评论 • 63 次浏览 • 2020-09-14 10:30 • 来自相关话题

我是Redis你好,我是Redis,一个叫Antirez的男人把我带到了这个世界上。说起我的诞生,跟关系数据库MySQL还挺有渊源的。在我还没来到这个世界上的时候,MySQL过的很辛苦,互联网发展的越来越快,它容纳的数据也越来越多,用户请求也随之暴涨,而每一个... ...查看全部

我是Redis
你好,我是Redis,一个叫Antirez的男人把我带到了这个世界上。2.png

说起我的诞生,跟关系数据库MySQL还挺有渊源的。在我还没来到这个世界上的时候,MySQL过的很辛苦,互联网发展的越来越快,它容纳的数据也越来越多,用户请求也随之暴涨,而每一个用户请求都变成了对它的一个又一个读写操作,MySQL是苦不堪言。尤其是到“双11”、“618“这种全民购物狂欢的日子,都是MySQL受苦受难的日子。据后来MySQL告诉我说,其实有一大半的用户请求都是读操作,而且经常都是重复查询一个东西,浪费它很多时间去进行磁盘I/O。后来有人就琢磨,是不是可以学学CPU,给数据库也加一个缓存呢?于是我就诞生了!出生不久,我就和MySQL成为了好朋友,我们俩常常携手出现在后端服务器中。应用程序们从MySQL查询到的数据,在我这里登记一下,后面再需要用到的时候,就先找我要,我这里没有再找MySQL要。

3.png

为了方便使用,我支持好几种数据结构的存储:

  • String

  • Hash

  • List

  • Set

  • SortedSet

  • Bitmap

  • ······

因为我把登记的数据都记录在内存中,不用去执行慢如蜗牛的I/O操作,所以找我要比找MySQL要省去了不少的时间呢。可别小瞧这简单的一个改变,我可为MySQL减轻了不小的负担!随着程序的运行,我缓存的数据越来越多,有相当部分时间我都给它挡住了用户请求,这一下它可乐得清闲自在了!有了我的加入,网络服务的性能提升了不少,这都归功于我为数据库挨了不少枪子儿。

缓存过期 && 缓存淘汰
不过很快我发现事情不妙了,我缓存的数据都是在内存中,可是就算是在服务器上,内存的空间资源还是很有限的,不能无节制的这么存下去,我得想个办法,不然吃枣药丸。不久,我想到了一个办法:给缓存内容设置一个超时时间,具体设置多长交给应用程序们去设置,我要做的就是把过期了的内容从我里面删除掉,及时腾出空间就行了。

4.png

超时时间有了,我该在什么时候去干这个清理的活呢?最简单的就是定期删除,我决定100ms就做一次,一秒钟就是10次!我清理的时候也不能一口气把所有过期的都给删除掉,我这里面存了大量的数据,要全面扫一遍的话那不知道要花多久时间,会严重影响我接待新的客户请求的!时间紧任务重,我只好随机选择一部分来清理,能缓解内存压力就行了。

5.png

就这样过了一段日子,我发现有些个键值运气比较好,每次都没有被我的随机算法选中,每次都能幸免于难,这可不行,这些长时间过期的数据一直霸占着不少的内存空间!气抖冷!我眼里可揉不得沙子!于是在原来定期删除的基础上,又加了一招:那些原来逃脱我随机选择算法的键值,一旦遇到查询请求,被我发现已经超期了,那我就绝不客气,立即删除。这种方式因为是被动式触发的,不查询就不会发生,所以也叫惰性删除!可是,还是有部分键值,既逃脱了我的随机选择算法,又一直没有被查询,导致它们一直逍遥法外!而于此同时,可以使用的内存空间却越来越少。

6.png

而且就算退一步讲,我能够把过期的数据都删除掉,那万一过期时间设置的很长,还没等到我去清理,内存就吃满了,一样要吃枣药丸,所以我还得想个办法。我苦思良久,终于憋出了个大招:内存淘汰策略,这一次我要彻底解决问题!我提供了8种策略供应用程序选择,用于我遇到内存不足时该如何决策:

  • noeviction:返回错误,不会删除任何键值

  • allkeys-lru:使用LRU算法删除最近最少使用的键值

  • volatile-lru:使用LRU算法从设置了过期时间的键集合中删除最近最少使用的键值

  • allkeys-random:从所有key随机删除

  • volatile-random:从设置了过期时间的键的集合中随机删除

  • volatile-ttl:从设置了过期时间的键中删除剩余时间最短的键

  • volatile-lfu:从配置了过期时间的键中删除使用频率最少的键

  • allkeys-lfu:从所有键中删除使用频率最少的键

有了上面几套组合拳,我再也不用担心过期数据多了把空间撑满的问题了~

缓存穿透 && 布隆过滤器
我的日子过的还挺舒坦,不过MySQL大哥就没我这么舒坦了,有时候遇到些烦人的请求,查询的数据不存在,MySQL就要白忙活一场!不仅如此,因为不存在,我也没法缓存啊,导致同样的请求来了每次都要去让MySQL白忙活一场。我作为缓存的价值就没得到体现啦!这就是人们常说的缓存穿透

7.png

这一来二去,MySQL大哥忍不住了:“唉,兄弟,能不能帮忙想个办法,把那些明知道不会有结果的查询请求给我挡一下”这时我想到了我的另外一个好朋友:布隆过滤器

8.png

我这位朋友别的本事没有,就擅长从超大的数据集中快速告诉你查找的数据存不存在(悄悄告诉你,我的这位朋友有一点不靠谱,它告诉你存在的话不能全信,其实有可能是不存在的,不过它他要是告诉你不存在的话,那就一定不存在)。

9.png

如果你对我这位朋友感兴趣的话,可以看看这里《白话布隆过滤器BloomFilter》。我把这位朋友介绍给了应用程序,不存在的数据就不必去叨扰MySQL了,轻松帮忙解决了缓存穿透的问题。

缓存击穿 && 缓存雪崩
这之后过了一段时间太平日子,直到那一天···有一次,MySQL那家伙正优哉游哉的摸鱼,突然一大堆请求给他怼了过去,给他打了一个措手不及。一阵忙活之后,MySQL怒气冲冲的找到了我,“兄弟,咋回事啊,怎么一下子来的这么猛”

10.png

我查看了日志,赶紧解释到:“大哥,实在不好意思,刚刚有一个热点数据到了过期时间,被我删掉了,不巧的是随后就有对这个数据的大量查询请求来了,我这里已经删了,所以请求都发到你那里来了”“你这干的叫啥事,下次注意点啊”,MySQL大哥一脸不高兴的离开了。这一件小事我也没怎么放在心上,随后就抛之脑后了,却没曾想几天之后竟捅了更大的篓子。那一天,又出现了大量的网络请求发到了MySQL那边,比上一次的规模大得多,MySQL大哥一会儿功夫就给干趴下了好几次!等了好半天这一波流量才算过去,MySQL才缓过神来。“老弟,这一次又是什么原因?”,MySQL大哥累的没了力气。“这一次比上一次更不巧,这一次是一大批数据几乎同时过了有效期,然后又发生了很多对这些数据的请求,所以比起上一次这规模更大了”

11.png

MySQL大哥听了眉头一皱,“那你倒是想个办法啊,三天两头折磨我,这谁顶得住啊?”“其实我也很无奈,这个时间也不是我设置的,要不我去找应用程序说说,让他把缓存过期时间设置的均匀一些?至少别让大量数据集体失效”“走,咱俩一起去”后来,我俩去找应用程序商量了,不仅把键值的过期时间随机了一下,还设置了热点数据永不过期,这个问题缓解了不少。哦对了,我们还把这两次发生的问题分别取了个名字:缓存击穿和缓存雪崩。我们终于又过上了舒适的日子···

彩蛋

那天,我正在努力工作中,不小心出了错,整个进程都崩溃了。当我再次启动后,之前缓存的数据全都没了,暴风雨似的请求再一次全都怼到了MySQL大哥那里。唉,要是我能够记住崩溃前缓存的内容就好了···预知后事如何,请关注后续精彩······



作者 | 轩辕之风O

来源 公众号 | 编程技术宇宙

刚刚用鸿蒙跑了个“hello world”!跑通后,我特么开始怀疑人生了....

技术交流大兴 发表了文章 • 0 个评论 • 69 次浏览 • 2020-09-14 10:18 • 来自相关话题

最近华为鸿蒙OS 2.0正式开源!关于鸿蒙的教程其实网上也已经有一些尝鲜的小伙伴分享的相关文章了,编者我按照步骤一步步跑下来,整个流程还是非常简单的,尤其是对Android开发的小伙伴来说,从IDE到项目的创建及项目的编译安装简直是一模一样呀。我特么的都有点怀... ...查看全部

最近华为鸿蒙OS 2.0正式开源!关于鸿蒙的教程其实网上也已经有一些尝鲜的小伙伴分享的相关文章了,编者我按照步骤一步步跑下来,整个流程还是非常简单的,尤其是对Android开发的小伙伴来说,从IDE到项目的创建及项目的编译安装简直是一模一样呀。我特么的都有点怀疑人生了...感兴趣的读者也可以试试哦。

再贴一下鸿蒙的源码地址:https://openharmony.gitee.com

咱们一起来跟着一位网友学习一下如何跑起来第一个“hello world”,原文如下:

1.前序

1.1 官网:

https://www.harmonyos.com 网上搜索第一个不是官方是三方的

1.2.IDE下载位置:

源码编译的下载: https://device.harmonyos.com/cn/ide 

开发应用的下载:https://developer.harmonyos.com/cn/develop/deveco-studio#download

1.3.源码位置:

https://device.harmonyos.com/cn/docs/start/get-code/oem_sourcecode_guide-0000001050769927

2. 开发应用部分

2.1 安装时候启动会提示下载SDK,点击取消,搜索SDK,重新自定义SDK路径。


我把所有的SDK都按照上,打勾会自动下载。

2.2 创建的项目

点击创建项目,发现现在支持有三种类型

2.2.1 TV 设备应用

2.2.2 Wearable 可穿戴设备应用

2.2.3 Lite Wearable 可穿戴设备(Lite)应用

2.2.4 创建TV项目 (Java),选了一个列表模板。

创建中:

下载gradle-5.4.1-all.zip慢得等等。( 默认下载到: 

这个应该有办法直接下载好

设置里面很全面都能进行设置,可以探索探索 ) grade 源已经正确的切换到华为国内

2.2.5 下载模拟器

弹窗点击确认就可以下载了 (此处下载速度略慢,下载失败点击 downloadagain 继续下载 估计下载人太多,失败了十几次把)


刷新以后:

使用自己的华为账号登录(此处注意有坑,如果默认使用Chrome可能授权会失败,使用Windows自带的浏览器进行登录)

(开发者账号实名认证,我填写的是银行卡验证速度很快) 

进行授权:

授权成功:

同意协议:

罗列了可用的模拟器:

TV模拟器启动了

运行就可以看到模拟器了

运行成功:


友情链接