Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 11850 articles
Browse latest View live

别让自己“墙”了自己

$
0
0

这一两周与几个朋友聊天,有年轻的90后,也有大叔级的70后,这些人在我看来都是很有能力的人,但是一些喜好过于强烈,让我不经意地回顾了我工作20年来身边的人,有发展得好的,也有发展的不好的,有些人是很可惜的,因为限制他们的不是其它人,也不是环境,而是自己,所以,很想写下这篇文章。(注:这篇文章可能会是一篇说教的文章,所以,可能会让你看着犯困,所以,我会尽量地短一些,而且尽可能多讲故事,少道理,这里的故事,全是真实发生的)

几个故事

2019年年初,我面试了一个很年轻的小伙子(93/94年出生),这个小伙子特别有灵性,也很聪明,计算机专业出生,也很喜欢技术,基础和学习能力也很好。在我这20年来认识的人中,如果他能呆在北京、上海、深圳这样的城市,我保证不出三年,他会成为他们同龄人中非常出色的技术人员,如果有个好的舞台有一个好的团队带他,他的未来会非常成功。然而,这个小伙子有两大喜好:1)只愿呆在一个毫无IT的环境的三/四线城市,2)对技术有非常大的偏好,只喜欢Go语言,非常不喜欢其它的语言,比如:Java(离开Java的世界,基本上离开了做架构的世界)。

他的这两个喜好,足以让一个未来会很优秀的人毁掉,因为,这个时代没有限制他,他的能力也没有限制他,但是他的意识完完全全地限制了他。

  • 他把自己最宝贵的青春放在了很烂的项目上,就算能用一些新的技术,他也只能算是自娱自乐,在实验室中玩玩具罢了。
  • 他把自己的技术栈封闭起来,而直接放弃了这个时代最具工业化的技术Java,对于一个好的程序员来说,同时掌握几门语言和技术完全是没什么问题,但是自己封闭了自己的视野。

实在是非常可惜,我本来是可以为他介绍到一些很不错的公司的,但是他这样的习性,等于自己把自己未来的门给关上了,虽然我跟他长谈过,但是我也没有办法叫醒不想醒的人……

  • 视野、环境和舞台,对一个人的限制是非常大的。井蛙不知道大海,被空限维度所限制;夏虫不知道冬天,是被时间维度所限制;圈奍的动物没有斗志,是被自己意识所限制。
  • 偏见和不开放,对一个人的限制是真正有毁灭性的。主动让自己成为一个瞎子和聋子,主动把自己的能力阉割掉,这是一件令人痛心的事。想想大清的闭关锁国是如何让世界第一的北洋水师给毁掉的……

我还有个同学,他的技术并不差,就算呆在昆明这种很落后的地方,他也非常地好学,学习英文,学习各种新技术,对技术没有任何的偏好,喜欢C/C++/Java/Python/Shell,同样喜欢前端Javascript,对基础知识非常地踏实,他在技术上没有限制自己的潜力,有什么就学什么。后来,我带他玩Docker/Go/K8S……分布式架构,他也上手的很快……像他这样的人,技术能力完全没得说,比我还大一岁,44岁了,还是一样的天天追代码细节,看Youtube的各种大会,翻github里的各种issue和pull request……

我同学这人,拥有了成为一个技术牛人几乎的条件:基础知识过硬,细节扎得深,面很广,学习能力强,有英文能力,逻辑思维能力不错,非常的自律,执行力也很强,抓得住重点……然而,只有一个小问题,就是没有到大公司历练过,我三番五次叫他从昆明出来,但是最终他都呆在昆明这个城市没有出来,因为有所谓的家庭约束。然而,我身边还有好些人,把自己家从北京搬到上海,从上海搬到深圳,从厦门搬到深圳……这样的人大有人在……像他这样的能力,在哪个公司都会是主力和骨干,对于一个公司的主力和骨干来说,家庭上的这些问题都是小问题都是有很多解的……

另外,我这个同学还是一个比较悲观的人,任何事情都是先想到不好的事,他关注负面的东西会胜于正面的东西,而且他还有一定的社交恐惧,怕与人相处和交流,时间越长越害怕,甚至有时候直接跟我说,“我就是不想改变”这样的话……其实,我以前也是一个很害怕与人交流的人,面试的时候,我根本不敢正眼看面试官一眼,也不知道与人怎么交流。但是,我与他不一样,我努力克服,不断地面试,与人面对面的交流,到一线技术客服接用户的电话,在公司里做分享,慢慢地到外面分享……3-5年就完全克服掉了。

其实,很多事情,完全是有解的,也没有必要担心,自己的心理障碍也是可以克服的,重点就是自己愿不愿意,只要愿意完成了一半,接下来就是不断的摸爬滚打坚持了。

  • 不限制自己的人,会穷举各种方法来解决问题,限制自己的人,只会找各式各样的问题或借口。
  • 不限制自己的人,会努力改变自己的问题和缺陷,限制自己的人,会放任自己。

另外几个故事

我还有另外几个故事(活到四十多,能看到好多人十几年的发展过程,感觉有点上帝视角了)

我还有一个以前团队里的一个小伙,人是很聪明,但就完全就是野路子,他对技术没有什么偏好,一个PHP程序员,做那个Discuz!论坛,公司被并购了,转成Java,开始研究Java的各种细节,对技术从来没有什么偏见,有什么就玩什么,每做一个项目,就算是一样的他都要用新的技术做一遍,然后跟着我做云计算,我教他TCP,教他C/C++,后来一起玩Docker/Go,等等,反正是一点就通,他是我见过学习能力最强的人。但是,有一个事他一直与我的想法不一样,就是我希望他先把软件设计好,再写代码,他非常不能理解,他习惯于直接动手开干,然后有什么问题就整什么问题,我也很难教育他。

有一天,他电话面了一下Facebook,电话面了15分钟后对方就放弃了,他受到了严重的打击。然后,他就开始找菲利宾人练英文口语了,我也让他做算法题,然后,他才发现,一道连算法都不是的纯编程题都提交几次都过不了,等他做完了Leetcode最初的那151道题后,整个人都改变了,写代码前认认真真地在纸上把程序的状态,处理时序以及可能遇到的一些条件先罗列出来,然后,进行逻辑设计后,再写,从此,他就开启他更大的天地了。我后来把他推荐给了微软,先在中国的Bing,在中国升好2-3级,然后去了美国的Azure,现在听说他准备要跟 k8s 的 co-founder Brendan Burns混了(虽然,他现在还在印度人手下,但是,我真的不知道他未来能玩多大,因为今年他才33岁,而且非常聪明)

他以前是把自己封闭起来的,我叫他出来,他也不出来,后来因为一些办公室政治的原因不得不来找我,于是我就带着他玩了两年,跟他讲了很多外面的世界是怎么玩的,他这个人也是一个相当不善于社交的人,但是心是开放的,愿意接受新的东西,虽然对技术也有一定偏见,比如不喜欢Windows,但是也不会不喜欢到完全封闭。后来我跟他说,微软的技术相当的强的,你看到的技术只是表面,深层次的东西都是相通的,直到他到了微软后发现各种牛逼的东西,对微软系统的技术的态度也有了改变,而且我让他跟我说很多微软那边的事,我发现,他对技术了解的维度已经是越来越高级的了……

还是我以前团队的一个小伙,他是一个前端,他说前端的东西没什么意思,想来找我做后端,我也一点点带他……后来,我说,你如果想要玩得好,你必需来北京,无论现在你觉得过得有多好,你都要放弃掉,然后,尽最大可能出去经历一下世界最顶尖的公司,我甚至跟他说,如果他女朋友不跟来的话,就先分开一段时间,先自己立业,他来北京的时候,他之前的同事都等着看他的笑话,我说,那些人连想都不敢想,不必管他们。于是,他去了Amazon,再过了一年去了西雅图,我跟他说,接下来就是去AWS,然后,如果有足够的野心,用自己的年轻这个资本去硅谷创业公司赌一把……未来他怎么样我不知道,但至少他没有限制自己,他的未来不会有封顶……

也是我的同学,我跟他在大学是上下铺,后来他去了人民大学读计算机博士,大学的时候做国产数据库kingbase,然后去了一家外企,天天被派到用户那边做数据分析,后来,他想回科研单位做国产数据库,我说,别啊,你的技术比我好太多,还有博士理论加持,你不去国外顶尖公司玩玩,你不知道自己有多强的,于是他跟公司申请去了国外做核心,后来因为Hadoop的原因,公司的产品最终成为了历史,于是我说,你来了美国么,你一定要去AWS,于是他就去了AWS的Aurora团队,成为了AWS明星级产品的中坚力量,天天在改MySQL的核心源码,干了两年,被提升为Principle Software Engineer ……

这里我到不是说出国有多牛,也许你只关注能挣多少钱,但是我想说,他们之所以能有这样的际遇,除了他们本来就有实力,还更因为他们从来不给自己设制什么限制,就是那种“艺多不压身”,有什么就学什么,有更高的就去向更高的迈进,其它的像家庭什么的问题其实都是会有解的,真的不必担心太多……

 别限制了自己

上面的这些故事,也许你能看得懂,也许你看得不一定能懂,这里,让我来做个总结吧

  • 做有价值的事。这个世界对计算机人才的要求是供不应求的,所以,不要让自己为自己找各式各样的借口,让自己活在“玩玩具”、“搬砖”和“使蛮力加班”的境地。其实,我发现这世界上有能力的人并不少,但是有品味的人的确很少。 所谓的有价值,就是,别人愿付高价的,高技术门槛的,有创造力的,有颠覆性的……
  • 扩大自己的眼界,开放自己的内心。人要变得开放,千万不要做一个狭隘的民族主义者,做一个开放的人,把目光放在全人类这个维度,不断地把自己融入到世界上,而不是把自己封闭起来,这里, 你的英文语言能力对你能不能融入世界是起决定性的作用。开放自己的心态,正视自己的缺点,你才可能往前迈进。 你的视野决定了你的知不知道要去哪,你的开放决定了你想不想去
  • 站在更高的维度。面的维度会超过点的维点,空间的维度会超过面的维度,在更高维度上思考和学习,你会获得更多。 整天在焦虑那些低维度的事(比如自己的薪水、工作的地点、稳不稳定、有没有户口……),只会让你变得越来越平庸,只要你站在更高的维度(比如: 眼界有没有扩大、可能性是不是更多、竞争力是不是更强、能不能解决更大更难的问题、能创造多大的价值……),时间会让你明白那些低维度的东西全都不是事儿。技术学习上也一样,站在学习编程语法特性的维度和站在学习编程范式、设计模式的维度是两种完全不一样的学习方式。
  • 精于计算得失。很多人其实不是很懂计算。绝大多数人都是在算计自己会失去多少,而不会算会得到多少。而一般的人也总是在算短期内会失去什么,优秀则总是会算我投入后未来会有什么样的回报,前者在算计今天,目光短浅,而后者则是舍在今天,得在明天,计算的是未来。 精于计算得失的,就懂得什么是投资,不懂的只会投机。对于赚钱,你可以投机,但是对于自己最好还是投资。
  • 勇于跳出传统的束缚。有时候,跳出传统并不是一件很容易的事,因为大多数人都会对未知有恐惧的心理。比如:我看到很多人才都被大公司垄断了,其实,有能力的人都不需要加入大公司,有能力的人是少数,这些少数的人应该是所有的公司share着用的,这样一来,对于所有的人都是利益最大化的。这样的事现在也有,比如:律师、设计师……。但是,绝大多数有能力的技术人员是不敢走出这步。我在2015年到2016年实践过一年半,有过这些实践,做“鸡”的比“二奶”好多了,收入也好很多很多(不好意思开车了)……

庄子说过几句话——

井蛙不可以语于海者,拘于虚也;//空间局限

夏虫不可以语于冰者,笃于时也;//时间局限

曲士不可以语于道者,束于教也。//认识局限

别自己墙了自己,人最可悲的就是自己限制自己,想都不敢想,共勉!

(全文完)


关注CoolShell微信公众账号和微信小程序

(转载本站文章请注明作者和出处 酷 壳 – CoolShell,请勿用于任何商业用途)

——=== 访问 酷壳404页面寻找遗失儿童。 ===——

分布式应用框架 Dapr

$
0
0

微服务架构已成为构建云原生应用程序的标准,微服务架构提供了令人信服的好处,包括可伸缩性,松散的服务耦合和独立部署,但是这种方法的成本很高,需要了解和熟练掌握分布式系统。为了使用所有开发人员能够使用任何语言和任何框架轻松地构建便携式微服务应用程序,无论是开发新项目还是迁移现有代码

Dapr 介绍

Github:  https://github.com/dapr/dapr

Dapr是一种可移植的,事件驱动的,无服务器运行时,用于构建跨云和边缘的分布式应用程序。

Distributed Application Runtime. An event-driven, portable runtime for building microservices on cloud and edge.

其中提到了多语言和多开发者框架,我认为这是他选择的通过通信共享信息,即  HTTP 和  GRPC 支持多语言等特性。微软想通过这个设定一个构建微服务应用的规则。从根本上确立你开发的每一个应用的独立性。赋能每个开发者,为了使Dapr对于不同的语言更加方便,它还包括针对Go,Java,JavaScript,.NET和Python的语言特定的SDK。这些SDK通过类型化的语言API(而不是调用http / gRPC API)公开了Dapr构建块中的功能,例如保存状态,发布事件或创建actor。这使开发人员可以使用他们选择的语言编写无状态和有状态功能以及参与者的组合。并且由于这些SDK共享Dapr运行时,您甚至可以获得跨语言的actor和功能支持!

Dapr还可以与任何开发人员框架集成。例如,在Dapr .NET SDK中,您将找到ASP.NET Core集成,该集成带来了可响应其他服务的发布/订阅事件的状态路由控制器,从而使ASP.NET Core成为构建微服务Web应用程序的更好框架。  

不过需要注意的是Dapr目前正处于Alpha阶段, 今天刚发布了0.2版本。在v1.0稳定版本发布之前,建议不要用于生产环境。 

下面进行一个 QuickStart

环境

  1. Install Docker(微服务已经离不开容器化了)

  2. Install Dapr CLI

  3. Install .Net Core SDK 3.0

在Windows 上通过Powershell 安装:

powershell -Command "iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1 | iex"
然后把 c:\dapr 添加到环境变量 PATH
运行dapr命令,检查输出是否正常

C:\workshop\Github\dotnet-sdk>dapr --help

         __
     ____/ /___ _____  _____
    / __  / __ '/ __ \/ ___/
   / /_/ / /_/ / /_/ / /    
   \__,_/\__,_/ .___/_/
               /_/

======================================================
A serverless runtime for hyperscale, distributed systems

Usage:
   dapr [command]

Available Commands:
   help        Help about any command
   init        Setup dapr in Kubernetes or Standalone modes
   list        List all dapr instances
   publish     publish an event to multiple consumers
   run         Launches dapr and your app side by side
   send        invoke a dapr app with an optional payload
   stop        Stops a running dapr instance and its associated app
   uninstall   removes a dapr installation

Flags:
   -h, --help      help for dapr
       --version   version for dapr

Use "dapr [command] --help" for more information about a command.


执行初始化(会启动 docker 容器)
dapr init
Making the jump to hyperspace...
Downloading binaries and setting up components
Success! Dapr is up and running
下载.NET SDk代码
https://github.com/dapr/dotnet-sdk ,里面有.NET Core的多个示例代码:
示例描述
1. ActorDemonstrates creating virtual actors that encapsulate code and state. Also see docs in this repo for a tutorial.
2. ASP.NET CoreDemonstrates ASP.NET Core integration with Dapr by create Controllers and Routes.
3. gRPC client

The gRPC client sample shows how to make Dapr calls to publish events, save state, get state and delete state using a gRPC client.

我们一起来看下ASP.NET Core的Demo;

例子中主 我们使用  Dapr 的交互。Dapr通过  Runtime

  • 提供 Dapr API 给多语言调用。

  • 提供 状态管理 By state stores


/// <summary>
  /// Sample showing Dapr integration with controller.
  /// </summary>
  [ApiController]
  public class SampleController : ControllerBase
  {
      /// <summary>
      /// Gets the account information as specified by the id.
      /// </summary>
      /// <param name="account">Account information for the id from Dapr state store.</param>
      /// <returns>Account information.</returns>
      [HttpGet("{account}")]
      public ActionResult<Account> Get(StateEntry<Account> account)
      {
          if (account.Value is null)
          {
              return this.NotFound();
          }

         return account.Value;
      }


     /// <summary>
      /// Method for depositing to account as psecified in transaction.
      /// </summary>
      /// <param name="transaction">Transaction info.</param>
      /// <param name="stateClient">State client to interact with dapr runtime.</param>
      /// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
      [Topic("deposit")]
      [HttpPost("deposit")]
      public async Task<ActionResult<Account>> Deposit(Transaction transaction, [FromServices] StateClient stateClient)
      {
          var state = await stateClient.GetStateEntryAsync<Account>(transaction.Id);
          state.Value ??= new Account() { Id = transaction.Id, };
          state.Value.Balance += transaction.Amount;
          await state.SaveAsync();
          return state.Value;
      }


     /// <summary>
      /// Method for withdrawing from account as specified in transaction.
      /// </summary>
      /// <param name="transaction">Transaction info.</param>
      /// <param name="stateClient">State client to interact with dapr runtime.</param>
      /// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
      [Topic("withdraw")]
      [HttpPost("withdraw")]
      public async Task<ActionResult<Account>> Withdraw(Transaction transaction, [FromServices] StateClient stateClient)
      {
          var state = await stateClient.GetStateEntryAsync<Account>(transaction.Id);

         if (state.Value == null)
          {
              return this.NotFound();
          }

         state.Value.Balance -= transaction.Amount;
          await state.SaveAsync();
          return state.Value;
      }
  }


这里重点是状态存储,即将   state通过 StateClient 存储在   Dapr中,我们通过状态转移在   Dapr里实现了   stateless。
 
Dapr 运行.NET 应用程序

演示Dapr的服务调用,在终端中切换到项目目录,然后使用dapr启动应用


C:\workshop\Github\dotnet-sdk\samples\AspNetCore\ControllerSample>dapr run --app-id routing --app-port 5000 dotnet run    
Starting Dapr with id routing. HTTP Port: 61102. gRPC Port: 61103
You're up and running! Both Dapr and your app logs will appear here.


注意: 以上dapr run命令,通过app-id指定了应用的ID,通过app-port指定了应用的端口(webapi默认使用5000作为http端口),后跟dotnet run命名启动当前项目。可参考Dapr文档服务调用


后台运行的  CLI 命令,这里是前台打印的日志, 注意到 .NET  App 在指定的  5000 端口运行,同时还有状态存储的  redis 在  6379 端口运行


== DAPR == time="2019-11-16T18:33:22+08:00" level=info msg="starting Dapr Runtime -- version 0.2.0 -- commit c75b11
1-dirty"
     == DAPR == time="2019-11-16T18:33:22+08:00" level=info msg="log level set to: info"
== DAPR == time="2019-11-16T18:33:22+08:00" level=info msg="standalone mode configured"
== DAPR == time="2019-11-16T18:33:22+08:00" level=info msg="dapr id: routing"
== DAPR == time="2019-11-16T18:33:22+08:00" level=info msg="loaded component messagebus (pubsub.redis)"        
     == DAPR == time="2019-11-16T18:33:22+08:00" level=info msg="loaded component statestore (state.redis)"
     == DAPR == time="2019-11-16T18:33:22+08:00" level=info msg="application protocol: http. waiting on port 5000"
     == APP == info: Microsoft.Hosting.Lifetime[0]
     == APP ==       Now listening on: http://localhost:5000
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Application started. Press Ctrl+C to shut down.
     == APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Hosting environment: Development
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Content root path: C:\workshop\Github\dotnet-sdk\samples\AspNetCore\ControllerSample
     == DAPR == time="2019-11-16T18:33:31+08:00" level=info msg="application discovered on port 5000"
     == DAPR == 2019-11-16 18:33:32.029764 I | redis: connecting to localhost:6379
     == DAPR == 2019-11-16 18:33:32.036316 I | redis: connected to localhost:6379 (localAddr: [::1]:61164, remAddr: 
[::1]:6379)
     == DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. 
actor scan interval: 30s"
     == DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="actors: starting connection attempt to placement se
rvice at localhost:6050"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="http server is running on port 61102"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="gRPC server is running on port 61103"
     == DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="local service entry announced"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 917
6.5164ms"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="actors: established connection to placement service
  at localhost:6050"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="actors: placement order received: lock"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="actors: placement order received: update"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="actors: placement tables updated"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="actors: placement order received: unlock"
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[100]
== APP ==       Start processing HTTP request GET http://localhost:61102/v1.0/state/17
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[100]
== APP ==       Sending HTTP request GET http://localhost:61102/v1.0/state/17
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[101]
== APP ==       Received HTTP response after 2228.2998000000002ms - OK     
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[101]       
== APP ==       End processing HTTP request after 2257.3405000000002ms - OK
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[100]
== APP ==       Start processing HTTP request POST http://localhost:61102/v1.0/state
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[100]
== APP ==       Sending HTTP request POST http://localhost:61102/v1.0/state
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[101]
     == APP ==       Received HTTP response after 67.46000000000001ms - Created
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[101]
== APP ==       End processing HTTP request after 68.0343ms - Created
     == APP == info: System.Net.Http.HttpClient.state.LogicalHandler[100]
     == APP ==       Start processing HTTP request GET http://localhost:61102/v1.0/state/17
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[100]
== APP ==       Sending HTTP request GET http://localhost:61102/v1.0/state/17
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[101]
== APP ==       Received HTTP response after 5.8247ms - OK
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[101]
== APP ==       End processing HTTP request after 6.268400000000001ms - OK
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[100]
== APP ==       Start processing HTTP request POST http://localhost:61102/v1.0/state
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[100]
== APP ==       Sending HTTP request POST http://localhost:61102/v1.0/state
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[101]
== APP ==       Received HTTP response after 4.5181000000000004ms - Created
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[101]
== APP ==       End processing HTTP request after 4.6208ms - Created
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[100]
== APP ==       Start processing HTTP request GET http://localhost:61102/v1.0/state/17
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[100]
== APP ==       Sending HTTP request GET http://localhost:61102/v1.0/state/17
== APP == info: System.Net.Http.HttpClient.state.ClientHandler[101]
== APP ==       Received HTTP response after 20.2967ms - OK
== APP == info: System.Net.Http.HttpClient.state.LogicalHandler[101]
== APP ==       End processing HTTP request after 20.691100000000002ms – OK

为了同时实现可移植性和与现有代码的轻松集成,Dapr通过http或gRPC提供了标准API。Dapr端口可从Dapr启动日志中获取,如以下日志表示Dapr公开的HTTP端口为61102(通过Dapr也可使用gRPC方式进行服务调用)

== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="http server is running on port 61102"
== DAPR == time="2019-11-16T18:33:32+08:00" level=info msg="gRPC server is running on port 61103"

我们可通过以下地址来调用示例方法,根据Dapr服务调用API规范,其代理调用规则为:

POST/GET/PUT/DELETE http://localhost:<Dapr端口>/v1.0/invoke/<id>/method/<method-name>

直接调用:GET http://localhost:5000/17

通过Dapr服务调用: GET http://localhost:61102/v1.0/invoke/routing/method/17
 
注意:Dapr的服务调用是有dapr sidecar来实现的,在被调用的服务中无需注入任何与dapr相关的代码。


coding-interview-university/README-cn.md at master · jwasham/coding-interview-university · GitHub

$
0
0

[译] Coding Interview University 一套完整的学习手册帮助自己准备 Google 的面试

xitu

这是?

这是我为了从 web 开发者(自学、非计算机科学学位)蜕变至 Google 软件工程师所制定的计划,其内容历时数月。

白板上编程 ———— 来自 HBO 频道的剧集,“硅谷”

这一长列表是从 Google 的指导笔记中萃取出来并进行扩展。因此,有些事情你必须去了解一下。我在列表的底部添加了一些额外项,用于解决面试中可能会出现的问题。这些额外项大部分是来自于 Steve Yegge 的“ 得到在 Google 工作的机会”。而在 Google 指导笔记的逐字间,它们有时也会被反映出来。


目录

---------------- 下面的内容是可选的 ----------------


为何要用到它?

我一直都是遵循该计划去准备 Google 的面试。自 1997 年以来,我一直从事于 web 程序的构建、服务器的构建及创业型公司的创办。对于只有着一个经济学学位,而不是计算机科学学位(CS degree)的我来说,在职业生涯中所取得的都非常成功。然而,我想在 Google 工作,并进入大型系统中,真正地去理解计算机系统、算法效率、数据结构性能、低级别编程语言及其工作原理。可一项都不了解的我,怎么会被 Google 所应聘呢?

当我创建该项目时,我从一个堆栈到一个堆都不了解。那时的我,完全不了解 Big-O 、树,或如何去遍历一个图。如果非要我去编写一个排序算法的话,我只能说我所写的肯定是很糟糕。一直以来,我所用的任何数据结构都是内建于编程语言当中。至于它们在背后是如何运作,对此我一概不清楚。此外,以前的我并不需要对内存进行管理,最多就只是在一个正在执行的进程抛出了“内存不足”的错误后,采取一些权变措施。而在我的编程生活中,也甚少使用到多维数组,可关联数组却成千上万。而且,从一开始到现在,我都还未曾自己实现过数据结构。

就是这样的我,在经过该学习计划后,已然对被 Google 所雇佣充满信心。这是一个漫长的计划,以至于花费了我数月的时间。若您早已熟悉大部分的知识,那么也许能节省大量的时间。

如何使用它

下面所有的东西都只是一个概述。因此,你需要由上而下逐一地去处理它。

在学习过程中,我是使用 GitHub 特殊的语法特性 markdown flavor 去检查计划的进展,包括使用任务列表。

  • 创建一个新的分支,以使得你可以像这样去检查计划的进展。直接往方括号中填写一个字符 x 即可:[x]

更多关于 Github-flavored markdown 的详情

我得到了工作吗?

我还没去应聘。

因为我离完成学习(完成该疯狂的计划列表)还需要数天的时间,并打算在下周开始用一整天的时间,以编程的方式去解决问题。当然,这将会持续数周的时间。然后,我才通过使用在二月份所得到的一个介绍资格,去正式应聘 Google(没错,是二月份时就得到的)。

感谢 JP 的这次介绍。

跟着我的脚步

目前我仍在该计划的执行过程中,如果你想跟随我脚步去学习的话,可以登进我在 GoogleyAsHeck.com上所写的博客。

下面是我的联系方式:

John Washam - Coding Interview University

不要妄自菲薄

  • Google 的工程师都是才智过人的。但是,就算是工作在 Google 的他们,仍然会因为觉得自己不够聪明而感到一种不安。
  • 天才程序员的神话

关于 Google

相关视频资源

部分视频只能通过在 Coursera、Edx 或 Lynda.com class 上注册登录才能观看。这些视频被称为网络公开课程(MOOC)。即便是免费观看,部分课程可能会由于不在时间段内而无法获取。因此,你需要多等待几个月。

很感谢您能帮我把网络公开课程的视频链接转换成公开的视频源,以代替那些在线课程的视频。此外,一些大学的讲座视频也是我所青睐的。

面试过程 & 通用的面试准备

为你的面试选择一种语言

在这,我就以下话题写一篇短文 —— 重点:为在 Google 的面试选择一种语言

在大多数公司的面试当中,你可以在编程这一环节,使用一种自己用起来较为舒适的语言去完成编程。但在 Google,你只有三种固定的选择:

  • C++
  • Java
  • Python

有时你也可以使用下面两种,但需要事先查阅说明。因为,说明中会有警告:

  • JavaScript
  • Ruby

你需要对你所选择的语言感到非常舒适且足够了解。

更多关于语言选择的阅读:

在此查看相关语言的资源

由于,我正在学习C、C++ 和 Python。因此,在下面你会看到部分关于它们的学习资料。相关书籍请看文章的底部。

在你开始之前

该列表已经持续更新了很长的一段时间,所以,我们的确很容易会对其失去控制。

这里列出了一些我所犯过的错误,希望您不要重滔覆辙。

1. 你不可能把所有的东西都记住

就算我查看了数小时的视频,并记录了大量的笔记。几个月后的我,仍然会忘却其中大部分的东西。所以,我翻阅了我的笔记,并将可回顾的东西制作成抽认卡(flashcard)(请往下看)

2. 使用抽认卡

为了解决善忘的问题,我制作了一些关于抽认卡的页面,用于添加两种抽认卡:正常的及带有代码的。每种卡都会有不同的格式设计。

而且,我还以移动设备为先去设计这些网页,以使得在任何地方的我,都能通过我的手机及平板去回顾知识。

你也可以免费制作属于你自己的抽认卡网站:

  • 抽认卡页面的代码仓库
  • 我的抽认卡数据库:有一点需要记住的是,我做事有点过头,以至于把卡片都覆盖到所有的东西上。从汇编语言和 Python 的细枝末节,乃至到机器学习和统计都被覆盖到卡片上。而这种做法,对于 Google 的要求来说,却是多余。

在抽认卡上做笔记:若你第一次发现你知道问题的答案时,先不要急着把其标注成“已懂”。你需要做的,是去查看一下是否有同样的抽认卡,并在你真正懂得如何解决问题之前,多问自己几次。重复地问答可帮助您深刻记住该知识点。

3. 回顾,回顾,回顾

我留有一组 ASCII 码表、OSI 堆栈、Big-O 记号及更多的小抄纸,以便在空余的时候可以学习。

每编程半个小时就要休息一下,并去回顾你的抽认卡。

4. 专注

在学习的过程中,往往会有许多令人分心的事占据着我们宝贵的时间。因此,专注和集中注意力是非常困难的。

你所看不到的

由于,这个巨大的列表一开始是作为我个人从 Google 面试指导笔记所形成的一个事件处理列表。因此,有一些我熟悉且普遍的技术在此都未被谈及到:

  • SQL
  • Javascript
  • HTML、CSS 和其他前端技术

日常计划

部分问题可能会花费一天的时间去学习,而部分则会花费多天。当然,有些学习并不需要我们懂得如何实现。

因此,每一天我都会在下面所列出的列表中选择一项,并查看相关的视频。然后,使用以下的一种语言去实现:

C —— 使用结构体和函数,该函数会接受一个结构体指针 * 及其他数据作为参数。
C++ —— 不使用内建的数据类型。
C++ —— 使用内建的数据类型,如使用 STL 的 std::list 来作为链表。
Python ——  使用内建的数据类型(为了持续练习 Python),并编写一些测试去保证自己代码的正确性。有时,只需要使用断言函数 assert() 即可。
此外,你也可以使用 Java 或其他语言。以上只是我的个人偏好而已。

为何要在这些语言上分别实现一次?

因为可以练习,练习,练习,直至我厌倦它,并完美地实现出来。(若有部分边缘条件没想到时,我会用书写的形式记录下来并去记忆)
因为可以在纯原生的条件下工作(不需垃圾回收机制的帮助下,分配/释放内存(除了 Python))
因为可以利用上内建的数据类型,以使得我拥有在现实中使用内建工具的经验(在生产环境中,我不会去实现自己的链表)

就算我没有时间去每一项都这么做,但我也会尽我所能的。

在这里,你可以查看到我的代码:

你不需要记住每一个算法的内部原理。

在一个白板上写代码,而不要直接在计算机上编写。在测试完部分简单的输入后,到计算机上再测试一遍。

必备知识

算法复杂度 / Big-O / 渐进分析法

数据结构

更多的知识

树(Trees)

排序(Sorting)

图(Graphs)

图论能解决计算机科学里的很多问题,所以这一节会比较长,像树和排序的部分一样。

可以从 Skiena 的书(参考下面的书推荐小节)和面试书籍中学习更多关于图的实践。

更多知识


终面

这一部分有一些短视频,你可以快速的观看和复习大多数重要概念。
这对经常性的巩固很有帮助。

综述:

  • 2-3 分钟的短视频系列 (23 个)
  • 2-5 分钟的短视频系列 - Michael Sambol (18 个):

排序:

书籍

Google Coaching 里提到的

阅读并做练习:

  • 算法设计手册 (Skiena)

    read and do exercises from the books below. Then move to coding challenges (further down below) 一旦你理解了每日计划里的所有内容,就去读上面所列的书并完成练习,然后开始读下面所列的书并做练习,之后就可以开始实战写代码了(本文再往后的部分)

首先阅读:

然后阅读 (这本获得了很多推荐, 但是不在 Google coaching 的文档里):

附加书单

这些没有被 Google 推荐阅读,不过我因为需要这些背景知识所以也把它们列在了这里。

如果你有时间

编码练习和挑战

一旦你学会了理论基础,就应该把它们拿出来练练。 尽量坚持每天做编码练习,越多越好。

编程问题预备:

编码练习平台:

当你临近面试时

你的简历

当面试来临的时候

随着下面列举的问题思考下你可能会遇到的 20 个面试问题
每个问题准备 2-3 种回答
准备点故事,不要只是摆一些你完成的事情的数据,相信我,人人都喜欢听故事
  • 你为什么想得到这份工作?
  • 你解决过的最有难度的问题是什么?
  • 面对过的最大挑战是什么?
  • 见过的最好或者最坏的设计是怎么样的?
  • 对某项 Google 产品提出改进建议。
  • 你作为一个个体同时也是团队的一员,如何达到最好的工作状态?
  • 你的什么技能或者经验是你的角色中不可或缺的?为什么?
  • 你在某份工作或某个项目中最享受的是什么?
  • 你在某份工作或某个项目中面临过的最大挑战是什么?
  • 你在某份工作或某个项目中遇到过的最蛋疼的 Bug 是什么样的?
  • 你在某份工作或某个项目中学到了什么?
  • 你在某份工作或某个项目中哪些地方还可以做的更好?

问面试官的问题

我会问的一些:(可能我已经知道了答案但我想听听面试官的看法或者了解团队的前景):
  • 团队多大规模?
  • 开发周期是怎样的? 会使用瀑布流/极限编程/敏捷开发么?
  • 经常会为 deadline 加班么? 或者是有弹性的?
  • 团队里怎么做技术选型?
  • 每周平均开多少次会?
  • 你觉得工作环境有助于员工集中精力吗?
  • 目前正在做什么工作?
  • 喜欢这些事情吗?
  • 工作期限是怎么样的?

当你获得了梦想的职位

我还能说些什么呢,恭喜你!

坚持继续学习。

得到这份工作只是一个开始。


*****************************************************************************************************
*****************************************************************************************************

下面的内容都是可选的。这些是我的推荐,不是 Google 的。
通过学习这些内容,你将会得到更多的有关 CS 的概念,并将为所有的软件工程工作做更好的准备。

*****************************************************************************************************
*****************************************************************************************************

附加的学习

--

一些主题的额外内容

我为前面提到的某些主题增加了一些额外的内容,之所以没有直接添加到前面,是因为这样很容易导致某个主题内容过多。毕竟你想在本世纪找到一份工作,对吧?

视频系列

坐下来享受一下吧。"netflix and skill" :P

计算机科学课程

Git_014:最佳敏捷分支策略

$
0
0
目前业界有三种分支策略:Git Flow,Github Flow,Gitlab Flow,它们都是采用"功能驱动式开发"(Feature-driven development,FDD)。所谓 FDD,指的是需求是开发的起点,先有需求再有功能分支(feature branch)或者补丁分支(bugfix 或 hotfix branch)。完成开发后,该分支就合并到主分支,然后该分支被删除。

在分析了三种分支策略后,笔者发现三种策略都有某些缺陷,不能完全满足敏捷开发、持续集成、持续部署的要求。

为此,笔者提出最佳敏捷分支策略。


1. 主分支
代码库有两个主分支作为常设分支。

  • master
  • release

1.1 master 分支
master 分支用于日常开发,存放最新的代码。
master 分支对应测试环境,一套代码版本至少需要搭建两套测试环境,分别用于系统测试(由测试人员测试)和验收测试(由业务人员测试)。
如何保护 master 分支❓

1.2 release 分支
release 分支用于跟踪线上版本,存放所有对外正式发行的版本。
release 分支对应生产环境。
所有测试通过后,从 master 分支创建 release 分支,格式型如 release/1.0,同时在该 release 分支上打 Tag,格式型如: 1.0,注意前面不要加 v,v1.0 不符合习惯

如何保护 release 分支❓

2. 临时分支
  • feature
  • bugfix
  • hotfix
2.1  feature 分支
feature 分支是功能分支,用于开发各个功能模块,格式型如 feature/。
开发人员领取各个功能任务后, 从 master 分支创建各自的 feature 分支,通过单元测试和集成测试(由开发人员测试)后,最终合并到 master 分支
所有 feature 分支都合并到 master 分支后,创建系统测试环境,由测试人员进行系统测试;创建验收测试环境,由业务人员进行验收测试。

2.2. bugfix 分支
bugfix 分支是补丁分支,用于修复在测试环境中测试出来的各个 bug,格式型如 bugfix/。
在测试环境中测试出来的 bug,由开发人员领取任务, 从 master 分支创建各自的 bugfix 分支进行修复,开发人员需要为每个 bugfix 单独编写单元测试和集成测试,测试通过后,最终合并到 master 分支

2.3. hotfix 分支
hotfix 分支是热补丁分支,用于修复在生产环境中发现的各个 bug,格式型如 hotfix/。
hotfix 分支对应准生产环境,一套代码版本至少需要搭建两套测试环境,分别用于系统测试(由测试人员测试)和验收测试(由业务人员测试)。
在生产环境中发现的 bug,由开发人员领取任务, 从当前发现问题的 release 分支创建各自的 hotfix 分支进行修复,开发人员需要为每个 hotfix 单独编写单元测试和集成测试,
所有测试通过后,将 hotfix 分支合并到 master 分支,然后创建 release 分支,格式型如 release/1.0.x,同时在该 release 分支上打 Tag,格式型如: 1.0.x,注意前面不要加 v,v1.0 不符合习惯。

参考文献:
1. https://gist.github.com/digitaljhelms/4287848
2. http://www.ruanyifeng.com/blog/2015/12/git-workflow.html
3. https://www.cnblogs.com/doit8791/p/10147321.html
4. https://blog.csdn.net/hu_zhiting/article/details/95030586
5. http://www.ruanyifeng.com/blog/2012/07/git.html
6. https://www.atlassian.com/blog/git/simple-git-workflow-is-simple
7. https://mohamedradwan.com/2018/01/08/promoting-your-application-deployment-to-different-environments-from-branches-with-and-without-feature-toggle/

ElasticSearch 亿级数据检索深度优化

$
0
0

一、前言

数据平台已迭代三个版本,从头开始遇到很多常见的难题,终于有片段时间整理一些已完善的文档,在此分享以供所需朋友的实现参考,少走些弯路,在此篇幅中偏重于ES的优化,关于HBase,Hadoop的设计优化估计有很多文章可以参考,不再赘述。

二、需求说明

项目背景:

在一业务系统中,部分表每天的数据量过亿,已按天分表,但业务上受限于按天查询,并且DB中只能保留3个月的数据(硬件高配),分库代价较高。

改进版本目标:
  1. 数据能跨月查询,并且支持1年以上的历史数据查询与导出。

  2. 按条件的数据查询秒级返回。

三、Elasticsearch检索原理

3.1 关于ES和Lucene基础结构

谈到优化必须能了解组件的基本原理,才容易找到瓶颈所在,以免走多种弯路,先从ES的基础结构说起(如下图):


一些基本概念:
  • Cluster: 包含多个Node的集群

  • Node: 集群服务单元

  • Index: 一个ES索引包含一个或多个物理分片,它只是这些分片的逻辑命名空间

  • Type: 一个index的不同分类,6.x后只能配置一个type,以后将移除

  • Document: 最基础的可被索引的数据单元,如一个JSON串

  • Shards : 一个分片是一个底层的工作单元,它仅保存全部数据中的一部分,它是一个Lucence实例 (一个Lucene: 索引最大包含2,147,483,519 (= Integer.MAX_VALUE - 128)个文档数量)

  • Replicas: 分片备份,用于保障数据安全与分担检索压力

    ES依赖一个重要的组件Lucene,关于数据结构的优化通常来说是对Lucene的优化,它是集群的一个存储于检索工作单元,结构如下图:

在Lucene中,分为索引(录入)与检索(查询)两部分,索引部分包含 分词器、过滤器、字符映射器等,检索部分包含 查询解析器等。

一个Lucene索引包含多个segments,一个segment包含多个文档,每个文档包含多个字段,每个字段经过分词后形成一个或多个term。

通过Luke工具查看ES的lucene文件如下,主要增加了_id和_source字段:

3.2 Lucene索引实现

Lucene 索引文件结构主要的分为: 词典、倒排表、正向文件、DocValues等,如下图:

注:整理来源于lucene官方:  http://lucene.apache.org/core/7_2_1/core/org/apache/lucene/codecs/lucene70/package-summary.html#package.description

Lucene随机三次磁盘读取比较耗时。其中.fdt文件保存数据值损耗空间大,.tim和.doc则需要SSD存储提高随机读写性能。另外一个比较消耗性能的是打分流程,不需要则可屏蔽。

关于DocValues

倒排索引解决从词快速检索到相应文档ID, 但如果需要对结果进行排序、分组、聚合等操作的时候则需要根据文档ID快速找到对应的值。

通过倒排索引代价缺很高:需迭代索引里的每个词项并收集文档的列里面 token。这很慢而且难以扩展:随着词项和文档的数量增加,执行时间也会增加。Solr docs对此的解释如下:

For other features that we now commonly associate with search, such as sorting, faceting, and highlighting, this approach is not very efficient. The faceting engine, for example, must look up each term that appears in each document that will make up the result set and pull the document IDs in order to build the facet list. In Solr, this is maintained in memory, and can be slow to load (depending on the number of documents, terms, etc.)

在lucene 4.0版本前通过FieldCache,原理是通过按列逆转倒排表将(field value ->doc)映射变成(doc -> field value)映射,问题为逐步构建时间长并且消耗大量内存,容易造成OOM。

DocValues是一种列存储结构,能快速通过文档ID找到相关需要排序的字段。在ES中,默认开启所有(除了标记需analyzed的字符串字段)字段的doc values, 如果不需要对此字段做任何排序等工作,则可关闭以减少资源消耗。

3.3 关于ES索引与检索分片

ES中一个索引由一个或多个lucene索引构成,一个lucene索引由一个或多个segment构成,其中segment是最小的检索域。

数据具体被存储到哪个分片上: shard = hash(routing) % number_of_primary_shards

默认情况下 routing参数是文档ID (murmurhash3),可通过 URL中的 _routing 参数指定数据分布在同一个分片中,index和search的时候都需要一致才能找到数据, 如果能明确根据_routing进行数据分区,则可减少分片的检索工作,以提高性能。

四、优化案例

在我们的案例中,查询字段都是固定的,不提供全文检索功能,这也是几十亿数据能秒级返回的一个大前提:

  1. ES仅提供字段的检索,仅存储HBase的Rowkey不存储实际数据。

  2. 实际数据存储在HBase中,通过Rowkey查询,如下图。

  3. 提高索引与检索的性能建议,可参考官方文档(如 https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html)。

一些细节优化项官方与其他的一些文章都有描述,在此文章中仅提出一些本案例的重点优化项。

4.1  优化索引性能

  1. 批量写入,看每条数据量的大小,一般都是几百到几千。

  2. 多线程写入,写入线程数一般和机器数相当,可以配多种情况,在测试环境通过Kibana观察性能曲线。

  3. 增加segments的刷新时间,通过上面的原理知道,segment作为一个最小的检索单元,比如segment有50个,目的需要查10条数据,但需要从50个segment分别查询10条,共500条记录,再进行排序或者分数比较后,截取最前面的10条,丢弃490条。在我们的案例中将此 refresh_interval: -1 ,程序批量写入完成后进行手工刷新(调用相应的API即可)。

  4. 内存分配方面,很多文章已经提到, 给系统50%的内存给Lucene做文件缓存,它任务很繁重,所以ES节点的内存需要比较多(比如每个节点能配置64G以上最好)。

  5. 磁盘方面配置SSD,机械盘做阵列RAID5 RAID10虽然看上去很快,但是随机IO还是SSD好。

  6. 使用自动生成的ID,在我们的案例中使用自定义的KEY,也就是与HBase的ROW KEY,是为了能根据rowkey删除和更新数据,性能下降不是很明显。

  7. 关于段合并,合并在后台定期执行,比较大的segment需要很长时间才能完成,为了减少对其他操作的影响(如检索),elasticsearch进行阈值限制,默认是20MB/s,可配置的参数:indices.store.throttle.max_bytes_per_sec : 200mb  (根据磁盘性能调整)合并线程数默认是:Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2)),如果是机械磁盘,可以考虑设置为1:index.merge.scheduler.max_thread_count: 1,在我们的案例中使用SSD,配置了6个合并线程。

4.2 优化检索性能

  1. 关闭不需要字段的doc values。

  2. 尽量使用keyword替代一些long或者int之类,term查询总比range查询好 (参考lucene说明 http://lucene.apache.org/core/7_4_0/core/org/apache/lucene/index/PointValues.html)。

  3. 关闭不需要查询字段的_source功能,不将此存储仅ES中,以节省磁盘空间。

  4. 评分消耗资源,如果不需要可使用filter过滤来达到关闭评分功能,score则为0,如果使用constantScoreQuery则score为1。

  5. 关于分页:

  • from + size: 每分片检索结果数最大为 from + size,假设from = 20, size = 20,则每个分片需要获取20 * 20 = 400条数据,多个分片的结果在协调节点合并(假设请求的分配数为5,则结果数最大为 400*5 = 2000条) 再在内存中排序后然后20条给用户。这种机制导致越往后分页获取的代价越高,达到50000条将面临沉重的代价,默认from + size默认如下:index.max_result_window :10000

  • search_after:  使用前一个分页记录的最后一条来检索下一个分页记录,在我们的案例中,首先使用from+size,检索出结果后再使用search_after,在页面上我们限制了用户只能跳5页,不能跳到最后一页。

  • scroll 用于大结果集查询,缺陷是需要维护scroll_id

  • 关于排序:我们增加一个long字段,它用于存储时间和ID的组合(通过移位即可),正排与倒排性能相差不明显。

  • 关于CPU消耗,检索时如果需要做排序则需要字段对比,消耗CPU比较大,如果有可能尽量分配16cores以上的CPU,具体看业务压力。

  • 关于合并被标记删除的记录,我们设置为0表示在合并的时候一定删除被标记的记录,默认应该是大于10%才删除: merge.policy.expunge_deletes_allowed: 0

  • {   
        mappings: {
            data: {
                dynamic: false,
                _source: {
                    includes: [XXX]  -- 仅将查询结果所需的数据存储仅_source中
                },
                properties: {
                    state: {
                        type: keyword,   -- 虽然state为int值,但如果不需要做范围查询,尽量使用keyword,因为int需要比keyword增加额外的消耗。
                        doc_values: false  -- 关闭不需要字段的doc values功能,仅对需要排序,汇聚功能的字段开启。
                    },
                    b: {
                        type: long    -- 使用了范围查询字段,则需要用long或者int之类 (构建类似KD-trees结构)
                    }
                }
            }
        },
       settings: {......}
    }

    五、性能测试

    优化效果评估基于基准测试,如果没有基准测试无法了解是否有性能提升,在这所有的变动前做一次测试会比较好。在我们的案例中:

    1. 单节点5千万到一亿的数据量测试,检查单点承受能力。

    2. 集群测试1亿-30亿的数量,磁盘IO/内存/CPU/网络IO消耗如何。

    3. 随机不同组合条件的检索,在各个数据量情况下表现如何。

    4. 另外SSD与机械盘在测试中性能差距如何。

    性能的测试组合有很多,通常也很花时间,不过作为评测标准时间上的投入有必要,否则生产出现性能问题很难定位或不好改善。对于ES的性能研究花了不少时间,最多的关注点就是lucene的优化,能深入了解lucene原理对优化有很大的帮助。

    六、生产效果

    目前平台稳定运行,几十亿的数据查询100条都在3秒内返回,前后翻页很快,如果后续有性能瓶颈,可通过扩展节点分担数据压力。

    作者:mikevictor

    来源:https://www.cnblogs.com/mikevictor07/p/10006553.html

    2020年的互联网行业:我想提出的12个问题,以及初步回答

    $
    0
    0

    本怪盗团负责人 裴培

    archibaldpei#icloud.com

    2019年就快过去了。对于互联网行业来说,这又是瞬息万变、变化无穷的这一年;过去十几年,每一年都是如此。相信各大互联网公司早已在认真考虑2020年的战略战术,投资者也在考虑如何布局下一年。如果要为即将到来的2020年找一个主题词,那就是“不安”——过去十年的经验越来越靠不住了,大家越来越需要学习,新生事物那么多,宏观局势变化又那么快,而行业基数越来越大了。

    下面是本怪盗团希望对2020年的互联网行业提出的12个问题。我不能未卜先知,只是学习者。对下列12个重要问题, 我努力通过自身掌握的信息和自认为可行的逻辑,给出了一些初步答案。然而,未来毕竟是一步一个脚印踩出来的,我的答案肯定有很多错误;而且,肯定有一些重要问题是我没有认识到的。如果本怪盗团提出的问题能给业内人士带来一些参考,那就心满意足了。

    自从2010-11年移动互联网崛起(以微博、微信、小米手机的诞生为标志)以来,中国互联网行业经历了一个完整的世代。现在呼风唤雨的互联网巨头,要么是在移动时代崛起的,要么是PC时代巨头当中顺应了移动潮流的那一部分。在可见的未来,我们仍将处于移动互联网时代,但是竞争格局越来越激烈,既有经验的价值越来越低。我们需要远离舒适区,在所剩无几的荒芜之地上尝试开辟新路。这就是本怪盗团写这篇文章的主要目的——抛砖引玉,互联网行业应该需要抛砖吧。

    (战役计划是指挥官和参谋制订的,但是是前线士兵打出来的)

    1.整体格局

    从2016年开始,互联网行业就在喊“流量红利耗尽”;然而,2017-19年,中国移动设备用户仍然增长了2亿以上,用户日均时长也增长了30-45分钟。换句话说,过去三年是“移动流量红利的尾声期”。现在,中国拥有11亿智能手机用户,日均亮屏时间约4.5小时;两者均逼近了“理论上限”。

    可以认为,直到今天,互联网巨头还没有进入所谓“存量博弈”“互相进攻大本营”的时代。举一个很简单的例子:当抖音势不可挡地崛起之时,快手的增长并未停滞;所谓抖音抢走了微信用户时长的说法也缺乏根据(抖音和快手的用户时长其实是自己创生的)。通过经营细分市场、用户分层、占领剩余空白地,相同行业的互联网巨头仍可能实现共处:想想看,2019年,阿里、京东、拼多多的业绩都很好看。

    然而,上述景象更应该称为“风暴前的静谧”。最迟至2020年上半年,绝大部分仅存的“空白地”会被开拓殆尽;围绕老用户的变现会遭遇瓶颈;实体经济不振会对互联网构成持续影响。因此,我们终将进入“存量博弈”或曰“巨人互相伤害”的时代。这个时代会不会远比以前更残酷?竞争逻辑和成长逻辑会不会完全不同?最终会不会所有人都要站队,形成几个更严密的集团?无论如何,未来不会比过去更好……

    (战争会越来越残忍。小心,不要爱上它。)

    2.互联网的站队问题

    投资者一般认为,在中国互联网行业存在着几个“阵营”,就像二战中的同盟国/轴心国一样:腾讯系、阿里系、百度系,还有正在崛起的头条系、若有若无的雷军系,等等。然而,上述观点是错误的。可以认为:直到2019年,互联网行业的“站队”“造系”现象还处于初期,远远谈不上形成阵营。

    首先,“腾讯系”是不存在的。腾讯对创业公司进行战略投资时,甚至往往不会约定禁止阿里或字节跳动投资;腾讯很少参与战略投资对象的管理,这一点经常为人诟病。其次,“阿里系”也是不存在的,因为近年来阿里越来越倾向于将重要投资对象收归并表体系——菜鸟网络、饿了么、口碑网均是如此,盒马鲜生、钉钉一开始就是并表的。最后,“百度系”“头条系”其实也不存在,它们最强大的子公司或子应用其实都在并表范围内。

    进入2020年,“站队”可能更加重要,因为竞争环境恶化了,融资环境也不容乐观。互联网可能会真的出现“三大/四大阵营并立”的状况,而且各个阵营的流量和内容相对封闭。腾讯、阿里、字节跳动这些超级巨头可能越来越关心投资对象的日常管理,新兴公司(如果还存在的话)也会越来越欢迎它们介入。这将成为“新常态”吗?这个新世界会不会一点也不美丽?

    (互联网世界会被几个巨头捏在手里摆弄吗?)

    3.用户集中与分层的天然矛盾

    在移动互联网发展晚期,流量格局存在一对天然矛盾:一方面,用户越来越懒、越来越不愿安装很多App,而是更青睐“一站式服务”,流量集中于少量头部平台(强者恒强);另一方面,用户经验越来越丰富、自主性越来越强,对“调性”“垂直特色”等虚无缥缈的东西日益重视(分层、分类)。矛盾的两个方面都蕴含着商机,问题在于你很难两者兼得。

    过去几年,我们看到抖音、快手等短视频App飞速成长为“全能平台”,打入秀场直播、游戏直播、电商带货等领域,这就是“强者恒强”所导致的“降维打击”;我们也看到B站、小红书等垂直平台稳步扩张用户基础并实现变现,这就是“垂直调性”大显神威的结果。在游戏行业,上述“精神分裂”的趋势更加明显:一边是“吃鸡”等全民品类几乎在一夜之间风靡全国,一边是《明日方舟》《闪耀暖暖》等口碑向垂类游戏大放异彩。

    在上述“精神分裂”的过程中,最痛苦的是那些“高不成低不就”的平台或内容:既没有实力做超级平台、全民级内容,又没有特色或调性吸引垂直粉丝。尤其在视频、电商等领域,“中等选手”几乎就是“没落”的代名词。2020年,我们会不会看到整个互联网行业的两极分化?今后就是少数头部平台加上一大群特色应用/内容商?我倒是很乐意看到这一幕!

    (永远记住:一开始得意的人未必笑到最后)

    4.永远不可能降临的2B互联网?

    过去二十年,成功的中国互联网公司做的都是2C生意。严格地说,全世界绝大部分互联网公司做的都是2C生意;在美国,2B的软件/IT解决方案公司与2C的互联网公司也是两个圈子(亚马逊或许算个例外)。从2018年开始,由于种种原因,中国互联网公司及投资者越来越强调2B生意的重要性。遗憾的是,就算到了2020年,我们还是很难看到2B业务为任何互联网公司贡献实质性利润。

    2B和2C是完全不同的生意,后者讲究规模效应、高举高打、快速迭代、漏斗理论,前者几乎与之完全相反。互联网公司其实更适合做B2B2C,例如为银行做助贷、为传统企业获客提供C2B经验等。最重要的是:拿下2B市场又有什么意义呢?中国最大的2B软件公司又能有多大?如果不是传统的2C业务已经接近瓶颈,哪家互联网巨头会重兵投入2B?

    对互联网巨头来说,即便流量红利彻底耗尽,2B也不是唯一的战略方向。下面几个方向至少同样有吸引力:海外扩张;整合上游内容;智能家居(IoT);进一步强化数据变现。当然,对外部投资者来说,“万亿级别的2B解决方案市场”听起来很性感”;问题在于,互联网公司吃得到吗?就算吃到了,能做出利润吗?我对此不抱乐观态度。

    (有些战役你打不赢,但还是要打一打)

    5.海外扩张的多重难题

    人们曾经天真地认为:凭借中国市场十几亿用户培养出来的成功经验和战斗力,中国互联网公司出海将是一片坦途,互联网将是中国“输出商业模式”的首选。TikTok的成功,似乎验证了这个观点。然而,到2019年下半年,我们看到事态没这么美好。一言以蔽之:进军发达国家会越来越难,进军发展中国家又无利可图。

    美国政客对TikTok的敌意态度可以说明很多问题:他们认为,由一家中国公司去收集美国公民的隐私数据本来就是危险的。在欧洲,许多中国公司都吃过用户隐私方面的亏。欧美监管部门为了用户隐私,甚至可以对自家公司开出天价罚单,何况对中国公司?此外,Facebook、Google等北美互联网巨头远不像很多中国人想象的那么无能——它们确实不怎么加班,但是它们应对挑战的效率不低。

    2020年,中国互联网出海的战略方向大概会指向发展中国家——传统强项的东南亚,正在崛起的南亚,钱多人少的中东,新兴的拉美和东欧,等等。问题在于,以上大部分要么是中低收入市场,要么文化背景与中国差异很大。在游戏等内容领域,出海难度或许稍低;在平台层面,出海仍将困难重重。互联网巨头会不会采取更务实、更保守的海外扩张态度?还是趁着有钱,加速扩张碰碰运气?不同的公司会做出不同的选择吧。

    (在别人的领土上进行战争是一种奖赏)

    6.流量的“私有化”与品牌的“个人化”

    2019年底,李佳琦、薇娅的大名无人不知。其实,他们早就是淘宝直播的风云人物,只是近期走向更大的世界而已。用户非常青睐李佳琦,他的带货转化率极高;品牌也非常期待李佳琦,雅诗兰黛等头部品牌会把首发尖货以全网最低价拿给他卖。与此同时,我们看到传统品牌广告日益衰落;李湘等“明星”尝试带货的效果很差;传统视频平台和经纪公司至今尚未复制一个自己的李佳琦/薇娅。这是怎么回事?

    一言以蔽之:我们处在一个“品牌个人化”的时代。用户对传统的假大空宣传、高逼格人设不再感兴趣。他们希望看到会呼吸、接地气、有调性、有专业性的网红/内容/品牌。经常有人问我“什么是调性”,我会回答:你绝不会把李佳琦误认为路人甲,绝不会把郭德纲误认为姜昆,绝不会把昆汀误认为郭敬明,这就是调性!这就是微博衰落而快手走红、长视频衰落而抖音走红的根本原因:你是更愿意看整容脸、演技差、经营着虚假人设的流量小花刷数据,还是愿意看真性情、潮人范、接地气的UP主妙语连珠?别误会,我知道很多UP主/主播的人设也是经营出来的,但是仍然更可信。

    交流方式的“个人化”“调性化”,必然伴随着流量的“私有化”。B站一粉顶微博十粉,微信群的价值远超过微淘群——因为前者的“私有性”更强。传统媒体、传统广告平台、传统流量分配机制、传统内容生态在不断被架空。总而言之,粉丝闭环在不断缩短,粉丝越来越重视“内容本身”“创作者本身”而不是背后的那套体制。这对互联网行业而言是福是祸?我只知道,这是个大变局,一定有人受益。

    (任何一次重新洗牌,都是几家欢乐几家愁)

    7.移动互联网原住民长大了,他们比你聪明

    2020年,第一批90后将年满30岁,第一批00后将年满20岁。95-10后是移动互联网的原住民,对他们而言,移动互联网是“理所当然存在”的;就像对80后而言,电视机、汽车、冰箱是“理所当然存在”的一样。他们很聪明,比你我更聪明,玩梗玩的飞起,习惯了虚拟社交,往往有良好的付费习惯。他们中的大部分人都比父辈更幸福,善于怀疑权威、解构一切。

    我发现:绝大部分70-80后人群不了解95-10后的成长环境,低估了他们对新鲜事物的接受度。举个例子:我给某80后高管推荐过《命运石之门》,他看了两集就表示看不懂,“这么复杂的东西不可能流行”;他认为,现在的年轻人应该更喜欢唐家三少这样“简单粗暴的内容”。事实是:我认识的95后没有一个是唐家三少的粉丝(他属于上一个世代),大家都能理解《命运石之门》复杂的“时间机器”“世界线收束”理论。为什么?因为他们就是这样长大的呀!

    既然95后如此聪明,为什么很多人还觉得他们“懒、堕落、吃不了苦”呢?因为没有必要啊!他们知道,“人间不值得”,996理论无非肥了资本家,做一切事情归根结底是为了个人发展与开心。他们正在稳步接管互联网——从话语权、用户时长到收入贡献。很多投资者自以为懂他们,其实完全不懂。互联网公司能尽快学会取悦95-10后、破除刻板印象、与他们打成一片吗?我不太乐观;这注定是一条漫长的路。

    (不学习就会战败,战败就会做俘虏)

    8.电商行业:在神奇的2019年之后

    对于电商行业而言,2019年颇为神奇:宏观经济明明在减速,几大电商平台的增速都还不错,双十一也又报出了新高。然而,阿里、京东、拼多多三家的业绩逻辑是不同的——阿里正在尽情享受多年以来积累的“淘系电商生态”红利;京东正在以利润为导向,重新设置战术重点;拼多多正在野蛮生长,复购率的提升、现金流的健康是它高举高打的基础。对这三巨头来说,宏观经济因素都要让位于公司自身的因素。

    然而,进入2020年,形势会有很大变化:阿里可能会抽调一些资源到O2O、线下零售、云计算、海外新兴领域,对核心电商则更看重长线可持续发展而非短线增长/利润;京东需要找到新的成长点;拼多多的基数将足够巨大,与淘宝越来越像,两巨人真正的搏杀才刚开始。

    拼多多的GMV很可能在2020年达到1.5-2万亿,仅仅略逊于京东。在它面前只剩下一条道路,那就是挑战霸主角色。而阿里不怕挑战。双方将在所有领域缠斗:拼多多将竭力打入中高端品牌,加强履约能力,发展直播等内容电商业务;阿里将通过聚划算/淘宝低价版进攻拼多多,并努力守住中高端品牌。我们无法预测战斗的结局——决定胜负的是执行/运营,而非战略。我想知道:当拼多多突破2万亿GMV时,它的下一个主力增长引擎是什么?增长会结束吗?会趋于平缓吗?如果还能继续高增长,会不会是因为某种我们尚未意识到的因素?

    (任何人都必须亲手打下自己想占领的地方)

    9.游戏行业:腾讯、垂直品类及海外市场

    可以认为,2020年的游戏市场将围绕着三个主要因素运行:第一是腾讯,它的DNF、LOL手游注定震动全世界,并为“端转手”时代画上一个句号;第二是垂直品类,2019年的《明日方舟》《闪耀暖暖》《隐形守护者》打开了几个突破口,后继者们会拼命扩大突破口;第三是海外市场,游戏的出海毕竟比其他内容和平台的出海更容易一点。

    如果腾讯的新产品取得意料中的战绩,垂直品类又依靠口碑效应不断做大,那么大部分“中等内容商/发行商”的空间可能被挤压。不过,也不能一概而论——与庞然大物的腾讯比起来,绝大部分游戏公司其实都是小公司。《明日方舟》那样的垂直爆款足够养活一家大型上市公司,就算《隐形守护者》的利润(几千万)也不算低。数以百计的游戏公司会涌入二次元、女性向、超休闲等垂直品类,以及开放世界、VR/AR等新玩法。

    游戏行业的成长期还能持续几年?我一贯不赞成用人口学分析这个问题。时至今日,手游用户看起来很多,但是大部分付费仍然来自30-40岁的男性,其次是高中生/大学生。女性用户只得到了部分开发,更不要说真正意义上的中老年人了。在互联网内容领域,游戏行业的战斗力最强、创新精神最高,这就是我看好它的原因。下一个突破性的创新会出现在哪里?我认为是互动叙事和VR/AR。拭目以待吧。

    (永远不要小看市场上现存的领导者的实力)

    10.短视频/直播行业:快手与抖音的决战?

    快手和抖音都在逼近自己的“天然用户上限”,并早已互相抢夺用户。它们都不缺钱:我们估计2019年快手的营业收入约550亿,抖音约700亿(不含头条系其他应用)。过去几年,两家很大程度上还是井水不犯河水;2020年,残酷的直接竞争会成为主流。我相信两家都会生存下来,定位日益模糊化、全面化;其他短视频平台会越来越没有生存空间。

    在秀场直播和电商领域,快手、抖音先后证明:短视频的巨大、高黏性用户池,可以被导向其他功能,并且快速变现。下一步还能导向哪里?游戏、电竞直播、自营电商、长视频?关键不能为了取金蛋而杀金鸡——短视频社区的调性和黏性还是最重要的。抖音的产品思路更特异、更“非标”,所以向其他功能的扩充稍慢,但是广告变现能力极强;快手与之恰好相反。

    在目前的时间点,我的预测是:快手会跟腾讯合作加大流量基础并探索更高效的广告变现,而头条系会越来越多地尝试自有电商;两家都会坚定不移地向内容端扩张,这个内容端不仅包括游戏、短视频,还包括影视、VLOG、二次元等一切内容形式。还是那句话:两家都可以生存、壮大下去,但是成长路径会越来越相似。如果一定要有一个赢家,那会是谁?我心里有一个答案,但是现在不想说。

    (无论面对多么强大的对手,也要狠狠的打)

    11.互联网广告:“品效合一”就是效果吃掉品牌?

    2017年以来,随着抖音的崛起,短视频广告大显神威。我们估计,今年抖音、快手两家的广告收入之和超过700亿元(还不包括电商带货收入)。短视频广告效果很好、用户体验不错、形式灵活,还能维持一定的品牌调性。从这个角度看,广告主确实不需要维持大而无当的品牌广告预算。尤其是在经济不景气的情况下,任何人都希望广告带来立竿见影的销量增加。

    微信朋友圈广告已经于2019年全面效果化。B站开始尝试短视频带货。芒果TV正在策划第一款带货主题综艺。总而言之,效果(CPA/CPS/CPL/ROI考核)广告仍在不断扩张地盘,而且自己也在进化。头条系的广告销售甚至可以比客户还懂ROI,能够随时拿出几套可行的广告销售框架。这就是腾讯广告一直无法打败头条系的主要原因(而不是像很多人想象的那样因为“没有技术中台”)。

    什么样的平台、什么样的形式最适合效果广告?首先,你要有调性(又是这个虚无缥缈的词,但现实就是如此)、有特色;其次,你要有一定的交互性或社交性;再次,你要具备灵活的投放方式和较快的响应速度。抖音、快手满足上述所有条件,B站、微信朋友圈也满足。如果还有满足上述条件的垂直平台,无论用户基数如何,单用户变现效率都不会太低吧?2020年,会不会有这样的垂直广告平台崛起?我觉得有可能,但我不知道是谁。

    (越是残酷的战斗,越会让人肾上腺素飙升)

    12.音频/音乐:互联网最后的流量洼地?

    显然,用户时长争夺战已经接近尾声。2019年底,中国智能手机用户的日均亮屏时间约4.5-5.0小时,已经接近了生理极限。人总不可能一天到晚盯着手机看。只有在一种情况下,用户不用盯着手机,甚至不用亮屏:音频娱乐,包括音乐、FM、知识付费等。这可能是移动互联网最后的流量洼地了。腾讯音乐、荔枝FM均已上市或申请上市,网易云音乐、喜马拉雅也快了。

    我完全不担心音频娱乐的流量前景——现在的音乐/音频类应用,尚未达到历史上广播/录音机达到的高度的一半,也还没有彻底占领用户心智。物极必反,人们总会对“手机亮屏”这件事情厌倦。听书、听音乐、听相声都是很好的娱乐方式。而且,正因为不用亮屏,音频类App可以长期留驻后台,不用加入各类App的用户眼球截流大战(如果你用的是安卓手机,肯定对此深有体会)。

    问题出在商业化方面——音频娱乐的广告前景肯定比不上视频/信息流(在广播时代就是如此);如果要依靠付费订阅,它比长视频也不会有什么优势;如果依靠知识付费呢?现在,知识付费基本还是以冲动付费为主,尚未形成稳固的行业体系。按照互联网行业的惯例,一律是圈占用户,再慢慢考虑变现;但是现在音频娱乐的用户已经圈占的差不多了。腾讯音乐通过直播这种“亮屏娱乐方式”实现了快速变现;其他平台呢?我很看好这条赛道,但是我没有答案。

    (在明年的战局开始之前,先观赏一下这个雕塑吧)

    提前祝各位圣诞节和新年快乐!希望明年是一个大有成果之年——在问题之中解决问题,乃是互联网行业的发展之道,也是这个世界的发展之道。



    本话题在雪球有11条讨论,点击查看。
    雪球是一个投资者的社交网络,聪明的投资者都在这里。
    点击下载雪球手机客户端 http://xueqiu.com/xz

    再谈企业中台(12.02)

    $
    0
    0


    首先我再整理下我原来提到过的一些关于企业中台的观点

    1. 企业中台是企业共性业务能力的下沉,体现的是业务能力可复用和灵活组合
    2. 企业中台区别传统的IaaS和PaaS平台,更多是一个业务平台,包括了业务中台和数据中台
    3. 中台构建本身参考了微服务架构思想,并基于业务高内聚进行了微服务化并提供能力

    对于一个专业细分的业务领域而言,软件企业要做的就是将对业务领域的多年经验和理解沉淀到业务中台,形成可复用的各个业务中台能力中心,然后为上层灵活多变的各类应用提供服务能力。由于沉淀了业务理解形成通用化,可复用的业务模型,那么这个能力被不会轻易被模仿。

    而今天当我重新再谈企业中台的时候,可以理解为:

    业务平台+能力开放平台 构成了企业中台,即业务平台各微服务模块化后的业务中心首先提供可复用的业务能力API接口,然后这些接口能力再通过能力开放平台开放出去并统一管理。

    今天我再谈这个概念,主要是想从如果一个企业邀请我们去将中台建设,那么从售前方案PPT的角度我们应该如何来准备材料来说明企业中台的建设思路和解决方案?

    其一,中台思路的产生

    首先还是要先讲清楚为什么会产生中台的概念,中台的提出和中台的产生背景。这些还是得介绍清楚。同时在介绍这些的时候还是要谈到SOA,可以看到前台和后台分离,中台提供能力,前台可以基于中台能力快速的构建应用本质还是SOA的核心思想,即原来讲过的可重复服务识别,服务能力的组装和组合。

    那么中台思路和原来的SOA的思路差别点在哪里?

    从我原来对SOA架构思想的描述,到中台的核心构建可以看到,SOA更多的是遗留系统本身的可复用接口服务识别,形成共享服务能力层,对遗留系统本身是一个简单的适配过程;而对于中台思想下可以看到完全是一次重新构建过程,这种重新构建的体现在。

    传统模式更多的是垂直化的业务系统构建模式,而中台思路下不再有明确的单垂直化业务系统的概念,而本身就是为了打破原来垂直化竖井的边界,因此采用的是一种分层构建的新IT应用构建模式。

    其二,从SOA到微服务,中台演进的必然之路

    前面已经讲到了中台本身就是一个能力提供中心,而这个能力中心本身不再是简单的遗留系统暴露接口的适配和发布,而是微服务能力+能力开放API接口,这个是和传统SOA架构和业务系统集成下一个很大的区别点。正是这个原因我们讲从SOA到微服务,是中台演进的必然之路。

    那么又得讲清楚什么是微服务?SOA和微服务架构的区别点在哪里?在采用了微服务架构后真正带来了哪些复杂度,同时在采用微服务架构后又面对哪些挑战。

    从SOA到微服务,本周管理的粒度更加细,管理复杂度实际是增加了,为了更好的进行模块开发和持续集成,配套开始介绍下DevOps和容器化技术。

    其三,构建核心中台层能力(中台微服务模块+API接口服务)

    要将企业中台的构建本身又需要分为好几个方面来讲。其中包括了业务中台的构建和数据中台的构建。而对于业务中台的构建本身又包括了由已有的遗留系统和IT资源来构建中台,还是全新构建中台。

    构建中台核心要做哪些事情?可以看到重点就是要搞清楚重点就是识别中台应该包括哪些微服务模块,同时每个微服务模块究竟应提供哪些API能力接口?其次才是单独的一个中台模块如何进行开发建设,API接口如何进行开发并能力开放。

    即中台的构建部分一定包括两个方面的内容,业务咨询和规划,技术实现两个层面。业务咨询规划解决的是中台模块如何划分,接口服务如何识别?而技术实现解决的是采用微服务开发框架如何开发,API接口如何开发和接入等技术层面的问题。

    其四,构建能力开放平台(API接入+能力运营+管控运维)

    这块感觉可以单独拿出来讲,即传统业务系统集成我们更多讲的是ESB服务总线,共享服务平台。而在企业中台构建思想下,我们讲的是API服务网关和能力开放平台,即是一种轻量的SOA服务总线。

    业务平台+能力开放平台 构成了企业中台

    中台构建完成后必须要将能力以API接口服务的方式暴露出去给前台用,因此有必要单独介绍下能力开放平台,刚开始可以是简单的API网关,但是要实现更好的接口服务运营和管理运维,则需要进一步将API网关引擎升级为完整的能力开放平台。

     

    [译]配置 MySQL 主主复制

    $
    0
    0

    原文: How to Setup MySQL Master Master Replication by Andy Hayes。

    MySQL 主-主 复制 ( master master replication), 也叫做 mysql chained replicationmulti master replicationmysql daisy chaining replication, 它是MySQL复制功能的扩展(普通复制功能见文章下半部分),允许创建多个主服务器,并且主服务器可以绑定多个从服务器。

    本文介绍设置主-主复制的方法。

    在多主 mysql的配置中,除了第一个主服务器外。其它添加的主服务器既当作主也当作从。因此,可以将每个添加的从服务器变为主服务器。

    看上面的图,可以比较直观的看出主主复制的配置。

    在本教程中,我们使用三台服务器(实例)做例子;两个主一个从,但是首先会介绍为什么我们想要设置这种链式复制模式。

    本文假定mysql其它的配置已经设置好了,我们只关注配置复制功能。

    主-主复制应用的场景

    • 数据库迁移
    • 提升复制的性能

    使用主-主复制帮助数据库迁移

    我最近遇到了一个大数据库迁移项目,我们不得不迁移几百GB的数据到线上服务器。数据库位于两组数据库上,它们会被整合到一组数据库中。每次迁移都会在不同的日子进行。迁移之后,应用会被重新上线,宕机的时间要尽量的少。

    备份和恢复数据库的常用方法包括 mysqldump或Percona Xtrabackup等工具。备份和恢复大的数据库是相当耗时的,尤其是使用mysqldump,所以我决定在每种情况下都让当前的数据库和新生产环境中的数据库保持同步。

    使用多主提升同步的性能

    系统架构师、应用架构师和数据库架构师使用MySQL数据库的一个主要原因就是可以水平的扩展数据库,使用一个或者多个从扩展读操作。

    当每个从服务器连接到主时,它会在主服务器上产生额外的负载。每个从服务器必须接收二进制日志的完整副本。在有许多从服务器的环境中,这会增加主服务器上的网络负载,而主服务器开始成为瓶颈。此外,主服务器还不得不处理一部分请求,包括写入请求。

    添加一个额外的主服务器作为从有助于分担主服务器的负载, 并且这种配置模型还可以自由扩展,以便可以创建多个次主服务器,所有这些次服务器都作为主服务器的从,具体配置取决于具体的需求。

    配置概览

    所有修改都会被持久化到 my.cnf文件中并持久化,mysql实例会被重启。

    主服务器 (primary)

    • 开启 binary log
    • 创建允许 secondary master server 连接的用户

    主服务器 (secondary)

    • 开启 binary log
    • 开启 relay log
    • 允许 log slave updates
    • 创建允许slave连接的用户
    • 指向 primary master log position

    从服务器 (作为secondary master server的从)

    • 允许 elay log
    • 指向 secondary master log position

    详细步骤

    配置的改变

    下面的截图显示了我在虚拟机中对 my.cnf所做的改变。

    主服务器的配置 (primary)

    次主服务器的配置(secondary)

    从服务器 (作为次主服务器的从)

    与标准复制一样, binary logrelay logs通过 log-binrelay-log参数进行设置。配置中需要额外设置的是 log-slave-updates,这个参数告诉次主服务器记录主服务器的改变到它的 binary log中,这样从服务器才能读取到这些改变。

    在主服务器上创建一个复制账号, 允许它的从使用这个账号可以连接

    1
    GRANT REPLICATION SLAVE ON *.* TO 'user'@'host' IDENTIFIED BY 'SecurePassword';

    找到主服务器的日志文件和位置,应用到次主服务器上

    1
    2
    3
    4
    5
    6
    7
    8
    SHOW MASTER STATUS\G;
    *************************** 1. row ***************************
    File: mysql-bin.000001
    Position: 897
    Binlog_Do_DB:
    Binlog_Ignore_DB:
    Executed_Gtid_Set:
    On the secondary master execute this changing to your host, user, log file etc accordingly:
    1
    2
    3
    4
    5
    6
    CHANGE MASTER TO
    MASTER_HOST='primarymaster.home',
    MASTER_USER='replication',
    MASTER_PASSWORD='SecurePassword',
    MASTER_LOG_FILE='mysql-bin.000001',
    MASTER_LOG_POS=897;

    完成之后执行下面的命令启动从复制:

    1
    START SLAVE;

    检查次主服务器的同步状态:

    1
    SHOW SLAVE STATUS\G;

    如果复制正常,你会看到下面的几行:

    1
    2
    3
    4
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Last_Error:
    Seconds_Behind_Master: 0

    在次主服务器和从服务器上执行步骤 2 和 3

    步骤相同,依次增加账号、主地址、日志文件和位置。

    测试

    在主服务器做一个更新操作,比如创建一个数据库,检查这个更新操作是否应用到次主服务器和从上。

    总结

    mysql 主-主复制可以很好的提升复制的性能,或者在数据库迁移的时候执行数据库的同步。

    更多的信息你可以看官方文档: 16.3.6 Improving Replication Performance


    作者还了一系列关于mysql的文章,其中还介绍了如何配置主从模式,一并翻译,整合在这一篇文章中。

    MySQL 主从配置

    通常,可以配置MySQL复制实现规模扩展、方便提供报告或者提供MySQL数据库的备份。我以前写过一篇关于这个的 文章

    整个过程依赖于二进制日志( binary log),这些日志被输出到主服务器上的某个文件夹,从服务器读取这些日志并应用保持和主服务器的同步。

    本文是一篇MySQL复制教程。我将设置MySQL复制功能,使用了两个MySQL服务器,一个主服务器和一个从服务器。本文假设服务器是新的,并且还没有在它们上创建数据库。

    我不会列出所有可能的设置或配置。只是必要的复制设置。

    需要对主服务器和从服务器的mysql配置文件进行更改。确保mysql配置文件中没有会导致任何网络问题的设置。关闭 –skip-networking,并且确保 –bind-address设置正确。

    主服务器复制功能的基本配置

    • server-id:在配置中的每一个服务需要一个唯一的id, 起始 1, 最大 2^32
    • log-bin:二进制文件的前缀, 一般设置为“mysql-bin”, “bin-log” 等等。文件会写入到你指定的文件夹中,当然运行mysql的用户需要写入权限。
    • expire-logs-days:二进制文件保留的最大天数。谨慎设置这个值,确保从服务器如果同步慢的话不会因为文件永久删除导致丢失数据。
    • binlog-format:仔细阅读关于这个参数的官方文档,非常非常的重要。如果设置不正确则意味着你的从可能包含和主不一样的数据,可选的值为 STATEMENT, ROWMIXED

    配置完之后重启你的mysql服务,检查这些变量,看看文件夹下二进制文件是否存在。

    从服务器复制功能的基本配置

    • server-id:在配置中的每一个服务需要一个唯一的id, 起始 1, 最大 2^32
    • relay-log:– 从会读取它自己的relay log, 并且应用复制过来的命令到它自己的数据库中。舍不设置它并不重要因为服务器自己会创建relay log,但是我总是显式设置它,这样我就能确保这些日志文件输出到哪里。当然需要确保运行mysql的账号要有写入这个文件夹的权限。

    配置完之后重启你的mysql服务,检查这些变量是否已持久化。

    对于其它一些有用的可选配置,检查官方的 文档

    在主服务器上创建复制数据的账号

    从需要认证才能连接到主上,你需要在主上创建一个账号,以便从使用这个账号连接主。

    虽然你可以使用一个已存在的账号,但是实践上不建议你这么做,原因有二:

    • 如果必须停用这个账号:使用这个账号的某人离开了公司或者某些应用的登录不再需要,这会导致复制中断。
    • 权限:复制需要特定的操作权限,你应该创建你的mysql账号,仅仅授权给它这些特定功能的权限。
    1
    GRANT REPLICATION SLAVE ON *.* TO 'replication'@'yourhostname.com' IDENTIFIED BY 'EnterSecurePasswordHere';

    记录主机上二进制日志文件和位置

    二进制日志文件的目的就是用来记录主上的改变,这些改变需要同样应用到从上。您需要找到主二进制日志的文件和位置(偏移)并将其记录下来,然后将其应用到从服务器。当从复制启动时,它需要知道在哪个日志文件中的哪个点开始读取主服务器数据库的副本并对其应用更新。

    您应该阻止对主服务的任何更新,然后记录日志位置。使用一行命令很容易做到这一点:

    1
    FLUSH TABLES WITH READ LOCK;

    保持这个连接窗口,新建一个到主的连接窗口,运行下面的命令得到位置:

    1
    SHOW MASTER STATUS;

    你会看到当前主正在写的文件以及当前log的位置,这些信息会用来配置从:

    1
    2
    3
    4
    5
    6
    7
    mysql> show master status;
    +------------------+----------+--------------+------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+------------------+
    | mysql-bin.000002 | 154 | | |
    +------------------+----------+--------------+------------------+
    1 row in set (0.00 sec)

    使用主的信息配置从

    连接到从,使用 CHANGE_MASTER_TO配置从:

    1
    2
    3
    4
    5
    6
    7
    8
    CHANGE MASTER TO
    MASTER_HOST='master.yourdomain.com',
    MASTER_USER='replication',
    MASTER_PASSWORD='EnterSecurePasswordHere',
    MASTER_PORT=3306,
    MASTER_LOG_FILE='mysql-bin.000002',
    MASTER_LOG_POS=154,
    MASTER_CONNECT_RETRY=10;

    在从上,运行下面的命令:

    1
    START SLAVE;

    解锁主并检查主从状态

    在主上运行:

    1
    UNLOCK TABLES;

    在从上运行:

    1
    SHOW SLAVE STATUS;

    检查看看是否有错误,确保你上面的设置设置正确。检查 Master_Log_FileRead_Master_Log_Pos

    1
    2
    Master_Log_File: mysql-bin.000002
    Read_Master_Log_Pos: 154

    测试

    在主上创建一个空的数据库,确保从上也会创建这个空的数据库。

    如果同步正常你可以准备在主上加载数据。

    这是一个基本的mysql主从配置的教程。推荐你阅读官方文档了解mysql的 主从复制的配置


    谈业务中台模块识别(12.03)

    $
    0
    0


    注:图片来源于阿里云栖大会相关材料

    再谈业务中台前,首先看下对于中台原来我们一般说法就是包括了业务中台和数据中台,而现在另外一种说法是包括了业务中台,数据中台,技术中台和AI中台。而实际上 对于技术中台不建议划分到中台里面,可以划分到底层的技术支撑平台,属于技术PaaS平台的一部分。而对于AI中台单独划分出来本身也没有必要,AI中台可以划分到数据中台的大范畴里面。

    就拿企业来说,中台的构建本身包括了业务中台和数据中台,按道理应该是先考虑业务中台如何构建,再基于构建好的业务中台来构建数据中台。但是也有企业由于遗留系统很多,并没有参考理想的方法去构建完整的业务中台,而是直接去构建数据中台。数据中台安装全新的方法去构建,替代传统的ODS加数据仓库的构建方法。

    对于数据中台的构建,我们后面再展开分析,今天还是想再谈下业务中台的构建。

    先看下传统的业务系统规划和构建思路,我们讲过更多的是业务和流程驱动型构建模式。简单来说就是,我们先分析清楚在业务上有哪些流程需要支撑,哪些业务需求需要支撑,然后基于流程逐层分解的方法来分析整个业务架构,基于业务架构再来分析数据架构,最后结合业务+数据架构来分析需要规划建设哪些业务系统或子系统。最后才会去考虑数据如何落地到数据库,应该有哪些数据对象和建立哪些数据库表。

    以数据驱动先行的思路来考虑中台模块的识别

    而对于业务中台的构建思路,我们这里给出一种新的构建思路,即数据驱动型的构建思路,对于切入你还是可以从端到端流程切入,但是只需要初步分析顶层业务流程即可,不需要进行详细的业务流程分析和分解,并规划业务架构。而是先进行数据架构规划和数据域划分。

    即流程并不需要分析的太细,你实际上已经能够完全了解企业核心基础主数据和核心共享数据。这个时候你已经可以梳理出比较粗的数据架构模型。找到核心的业务对象(基础主数据和核心共享数据)。

    同时我们也初步定义了数据域和数据边界。那么这个数据域和边界的划分是否合理?

    这又得回到我们前面分析的端到端流程,即还是需要根据端到端的业务流程来进一步试算和演练我们的数据域划分是否合理,即在端到端流程协同的时候是否会出现底层数据域之间的频繁交互和协同,如果存在多个数据对象间频繁交互,那么这些数据对象往往不能进行拆分,否则就可以拆分。

    同时我们看到以核心基础数据和共享数据为主体进行数据分域,分域后形成的各个数据域本身之间满足松耦合的要求,那么这些分离出来的数据域就是独立的中台各个业务能力提供中心。类似我们常说的订单中心,合同中心,项目中心,产品中心,用户中心,供应商中心,物料中心,客户中心等。

    在这个过程中你会发现供应商和物料之间的耦合性很强,那供应商+物料可以规划在中台的一个中心,一个微服微模块里面来实现。类似框架协议和采购订单,也需要放在一个中台中心一个道理。

    以对外流程协同,对内数据能力提供两条线来考虑中台模块接口服务识别

    如果中台模块已经识别出来,那么接着就需要去思考每个中台模块究竟需要提供哪些接口服务能力。而这种接口服务的识别,我们考虑两条线相互结合的方式进行。

    其一,是根据中台模块的核心数据对象来思考应该包括哪些数据接口服务能力,你可以理解为你先不用去思考需要支撑上层哪些业务功能和流程,就是将你已经识别的基础主数据对象和核心共享数据的CRUD能力暴露出现。但是这个暴露本身和简单额暴露数据库表有差异,这里暴露的应该是核心领域对象和数据对象,这个对象可能是底层多张数据库表。

    即将底层数据库表,以领域对象模型聚合后的思路将API接口暴露出去。同时我们还需要初步分析哪些能力是不需要对外开放的。比如一些数据对象只需要朝外暴露查询能力接口即可,而有些业务对象则需要暴露CRUD的所有能力,这个也需要分析清楚。

    其二,仍然是结合端到端交互流程,或者你也可以是理解为前台需要实现的业务场景和流程,来分析究竟中台模块需要提供哪些能力,要知道通过第一点往往并不能识别出来所有的中台模块应该提供的API接口服务,特别是一些涉及到业务规则和逻辑的接口服务能力,因此在这里还需要继续识别还需要哪些接口服务,这些接口应该确保粗粒度和可重用。

    简单的类似业务对象状态便跟的一个接口服务能力,在第一种方式下我们往往并不会单独将其识别出来定义为一个独立的API接口服务,但是基于业务场景分析后发现有这个需求,那么就需要单独定义接口。

    所有中台的构建目的都是为了更好的为前台业务功能实现服务,因此结合前台的业务场景和功能需求来进一步识别需要暴露的接口服务能力是必须的。即我们要意识到前台的构建更多的都是组装中台层各个微服务模块暴露的API接口服务能力,而不是自己去实现这个能力,前台可能有自己独立的数据库,但是这个数据库本身也很轻,只会存储一些临时的或局部使用的数据信息。

     

    等保2.0正式实施,这些重点帮你划好了

    $
    0
    0

    前言

    12 月 1 日,等级保护 2.0 标准正式实施,不过因为是在年底,大多数企业等级测评工作已经完成,所以重头戏应该在明年,这也是国家给企业充足的学习和整改时间。那么,在这个空档期,来和大家聊聊等级保护 2.0 测评时有哪些需要关心的重点吧。

    有关新老标准的变化,可以参考 之前文章或三所的解读,不再重复,这里说说比较接地气的东西吧。

    这里总结了一下,针对通用安全部分,三级和四级系统共有 45 条新增以及容易被忽略的要求向,如下表所示:

    image001.png

    下面将会针对这些要求项逐条进行说明。

    技术部分

    安全物理环境

    1.机房出入口应配置电子门禁系统,控制、鉴别和记录进入的人员

    image002.jpg

    按照以前的标准,门禁系统可以不是电子系统,可以通过流程和人来管控,但在新的标准中要求必须是电子门禁系统,即使流程管控再严格也是不符合要求的。

    2.重要区域应配置第二道电子门禁系统,控制、鉴别和记录进入的人员(四级)

    针对四级系统的要求,通常机房中会按照区域进行划分,但是对于重要区域的二道门禁,一般机房目前并无配置,因此这点要注意,尽快安装配备相应设施。

    3.应采取措施防止静电的产生,例如采用静电消除器、佩戴防静电手环等

    本项其实不算大事,但是也是容易忽略的问题。往往进了机房习惯性的上机就开始操作,不做除电。这里可以在每排机柜上配备一个防静电手环,在机房制度中新增一条关于静电消除的操作规范要求,基本可以符合。

    4.应设置冗余或并行的电力电缆线路为计算机系统供电

    要求三级及以上系统所在的机房要具备双路并行电力线路,来自不同供电站的电缆,目前大多数自建机房应该是不符合要求,大型 IDC 和云机房通常都有相关设计。不过介于整改比较困难,应该不会作为否决项,只是扣分而已。

    5.应提供应急供电设施(四级)

    image003.jpg

    1000kw 柴油电(guai)机(wu)

    针对四级系统的电力要求,基于三级要求,还要额外配备发电机,以应对市政停电情况。标准中并未提到双发电机的要求,但是介于冗余性考虑,有条件的可以配备。如果是大型数据中心,要配置多少台就要看实际规模了,一般是在 10-20 台的机组,采用 2N 或 N+1 的配置模式。这不是我们需要关心的,所以看看就好。

    image004.png

    数据中心柴油发电机室

    安全通信网络

    1.应在通信前基于密码技术对通信的双方进行验证或认证(四级)

    通常默认情况,我们 SSL/TLS 的认证是单向的,即只对服务端认证,那么对于四级系统,新标准要求必须开启双向认证,即同时对客户端也要进行认证。这里额外说明一下,根据公安三所专家的解读,通信加密所采用的算法应该基于国密算法(SM1、SM2、SM4、SM9 等),而非国际通用加密算法,不过介于目前大多企业采用的设备不支持国密算法,另一方面国密算法的推广和应用也在逐步完善,因此个人认为此项也非否决项,只是扣分项,不过未来可能会变为强制要求。(有关双向认证的细节,可参考本人之前发表的等保 2.0 个人解读安全通信网络部分)

    安全区域边界

    1.应能够对非授权设备私自联到内部网络的行为进行检查或限制(入侵检测)

    2.应能够对内部用户非授权联到外部网络的行为进行检查或限制(行为管理)

    此处两条是东西向的访问检测与限制,目前通过 IDPS 以及行为管理设备基本可以满足相应要求,测评时可能会查看策略启用效果以及检测和阻断记录,需要注意。

    3.应限制无线网络的使用,保证无线网络通过受控的边界设备接入内部网络

    首次在标准中提到有关无线网络安全的要求,这里要求比较基础,只要各无线 AP 或无线路由均通过 AD 进行管理和控制即符合。

    4.应能够在发现非授权设备私自联到内部网络的行为或内部用户非授权联到外部网络的行为时,对其进行有效阻断

    这部分在等保 1.0 中也有过相关要求描述,但没有如此具体,该项要求完全从技术上解决目前基本不太可能(当然,如果企业具备将附近基站的数据和语音分离的权限,那么这想倒是可以从技术上来搞定),通常是管理为主,技术为辅的方式来控制。毕竟个人热点和无线网卡等应用,很难及时发现。建议重点在制度上入手,形成意识、管理、流程上的多方面管控,以此达到要求。

    5.应删除多余或无效的访问控制规则,优化访问控制列表,并保证访问控制规则数量最小化

    新要求,重点是要定期优化和清理 ACL 以及策略路由等配置,测评时会查看当前安全策略配置以及规则优化和清理的记录。

    6.应在关键网络节点处检测、防止或限制从内部发起的网络攻击行为

    这里是对策略进行双向(in/out)应用,强调东西双向控制。

    7.应采取技术措施对网络行为进行分析,实现对网络攻击特别是新型网络攻击行为的分析

    强调对于 APT 和 0day 一类的攻击检测和防护能力,介于目前态势感知和威胁平台的水平,实现起来很难,而且不是每家都有这么强实力的安全团队。所以,如果你又某某家的态势感知产品,通常测评中心不会为难你。对于新型攻击,可以从人的角度(应急团队、安全团队)来强化管控和预警能力。

    8.应能对远程访问的用户行为、访问互联网的用户行为等单独进行行为审计和数据分析

    即对外接口的用户行为以及内部访问互联网的用户进行单独审计,如果在同一套审计平台中可以建立不同的审计任务,那么是可以满足要求的。如果不行,可能就要搭建两套审计平台来实现。不过也不是必须要达到的,属于扣分项。

    安全计算环境

    1.应能发现可能存在的已知漏洞,并在经过充分测试评估后,及时修补漏洞

    定期漏洞扫描工作,这次不是只扫描就 OK 了,对于发现的漏洞要进行验证,确认漏洞的真实性,然后对于真实漏洞进行整改。很刺激对吧,要验证了哦。

    image005.png

    2.应能够检测到对重要节点进行入侵的行为,并在发生严重入侵事件时提供报警

    这明显说的就是 IDPS 嘛,同行 NGFW 也具备同样能力。什么?你们没有防火墙,抱歉,我只能帮你到这里了,自求多福吧。这条可以直接否了你的本次测评。

    image006.png

    3.应提供异地实时备份功能,利用通信网络将重要数据实时备份至备份场地

    在老标准的基础上,等保 2.0 标准明确提出实时备份至异地,不过好在是对于重要数据,这点各家根据实际情况来权衡吧。没有的话肯定是 GG 了,有的话看情况,不能做到实时,但是有异地备份,这算是基本符合,不会被判定否决,可以后期列入整改计划,逐渐完善。

    image007.png

    中小企业或者云上系统,可以把这锅甩给云供应商;大型企业和自建机房/私有云的公司,建议尽可能完善,不求有功,但求无过。其实基本上等同于双活,只是没提切换延时的要求。

    4.应仅采集和保存业务必需的用户个人信息

    5.应禁止未授权访问和非法使用用户个人信息

    这两条都是关于个人信息保护的要求,基本就如字面意思。稍微解释一下,一方面是采集个人信息时,只能采集所需的必要信息,对于这类信息你可以收集,但是若未授权不得随意访问和修改信息,也就是说,信息可以放在你们这,但是我不同意,你就不能看,除非协助公安和相关部门处理特殊事宜时的强制配合。

    image008.png

    另一方面,信息收集过来后,不可以随便向其收集发送各种推销、广告以及恶意链接,这些操作都不可以。也就是说,对于一些常规流氓操作进行了约束和控制,虽然不知道效果如何,但起码提出了相应要求。这方面,对于那些需要采集个人信息的系统,是比较难搞的一项要求。靠技术展示基本不大可能,所以就要尽可能的解释,从管理制度、操作规范、员工培训、惩罚制度、保密协议、流程管控方面来说明,你们做得如何好,基本这样就差不多了。但是,未来几年,数据安全是趋势,信息安全和隐私保护都在立法阶段,后续的监控也会越来越严,因此建议还是要从实际出发,不要只考虑眼前的测评,多想想以后怎么跟监管解释吧。

    安全管理中心

    1.应对分散在各个设备上的审计数据进行收集汇总和集中分析,并保证审计记录的留存时间符合法律法规要求

    2.应能对网络中发生的各类安全事件进行识别、报警和分析

    这两条要求是对日志留存的要求,等保 2.0 标准不再对日志留存时间进行要求了,但是对于全流量以及安全事件日志必须留存。那么是不是可以不用再存放 6 个月了呢?

    image009.png

    请看这里:

    网络安全法第二十一条:

    (三)采取监测、记录网络运行状态、网络安全事件的技术措施,并按照规定留存相关的网络日志不少于六个月。

    大家懂了吧,所以以前怎么干的,还怎么干。

    管理部分

    安全管理制度

    1.应制定网络安全工作的总体方针和安全策略,阐明机构安全工作的总体目标、范围、原则和安全框架等

    2.应形成由安全策略、管理制度、操作规程、记录表单等构成的全面的安全管理制度体系

    3.应定期对安全管理制度的合理性和适用性进行论证和审定,对存在不足或需要改进的安全管理制度进行修订

    这三条要求中,等保 2.0 标准均有所变化,尤其最后一条,要对合理性和适用性进行论证,那些模板的东西已经没用了。

    那么怎么来改呢?方针和策略一般公司都会有,如果没有的话,尽快制定 2020 的 IT 和安全规划,目标和策略其实可以很简单,好比阿里的三句话策略。但是要贴合实际,不要胡扯。

    那么策略、制度、规程、表单(ISO 27001 的四级文档)就会配套进行修订,形成一套体系,如果已通过 ISO 27001 认证的,可以以此来证明自己已有安全管理制度体系。没有的,要尽快建立一套贴合业务和 IT 现状的制度,可以简单点,只要能落地就好。

    最后,关于合理性和适用性,一般是对于制度和流程的落地试点情况。体系比较完善的企业,在制度发布或修订时会进行内部评审,通过后才可正式发布。没有相关流程的企业,可以将此作为缺失的环节,在后续制度体系中增加或完善相应管理。

    安全管理机构

    1.应成立指导和管理网络安全工作的委员会或领导小组,其最高领导由单位主管领导担任或授权

    这点很多公司都没做好,主要体现在两个方面。一是,领导小组架构和职责很明确,但是岗位责任人是职位(如总经理、安全部总监)而不是人名,这样就无法做到责任落实,不符合领导小组的初衷;二是,组长的任命是空口说的,没有正式的任命函或董事会级别的正式通知。这两点如果都能做好,基本就没太大问题了。

    2.应针对系统变更、重要操作、物理访问和系统接入等事项执行审批过程,对重要活动建立逐级审批制度

    老生常谈的事情,凡是和安全相关的过程记录都要留存(纸质或电子记录均可),这种东西一般不太好凭空去造,所以还是建议踏踏实实的去建流程,落实制度。流程可以不够全面,但是一定要能落地,能运行起来。

    3.应定期进行全面安全检查,检查内容包括现有安全技术措施的有效性、安全配置与安全策略的一致性、安全管理制度的执行情况等

    等保 2.0 标准强制要求,定期进行全面安全检查,不只是技术层面,也包括制度层面。通管局、工信部的安全检查是监管,不属于要求中提到的检查,要各企业自行组织开展,并形成报告、对发现的问题整改、复测整改情况等。今年没做,明年要至少进行一次检查工作,类似银保监的安全自查评估。

    4.应制定安全检查表格实施安全检查,汇总安全检查数据,形成安全检查报告,并对安全检查结果进行通报

    结合前一项要求,除了自评估安全检查,还要制定检查表,检查过程的现状调研和检查结果记录表单也要汇总保留。有点类似于风险评估,包括资产、威胁、脆弱性。这里提一句,某些厂商坑爹的评估也称为风险评估,希望各位多去看看 GB/T 20984,好好了解下什么叫风评,不要随便测测出个报告就叫风评。

    安全管理人员

    1.应定期对不同岗位的人员进行技能考核

    首次提出针对技能进行考核,也就是针对不同岗位(运维、安全、开发、测试等),进行相关技能培训与考核。可以不用针对每一个 IT 相关岗位,但是要有一定的覆盖度,比如今年我们主要侧重运维和安全,明年主要侧重开发和测试,同时在制度和培训考核计划中也要有体现。

    安全建设管理

    1.应组织相关部门和有关安全技术专家对定级结果的合理性和正确性进行论证和审定

    2.应组织相关部门和有关安全专家对安全整体规划及其配套文件的合理性和正确性进行论证和审定,经过批准后才能正式实施

    等保 2.0 标准开始,不再提倡自主定级,改为由专家进行定级。一般就是由测评机构或者知名安全厂商来进行定级,出具定级报告,其中包括评审和论证环节。可以是会议记录,也可以是最终的评审报告或定级报告。

    3.应根据保护对象的安全保护等级及与其他级别保护对象的关系进行安全整体规划和安全方案设计,设计内容应包含密码技术相关内容,并形成配套文件

    本项要求其实是对三同步的要求,即同步规划、同步建设、同步使用。本项不再多说,已经很熟悉了。

    (1)同步规划

    在业务规划的阶段,应当同步纳入安全要求,引入安全措施。如同步建立信息资产管理情况检查机制,指定专人负责信息资产管理,对信息资产进行统一编号、统一标识、 统一发放,并及时记录信息资产状态和使用情况等安全保障措施。

    (2)同步建设

    在项目建设阶段,通过合同条款落实设备供应商、厂商和其他合作方的责任,保证相关安全技术措施的顺利准时建设。保证项目上线时,安全措施的验收和工程验收同步,外包开发的系统需要进行上线前安全检测,确保只有符合安全要求的系统才能上线。

    (3)同步使用

    安全验收后的日常运营维护中,应当保持系统处于持续安全防护水平,且运营者每年对关键信息基础设施需要进行一次安全检测评估。

    4.应制定代码编写安全规范,要求开发人员参照规范编写代码

    5.应在软件开发过程中对安全性进行测试,在软件安装前对可能存在的恶意代码进行检测

    等保 2.0 标准首次提出安全开发流程的要求,可以理解为 SDL 体系。这里明确指出在编码阶段和测试阶段的安全性要求,均为上线前安全管控。以上两条是针对自研软件。

    如果没有建立 SDL 流程的企业,可以先解决安全编码部分的问题,编码规范应该都会有的。上线前的安全测试,这块内容目前大多都会去做,如果没做,那我敬你是个好汉。

    image010.gif

    6.应在软件交付前检测其中可能存在的恶意代码

    7.应保证开发单位提供软件源代码,并审查软件中可能存在的后门和隐蔽信道

    这两条是对外包软件安全的要求,也是首次提出要外包开发商提供上线前安全测试报告、代码审计报告以及源代码。这下甲方开心坏了吧,可以更理直气壮的怼乙方了,虽然以前一直都是。但是介于刚刚实施这么靠谱的要求,很多乙方是不接受的,一开始可以双方一起来进行安全测试;代码审计一般不会要求严格意义的代码审计报告,可以用扫描加人工验证的方式来进行;而对于源代码,很对乙方是说死不给的,可以先提交一部分源码。但这些都是应对本次测评的准备,从长远来看,以后对于外包开发要求会规范化,标准化,强制化。SDL 体系建立会成为趋势。

    8.应通过第三方工程监理控制项目的实施过程

    那么,除了以上这些,乙方觉得没事了么,呵呵。

    image011.png

    明年开始,外包项目需要聘请第三方监理,对整个项目过程质量进行把控和监督,并实时汇报和协调。也就是说,除了甲方怼你,以后还有一个第三方监理也要怼你,爽不爽?

    9.应进行上线前的安全性测试,并出具安全测试报告, 安全测试报告应包含密码应用安全性测试相关内容

    乙方的兄弟,你先别吐血,还没说完呢,这回不是你自己,甲方也要一样受苦,是不是好受一些了?这条要求也是首次提出,要求系统上线前的安全测试中应包含密码应用安全性测试。

    那么,这个密码应用安全性测试又是个什么玩意呢。这是我在查阅了相关制度和材料得出的结果:

    商用密码应用安全性评估

    指对采用商用密码技术、产品和服务集成建设的网络和信息系统密码应用的合规性、正确性、有效性进行评估。按照商用密码应用安全性评估管理的要求,在系统规划阶段,可组织专家或委托测评机构进行评估;在系统建设完成后以及运行阶段,由测评机构进行评估。

    哪些系统要做密评

    《密码法》(《密码法草案》已于 2019 年 6 月 10 日经国务院常务会议讨论通过)要求「国家对关键信息基础设施的密码应用安全性进行分类分级评估,按照国家安全审查的要求对影响或者可能影响国家安全的密码产品、密码相关服务和密码保障系统进行安全审查」。《信息安全等级保护商用密码管理办法》规定:「国家密码管理局和省、自治区、直辖市密码管理机构对第三级及以上信息系统使用商用密码的情况进行检查」。在国家密码管理局印发的《信息安全等级保护商用密码管理办法实施意见》中规定「第三级及以上信息系统的商用密码应用系统,应当通过国家密码管理部门指定测评机构的密码测评后方可投入运行」。这些制度明确了信息安全等级保护第三级及以上信息系统的商用密码应用和测评要求。此外,在新版《网络安全等级保护条例》(征求意见稿)明确要求在规划、建设、运行阶段开展密码应用安全性评估。

    密评关注哪些方面

    为规范商用密码应用安全性评估工作,国家密码管理局制定了《商用密码应用安全性评估管理办法》、《商用密码应用安全性测评机构管理办法》等有关规定,对测评机构、网络运营者、管理部分三类对象提出了要求,对评估程序、评估方法、监督管理等进行了明确。同时,组织编制了《信息系统密码应用基本要求》《信息系统密码测评要求》等标准,及《商用密码应用安全性评估测评过程指南(试行)》《商用密码应用安全性评估测评作业指导书(试行)》等指导性文件,指导测评机构规范有序开展评估工作。其中,《信息系统密码应用基本要求》从物理和环境安全、网络和通信安全、设备和计算安全、应用和数据安全、密钥管理以及安全管理六个方面提出密码应用安全性评估指标。

    密评工作当前的进展

    现阶段,商用密码应用安全性评估试点工作正在有序开展。经过层层评审,截止 2018 年 6 月第一批共有 10 家测评机构符合测评机构能力要求,具备独立承担并规范开展试点测评任务的能力。中科院 DCS 中心作为首批通过的优秀测评机构,正在积极参与密码应用安全性评估的各项试点工作,为我国密码事业的发展贡献自己的力量。

    个人感觉,这项要求类似可信计算,在标准实施初期不做强制要求,以鼓励方式建议企业开展,但在后期随着技术和要求的成熟,会逐渐成为强制要求项。所以,明年各位可以不用太担心,先了解一下就好。

    安全运维管理

    1.应编制并保存与保护对象相关的资产清单,包括资产责任部门、重要程度和所处位置等内容

    2.应根据资产的重要程度对资产进行标识管理,根据资产的价值选择相应的管理措施

    对于资产的管理要求,当前大多数企业拥有自己的管控平台,对于 IT 资产进行统一管理。主要就是资产梳理和分级分类。如果没有这类平台,可以用堡垒机临时替代一下,起码这里不会被扣成零分。

    3.应对信息分类与标识方法做出规定,并对信息的使用、传输和存储等进行规范化管理

    这里是对数据治理提出要求,在管理制度中明确对于信息资产的分类和标识依据和规范。目前大多企业属于空白领域,明年有关数据安全和数据治理会很热门,因为明年 3 月 DSMM 会正式发布。本项要求其实不用很在意,明年测评时除了一些大厂,大家基本同一起跑线,你没做我也没做,没关系,列入后续的工作计划中。

    4.应采取必要的措施识别安全漏洞和隐患,对发现的安全漏洞和隐患及时进行修补或评估可能的影响后进行修补

    这里的要求同前边安全管理中心的全面安全检查可以结合到一起来看,因为最终目的相一致,过程也相似。

    5.应严格控制远程运维的开通,经过审批后才可开通远程运维接口或通道,操作过程中应保留不可更改的审计日志,操作结束后立即关闭接口或通道

    等保 2.0 标准首次提出对于远程运维的要求,原则上不开通远程运维接口。注意,这里是说远程运维,而不是远程用户接入。通常运维人员一般都应该在机房或办公环境内操作,除非特殊情况,会进行远程运维操作,按照要求以后此类操作要事先审批,通过后开通临时接口,操作完成后关闭接口。

    如果没有远程运维需求的企业,这点不用关心。有些企业受业务所限,必须远程操作,那么就要按照要求把相关制度规定,流程,审批记录,操作记录,接口关闭记录都留存好,以备现场检查。

    6.对造成系统中断和造成信息泄漏的重大安全事件应采用不同的处理程序和报告程序(信息泄露应急预案)

    7.应定期对系统相关的人员进行应急预案培训,并进行应急预案的演练(出演练外,要组织应急预案的专项培训)

    这两条放在一起来说,都是新要求。先说第一条关于信息泄露重大安全事件,要建立独立处理和报告程序,不能同 BCP 程序一样。个人观点,可能除了应急处理外,大公司(阿里、腾讯)还要考虑对外公告和说明情况的流程。这部分,因为没有先例,所以不知道什么样的流程算标准方案。建议各家可以交流讨论下,也可以借鉴一下国外的预案。

    第二条比较好理解,也是新要求,说的是要针对应急预案每年进行培训,不是演练,是培训哦!测评时会查看培训的 PPT,以及培训签到记录(可以是电子记录)和培训计划。

    最后

    OK,以上是我认为等级保护 2.0 中新增的一些重点以及测评时要注意的内容,希望对各位能有所帮助。最后,祝贺等级保护 2.0 制度顺利实施,也预祝各位能早日通过新标准下的测评。文章只代表个人观点,仅供参考。

    *本文原创作者:宇宸,本文属FreeBuf原创奖励计划,未经许可禁止转载

    谈业务中台构建场景(12.04)

    $
    0
    0


    注:图片来源阿里云栖大会材料

    最近我谈企业中台的文章比较多,主要原因还是我们看到企业对于中台构建的需求越来越多,这里面有些企业是想参考互联网企业的最佳实践,觉得是业务和技术发展趋势,但是中台建设究竟提供哪些业务价值并不清楚,还有一些企业是确实明白了一点,就是我原来提到过的中台是企业核心共性业务能力下沉,是属于企业业务资产和核心竞争力。

    由于阿里提出了中台的概念,那我们看下阿里为什么会提出大中台+小前台的概念,为什么需要一个强大的中台?对于互联网企业来说,需要不断的根据市场的需求来调整自己的业务,同时快速的推出各种新的业务类型,类似我们经常看到的聚划算,旅游,团购,花呗等各种业务类型。而这些业务类型往往就需要有相应的业务APP来支撑,但是这些APP本身又是基于企业已有的大用户群基础数据和电商平台展开的,也就是说APP本身并没有产生太多核心业务数据,而是充分利用已有核心业务数据形成新业务类型。

    新的业务流程和业务流程最终执行完成后,核心数据还是回归到我们原来的业务对象数据库存储。

    也正是这个原因我们看到,新业务APP应用和构建很多时候都不是需要自己构建某个能力,而是充分的使用和组装已有的能力,这些能力就是中台提供出来的API接口服务,前台只需要组合和组装这些能力就可以快速的构建前台面向最终客户的应用。中台能力越强大,那么前台构建应用就越快速,这也就是中台的核心价值。

    把这个搞清楚后,我们再回到传统企业才清楚,哪些企业和这种场景最类似,最适合借鉴互联网的思路来进行中台能力建设。

    首先,我们认为对于面向客户的运营类企业适合中台模式

    如果一个企业更多的是面向客户的运营模式,那么这个企业和互联网企业运营很类似,也适合进行中台建设,然基于中台能力快速构建前台,并快速响应前台需求和业务的变化。从这个意义上来说,可以看到类似电信运营商,银行,政务服务中心是很适合采用这种模式来构建的。

    前台面向客户的业务类型不断在优化和调整,但是底层中台层能力却是越来越稳定。

    其次,就是所有企业涉及到外网生态类构建的业务场景

    一个企业涉及到财务,供应链,研发,生产各类核心业务,并不是所有的业务都需要构建强大的中台,也不是所有的业务经常都在发生大的变化。实际上我们看到企业业务经常需要灵活响应的就是涉及到市场营销方面的,已经和外围供应商,客户生态链构建方面的。

    因此如果一个企业自己搞类似垂直一体化电商运营平台,那么就时候建设一个强大的中台,将企业内部围绕ERP已有的核心能力重新规划重新,并通过中台的能力开放平台暴露出去,方便前台应用的快速构建。如果一个企业经常会做面向最终客户的应用或APP,那么就适合基于这个业务域来构建中台并提供能力。

    最后,企业本身就属于为上游企业提供支撑类服务的企业

    如果一个企业本身就不是最终的面对客户,而是为上游诸多的不同企业提供自己的能力,那么这个企业也时候构建自己的中台,将自己的能力以中台服务的方式暴露出去。通过自己构建的能力开放平台来衔接上下游的所有企业并构建自己的生态圈。

    这样企业可以更加专注自己能力层的构建,这个能力层是通用能力层,不会去考虑前台客户使用场景下的差异,只需要专注把这个共性业务能力建设好即可。

     

    下一代自动贩卖机如何支持烟酒药品销售?结合区块链与数字身份认证技术

    $
    0
    0

    限于身分认证技术,市面上的贩卖机不能贩售烟酒,区块链新创BiiLabs与业安科技创下全球首例,结合区块链与数字身份认证技术,让传统贩卖机一秒升级。

    「智能贩卖机」是今年商超共同的关键字,少了人工盘点存货,清点营收、销售的数据自动勾稽到邻近的超商门市,是替超商经营加值的秘密武器,校园、办公大楼、百货公司,都能见到贩卖机踪影。

    不过,受限于身分认证技术,市面上的贩卖机不能贩售烟酒药品等特种商品,甚至在很多骨架,你随时随地的想要来杯啤酒,也无法在贩卖机购买,仍必须靠人力设摊贩售,这样的痛点很快将成过去式。

    台湾区块链新创BiiLabs,与业安科技(Yallvend)、数字身份股份有限公司(AuthMe)创下全球首例,结合区块链与数位身分认证技术,让传统贩卖机一秒升级,即便是无人贩卖机,也能把身分验证做到滴水不漏,贩卖机经济将迎来更多新商机。

    日、德贩卖机卖烟酒,身分认证仍存在漏洞

    从国际案例观察,目前日本、德国都能在贩卖机贩售酒类与香烟。以日本来说,符合购买烟酒的法定年龄,就可以申请一张身分验证的实体卡,只要有这张卡,就能在贩卖机买烟;德国则是透过护照、身分证、驾照等证件,让机器验证购买资格。

    不过问题来了,无论是证件、购买凭证,贩卖机都没办法辨别购买者是否是证件拥有者,儿子拿爸爸的证件、跟年长的朋友借证件,一样都能购买成功,现行的身分认证机制,仍存在很大漏洞。

    目前日本、德国都能在贩卖机贩售酒类与香烟,但是现行身分认证机制,仍存在很大漏洞。

    区块链新创BiiLabs 与业安科技(Yallvend)想出了一个方法,他们将BiiLabs的去中心化身份识别(Decentralized Identifiers;DID)技术,结合AuthMe的专利e-KYC解决方案,与业安贩卖机升级模组整合,贩卖机若贩售须受购买年龄规范的产品,就能导入这套模组,一秒升级成具备数字身份验证功能的贩卖机。

    贩卖机结合数字身份认证,创下全球首例

    BiiLabs透过DID技术,结合AuthMe的e-KYC解决方案,让贩卖机得以用数字化的方式做身分验证,这样的作法是全球首例。

    第一要进行去中心化身份识别(DID),消费者必须先做「认识你的客户(Know your customer:KYC)」,简单来说就是验明正身。消费者必须对护照拍照,接着感应护照上的IC卡,最后再用手机对本人拍一张照片,完成以上程序后,就能取得DID的KYC。

    过去贩卖机做身分验证,最大的问题就是无法辨识站在贩卖机前面的这个人,是不是证件拥有者。当要购买时,透过扫码登入系统,用手机进行人脸辨识,当系统确定是本人后,手机会回传至贩卖机,站在机台前的这位消费者符合购买资格,才会扣款给产品。每次购买都需进行人脸辨识,只要网络顺畅都能在1秒以内完成身份验证。

    当要购买时,需透过扫码登入系统,用手机拍一张自拍照,当系统确定是本人后,手机会回传至贩卖机,确认购买者的资格。

    为确保身分不被窜改,手机进行身分验证时,会产生专属序号并签章,在验证确认前,透过API提供带有时戳(time stamp)的电子收据,将ID身份、购买日期与地点传回至贩卖机。除了确保贩卖机不会收到任何个资,又能确认购买人的真实身分,比起现行的机制都还要完善。

    为了避免人脸辨识过程,有造假的可能及漏洞,AuthMe的首席执行官表示,从晶片证件取得包含年龄、照片等资料,全都受到数字签章所保护,并无法被窜改,每次进行人脸辨识时,会检查照片之数字签章是否吻合。

    AuthMe所提供的技术,除了验证晶片证件资料及人脸辨识之外,更重要的是会透过AI进行活体辨识(Liveness Detection),来杜绝恶意使用者利用照片、影片甚至是3D列印的头像对系统进行欺诈,进而将使用者身分验证做到滴水不漏。

    台湾华山、松烟抢先实验,逛展时体验微醺畅快

    烟酒在世界各国都是较为敏感的产品,尤其每个国家的法规、实体证件、仿伪特征、资讯位置都不相同,要如何将数位身分验证技术,转移到不同国家的硬体周边,是团队在研发技术时,最主要的挑战。

    数字身份的概念,近年逐渐被各国政府接受,尤其贩卖机、无人商店等新兴商业模式的演进,BiiLabs共同创办人朱宜振认为,建立完整验证机制绝对势在必行。结合DID身份认证的智能贩卖机升级模组,是基于IOTA Tangle网络的分布式帐本技术,将资料储存至区块链中,能够应各国政府数字身份认证的差异,进而降低业者开发成本。

    一旦身分认证的问题可以被解决,这意味着,无人销售的商业模式,将迎来更多可能性。黄建尧透露,当技术开发完成后,计划明年第一季在华山、松烟申请实验场域,并与几个专注在特色啤酒的新创合作,推出具备数字身份验证功能的贩卖机,届时,在文创园区优游漫步时,也能透过贩卖机感受畅饮啤酒的快感。

    VisualVM分析与HelloWorld、springBoot项目 - metabolism - 博客园

    $
    0
    0

    VisualVM分析与HelloWorld、springBoot项目

    自从1995年第一个JDK版本JDKBeta发布,至今已经快25年,这些年来Java的框架日新月异,从最开始的Servlet阶段,到SSH,SSI,SSM,springboot等,还有一些其他方向的框架微服务SpringCloud、响应式编程Spring Reactor。零零总总 的框架,我们都需要去熟悉,那么怎么去快速熟悉呢,我觉得可以看源码,可以看博客,也可以根据内存分配去完善理解。

    那么问题来了,一个Java项目在咱们平时启动项目的时候,究竟发生了什么,创建几个简单的项目,用VisualVM来分析一下~

    Main

    简单的项目,应该没有比HelloWorld更简单的了吧,按照老规矩,咱们就从HelloWorld开始分析!那么简单的项目大家都能闭着眼睛敲出来,是不是没分析的必要啊,别着急,写好HelloWorld咱们开始分析:

    System.out.println("HelloWorld start");
    // 这里让线程睡一会,方便分析
    Thread.sleep(100000);
    System.out.println("HelloWorld end");

    运行main方法,打开VisualVM,发现事情并不简单哦,这个简单的项目有十六个线程维护,其中守护线程有十五个。

    其中几大线程的内存分配情况如下:

    这些线程都是干什么用的?写了那么多年HelloWorld没想到还有这种知识盲区:

    1. RMI TCP Connection(2)-10.128.227.33

      10.128.227.33是我本地的ip地址。正确而愚蠢的原因是因为开了VisualVM(JMX客户端),JVM需要把他的数据传递给这个客户端,就是使用的TCP传递,相同作用的线程还有 JMX server connection timeout:MAIN方法跑完了,JMX连接的心跳断开。 RMI TCP Connection(idle):用来在RMI连接池中创建线程。 *** Profiler Agent Communication Thread:Profiler代理通信线程。 RMI TCP Accept-0:进行JMX进行JMX监测。

    2. Attach Listener

      Attach Listener线程是负责接收到外部的命令,对该命令进行执行并把结果返回给发送者。通常我们会用一些命令去要求jvm给我们一些反馈信息,如:java -version、jmap、jstack等等。如果该线程在jvm启动的时候没有初始化,那么,则会在用户第一次执行jvm命令时,得到启动。

    3. main

      main线程,就是我们代码所写得代码对应线程

    4. Monitor Ctr-Break

      这应该是 IDEA 通过反射的方式,伴随你的程序一起启动的对你程序的监控线程。这也是一个默认全局线程

    5. Signal Dispatcher

      前面提到的Attach Listener线程职责是接收外部jvm命令,当命令接收成功后,就会交给signal dispather线程分发到各个不同的模块处理,并且返回处理结果。signal dispather线程是在第一次接收外部jvm命令时,才进行初始化工作。

    6. Finalizer

      这个线程是在main线程之后创建的,其优先级为10,主要用于在垃圾收集前,调用对象的finalize()方法;关于Finalizer线程的几点:

      1. 只有当开始一轮垃圾收集时,才会开始调用finalize()方法;因此并不是所有对象的finalize()方法都会被执行;

      2. 该线程是守护线程,因此如果虚拟机中没有其他非守护线程的线程,不管该线程有没有执行完finalize()方法,JVM也会退出;
      3. JVM在垃圾收集时会将失去引用的对象包装成Finalizer对象(Reference的实现),并放入ReferenceQueue,由Finalizer线程来处理;最后将该Finalizer对象的引用置为null,由垃圾收集器来回收;
      4. JVM为什么要单独用一个线程来执行finalize()方法呢?如果JVM的垃圾收集线程自己来做,很有可能由于在finalize()方法中误操作导致GC线程停止或不可控,这对GC线程来说是一种灾难,所以单独创建了一个守护线程。

    7. Reference Handler

      VM在创建main线程后就创建Reference Handler线程,其优先级最高,为10,它主要用于处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题。

    经过上面的分析可以看出来main本身程序的线程有:main线程,Reference Handler线程,Finalizer线程,Attach Listener线程,Signal Dispatcher线程。

    java代码想要实现也很简单,如下即可:

    // 获取java线程管理器MXBean,dumpAllThreads参数:
    //                                  lockedMonitors参数表示是否获取同步的monitor信息
    //                                  lockedSynchronizers表示是否获取同步的synchronizer
    ThreadInfo[] threadInfos = ManagementFactory.getThreadMXBean().dumpAllThreads(true, false);
    for (ThreadInfo threadInfo : threadInfos) {
        System.out.println(threadInfo.getThreadId() + " : " + threadInfo.getThreadName());
    }

    得到的打印结果为:

    也就是说,写了那么多年的HelloWorld居然有五个线程来支撑,而我却一直被蒙在鼓里??谁能随时去关注项目有多少个线程啊,VIsualVM可以= =,虽然我觉得他一直起线程进行通信很蠢,但是项目结构大了就有必要了。

    Spring-Boot

    那么一个啥都没有的springBoot项目启动了之后,会有哪些线程呢?先看看他的pom文件:

    <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.1.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.visual.vm.performance</groupId><artifactId>mock</artifactId><version>0.0.1-SNAPSHOT</version><name>mock</name><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

    只引入了spring-boot-starter-web的依赖,其他的什么都没有,启动着试一下。共有27个线程,守护线程有23个。

    不同的颜色对应着不同的状态,详情看右下角。这些线程很多都是熟悉的,Main方法分析过的,通过VisualVM工具进行JMX监视(RMI TCP...)开了些线程;IDEA(Monitor Ctrl-Break)开了些线程;垃圾回收(Finalizer,Reference Handler)开了些线程。着重讲一下没见过的线程。

    1. DestroyJavaVM

      所有 POJO应用程序都通过调用该 main方法开始。正常情况下,main 完成后,将告知JVM的DestroyJavaVM`线程来关闭JVM,该线程等待所有非守护进程线程完成后再进行工作。这是为了确保创建的所有非守护程序线程都可以在JVM拆除之前运行完毕。

      但是,带有GUI的应用程序通常以多个线程运行。用于监视系统事件,例如键盘或鼠标事件。JVM仍然会创建 DestroyJavaVM线程,且需要等待所有创建的线程完成,然后再拆除VM,然而应用并不会停止,所以DestoryJavaVM线程就会一直处于等待,直到应用运行完成。

      任何创建线程并仅依赖其功能的应用程序都会有一个 DestroyJavaVM线程,等待应用程序完成并关闭JVM。由于它等待所有其他线程执行完毕( join),因此它不会消耗任何资源。

    2. Http-nio-8080-AcceptorHttp-nio-8080-ClientPollerHttp-nio-8080-BlockPollerhttp-nio-8080-exec-1...10

      这些线程都有个特点,http-nio-8080开头。8080就是这个应用的端口,显然这是给容器使用的。项目引入的是spring-boot-starter-web依赖,也就是默认使用springBoot的内置tomcat容器启动,我们的maven下面也会有这样的几个包: tomcat-embed-coretomcat-embed-eltomcat-embed-websocket,我们所看到的线程都是由这几个包产生的。那么这些线程是干什么用的?

      解决这个问题之前,先看一下tomcat的总体架构:

      Tomcat由Connector和Container两个核心组件构成,Connector组件负责网络请求接入,目前支持BIO、NIO、APR三种模式,Tomcat5之后就支持了NIO,看我们的线程名也就是用的NIO;Container组件负责管理servlet容器。service服务将Container和Connector又包装了一层,使得外部可以直接获取。多个service服务运行在tomcat的Server服务器上,Server上有所有的service实例,并实现了LifeCycle接口来控制所有service的生命周期。

      而NIO对应线程主要是实现在Connector组件中,他负责接受浏览器发过来的tcp请求,创建一个Reuqest和Response对象用来请求和响应,然后产生一个线程,将Request和Response分发给他们对应处理的线程。

      终于看到了线程名中包含的Acceptor、Poller。他们都在Connector组件下的Http11NioProtocol下。着重介绍一下Http11NioProtocol下面的几个组件

      1. Acceptor:接受socket线程,接受的方法比较传统:serverSocket.accept(),得到SocketChannel对象并封装到NioChannel对象中。然后NioChannel对象封装在PollerEvent对象中,并放到events queue中。使用队列(生产者-消费者)和Poller组件交互,Acceptor是生产者,Poller是消费者,通过events queue通信。

        package org.apache.tomcat.util.net;
        
        public class Acceptor<U> implements Runnable {
              ...
            public void run() {
                byte errorDelay = 0;
                while(this.endpoint.isRunning()) {
                              ....
                    try {
                        this.endpoint.countUpOrAwaitConnection();
                        if (!this.endpoint.isPaused()) {
                            Object socket = null;
                            try {
                              // 这句会调用NioEndPoint类,底层是serverSock.accept()
                                socket = this.endpoint.serverSocketAccept();
                            } catch (Exception var6) {
                                ...
                            }
                                              ...
                        }
                    } catch (Throwable var7) {
                        ...
                    }
                }
        
                this.state = Acceptor.AcceptorState.ENDED;
            }
        }
      2. Poller:NIO选择器Selector用于检查一个或多个NIO Channel(通道)的状态是否可读、可写。如此可以实现单线程管理多个channels也就是可以管理多个网络线程。Poller是NIO实现的主要线程,首先从events queue队列中消费得到PollerEvent对象,再将此对象中的Channel以OP_READ事件注册到主Selector中,Selector执行select操作,遍历出可以读数据的socket,并从Worker线程池中拿到可用的Workrer线程,将可用的socket传递给Worker线程。

        package org.apache.tomcat.util.net;
        public class Poller implements Runnable {
             ...
             public void run() {
                 while(true) {
                     boolean hasEvents = false;
                        label59: {
                            try {
                                if (!this.close) {
                                    hasEvents = this.events();
                                    if (this.wakeupCounter.getAndSet(-1L) > 0L) {
                                        this.keyCount = this.selector.selectNow();
                                    } else {
                                      // selector.select方法,接受acceptor的socket
                                        this.keyCount = this.selector.select(NioEndpoint.this.selectorTimeout);
                                    }
        
                                    this.wakeupCounter.set(0L);
                                }
        
                                if (!this.close) {
                                    break label59;
                                }
        
                                this.events();
                                this.timeout(0, false);
        
                                try {
                                    this.selector.close();
                                } catch (IOException var5) {
                                    NioEndpoint.log.error(AbstractEndpoint.sm.getString("endpoint.nio.selectorCloseFail"), var5);
                                }
                            } catch (Throwable var6) {
                                ExceptionUtils.handleThrowable(var6);
                                NioEndpoint.log.error(AbstractEndpoint.sm.getString("endpoint.nio.selectorLoopError"), var6);
                                continue;
                            }
        
                            NioEndpoint.this.getStopLatch().countDown();
                            return;
                        }
        
                        if (this.keyCount == 0) {
                            hasEvents |= this.events();
                        }
        
                        Iterator iterator = this.keyCount > 0 ? this.selector.selectedKeys().iterator() : null;
        
                        while(iterator != null && iterator.hasNext()) {
                            SelectionKey sk = (SelectionKey)iterator.next();
                            NioEndpoint.NioSocketWrapper socketWrapper = (NioEndpoint.NioSocketWrapper)sk.attachment();
                            if (socketWrapper == null) {
                                iterator.remove();
                            } else {
                                iterator.remove();
                              // 然后调用processKey方法,将socket传给worker线程进行处理
                                this.processKey(sk, socketWrapper);
                            }
                        }
        
                        this.timeout(this.keyCount, hasEvents);
                    }
                }
            }
      3. Worker:Worker线程从Poller传过来的socket后,将socket封装在SocketProcessor对象中,然后从Http11ConnectionHandler获取Http11NioProcessor对象,从Http11NioProcessor中调用CoyoteAdapter的逻辑(这就出了Http11NioProtocol组件,可以看上上图)。在Worker线程中,会完成从socket中读取http request,解析成HttpervletRequest对象,分派到相应的servlet并完成逻辑,然而将response通过socket发回client。

        package org.apache.tomcat.util.net;
        protected class SocketProcessor extends SocketProcessorBase<NioChannel> {
                public SocketProcessor(SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {
                    super(socketWrapper, event);
                }
        
                protected void doRun() {
                  // 这一句从Poller拿到socket,然后进行tomcat主线程处理流程
                    NioChannel socket = (NioChannel)this.socketWrapper.getSocket();
                    SelectionKey key = socket.getIOChannel().keyFor(socket.getSocketWrapper().getPoller().getSelector());
                    NioEndpoint.Poller poller = NioEndpoint.this.poller;
                    if (poller == null) {
                        this.socketWrapper.close();
                    } else {
                        try {
                            int handshake = -1;
        
                            try {
                                if (key != null) {
                                    if (socket.isHandshakeComplete()) {
                                        handshake = 0;
                                    } else if (this.event != SocketEvent.STOP && this.event != SocketEvent.DISCONNECT && this.event != SocketEvent.ERROR) {
                                        handshake = socket.handshake(key.isReadable(), key.isWritable());
                                        this.event = SocketEvent.OPEN_READ;
                                    } else {
                                        handshake = -1;
                                    }
                                }
                            } catch (IOException var13) {
                                handshake = -1;
                                if (NioEndpoint.log.isDebugEnabled()) {
                                    NioEndpoint.log.debug("Error during SSL handshake", var13);
                                }
                            } catch (CancelledKeyException var14) {
                                handshake = -1;
                            }
        
                            if (handshake == 0) {
                                SocketState state = SocketState.OPEN;
                                if (this.event == null) {
                                    state = NioEndpoint.this.getHandler().process(this.socketWrapper, SocketEvent.OPEN_READ);
                                } else {
                                    state = NioEndpoint.this.getHandler().process(this.socketWrapper, this.event);
                                }
        
                                if (state == SocketState.CLOSED) {
                                    poller.cancelledKey(key, this.socketWrapper);
                                }
                            } else if (handshake == -1) {
                                NioEndpoint.this.getHandler().process(this.socketWrapper, SocketEvent.CONNECT_FAIL);
                                poller.cancelledKey(key, this.socketWrapper);
                            } else if (handshake == 1) {
                                this.socketWrapper.registerReadInterest();
                            } else if (handshake == 4) {
                                this.socketWrapper.registerWriteInterest();
                            }
                        } catch (CancelledKeyException var15) {
                            ...
                        } finally {
                            ...
        
                        }
        
                    }
                }
            }
      4. NioSelectorPool:NioEndPoint对象维护了一个NioSelectorPool对象,这个NioSelectorPool中又维护了一个BlockPoller线程(基于Selector进行NIO逻辑)。

    总结

    平时看起来很熟悉的代码,HelloWorld和SpringBoot初始化的项目。没想到背地里有那么多线程来支撑。装了VisualVM插件并不是让你蹭的就变强,但是可以给你提供一些进步的思路,引导你去思考去进步。下面还会继续带着分析更复杂的项目,不知道会不会有更多常见又未知的知识点等待我们去发现~

    欢迎访问我的个人博客

    拼多多的逻辑

    $
    0
    0

    “同样的商品,为什么拼多多更便宜?”这一直是困扰消费者和研究者的不解之谜。

    前段时间,因为沸沸扬扬的“火不过三年”报告,有券商组织了一场闭门调研会,请来了国内某零食快消品的高管进行了解读。

    品牌商从生意的角度,给这个话题一个更合理也更接近真实商业模型的解释,对于理解今天的零售行业、互联网平台有很多启发。

    以下是该高管的现场讲述,略有删节:


    一、品牌商在互联网上的成本怎么计算?

    我们是一家同时在拼多多和天猫上卖零食的品牌,目前,在国内零食行业排到了前几名,算是最早进入互联网领域的零食连锁品牌之一。

    我们的商品在不同平台有着不同的价格,尽管可能包装、商品名有些区别,但实际上的确是一盘货,也有很多细心的消费者对此觉得很困扰。

    其实,我是一个生意人,从我们的角度看,同一批货不同平台不同价是很正常的,因为不同平台的成本有非常大的差异。

    我来给大家算一下品牌商在不同平台的成本。




    简单说,商家在平台上卖东西,成本主要包含三大块:生产、物流和销售。

    生产成本就是出厂价和拿货价,主要拼供应链,看你能在原材料上省多少,怎么跟供应商谈判。比如有品牌溢价的女装其实成本只有2折,而零食品类出厂价基本是55折。因为是一盘货,这块不止拼多多和天猫,所有电商平台基本一样。

    从物流开始,各平台开始有差距了。同样卖100块钱,拼多多有25块花在物流上,天猫只有20块。

    到这里大家可能会奇怪,为什么拼多多的成本要更高一些?

    第一个原因,拼多多为了降低消费者的购买门槛,都是商家包邮,天猫多数还要消费者承担部分运费。

    第二个原因,是拼多多的模式与天猫不同,因为包邮,消费者可能看到一个饼干就直接下单了,接着看到一个话梅也下单了,因此,订单量更大,包裹更多。同样是消费400块,拼多多的用户可能会直接下了8个订单,而天猫用户可能会凑到一个订单里买,发了5个包裹。

    这5块钱的成本,一开始很多卖家觉得不划算,但是做电商成本的大头其实还没到。

    第三大块,销售成本,重头戏,占了商品总成本的30%左右。

    品牌的销售成本包括两块费用。一是销售费用,占比15%,用于产品给消费者的降价折扣;二是行销费用占比15%,用于购买广告流量及赠品发放等。这两块费用一般都是直接打包进入品牌商的年度预算框架内。

    这里面就发生了很微妙的成本差别。因为拼多多的商家多数根本用不完15%的行销费用,根本不需要购买流量。


    二、为什么品牌商愿意在拼多多上多打折?

    注意一下这15%的销售费用,意味着,其实商家都已经在成本之中预留了给消费者打八五折的空间,至于这部分折扣打不打,要看总成本的控制问题。

    现实中,如果15%的行销费用根本不够用,那么也就意味着,商家会缩减给消费者的折扣补过来。

    天猫的产品价格常年在95折,只有在双11等大促节才会大幅调动销售费用。

    但拼多多是常年维持85折,甚至很多商家还想要给到更低,要不是怕扰乱经销商体系,公司要平衡各渠道的价格,很多商家甚至希望在拼多多常年75折甚至7折销售。

    拼多多商家为什么卖这么便宜?关键是行销费用。

    天猫有个阿里妈妈,里面有各式各样的营销工具,商家要花钱买流量和友军竞争,否则排名就会掉下去。大家可以到网上搜,“淘宝开车”,讲的就是商家们要不断烧钱买直通车,这部分的流量营销费用非常之多,在一些品类上,甚至可能会占到成本的25%到30%。






    如果你为了行销,就得花掉25%的成本来买流量,你自然只能给到消费95折的价格,不然你就是亏本的。

    而拼多多的流量分发机制是不一样的,虽然也有营销工具,也有算法排名,但现在并不成熟,你就算愿意烧钱,开放给商家的广告坑位也没多少。大家可以去拼多多里看,你很少能找到广告栏位,但是我们打开淘宝天猫,满屏幕的推荐、搜索排名那都是烧钱的工具。

    拼多多是典型的以用户为中心的流量分发机制,你去烧钱投广告的效果,可能还不如直接降价1块钱,你去研究竞价排名的广告,还不如专心打磨一个爆款。一个低价的爆款冲出销量后,会带动全部商品的销售,这就是很多拼多多商家的策略。

    拿休闲零食类目来说,这个类目天猫官方给出的ROI是1:0.85,即用1块钱广告换0.85的生意,而拼多多是多少?我们自己的统计是1:5甚至是1:8。ROI就是投入产出比,按账面来看1:1回本,但实际算上生产和物流成本,基本要达到1:2才不亏钱。






    综合来看,拼多多的行销费用,就算你特别想花钱,实际上最多也只能用掉10%。这就弥补了物流上多出来的5%。

    加一块,30%的成本预算,你其实最多也就用掉了15%,那么剩下的15%,如果我们能给消费者打折,换来更多的销量,打造更好的品牌,商家其实是愿意的。

    总结来说,如果一个商家在电商平台辛辛苦苦做生意,哪怕最后不亏不赚,利润是0,拼多多的分布是:55%、20%、15%、10%,这里面的15%,就是平台通过自己的运营和流量分发模式,为商家留出了可以给消费者打折的空间。

    相较之下,天猫商家这几项数字为:55%、15%、5%、25%,所以,我们在天猫上的商品,理论上最多只能打95折。


    三、平台是否抽成,也造成了商品价格的区别

    计算完这些,还要注意一点,拼多多针对销售额只收0.6%的支付手续费,而天猫要收佣金是2.5%。这意味着拼多多平台通过不赚钱,又留出了2.5%的让利空间,而天猫,则是加上了2.5%,也就意味着,消费者其实购买商品的价格已经基本上是原价了。

    天猫商家为了少亏点,只好压缩销售费用,即减少对消费者的让利。同样的商品,为何拼多多卖得更便宜,原因就在这里,一个是要不断花钱买广告位,一个是让商家把买广告的钱,拿出来补贴消费者。

    做了拼多多快两年,我们才慢慢理解这家公司的运营逻辑。其实你会发现,拼多多上做得好的商家,和拼多多平台在风格上高度一致:都没有太多钱去搞营销广告,弄个晚会等等,但是在日常,会拿出非常多的预算来不断补贴消费者。

    在这样一个生态下,如果没有阿里二选一的压力,我们天然都愿意给拼多多上降价打折。而拼多多平台如果通过百亿补贴、天天领现金等营销活动,自己再继续投钱,这一点点的营销杠杆费用,就能撬动起非常巨大的规模效应,对于这一点,我们是非常佩服的。

    外界有人质疑拼多多补贴太多,其实是没有理解拼多多的整个体系。在这个体系里,拼多多最厉害的是通过流量和算法,避开了营销费用的无谓投入。






    现在是消费社会,我们都接触了太多广告,这些广告打得越多,其实品牌商的商品就卖得越贵,中间商拿走了利润。而局中的买卖双方,并没有获得直接的好处。如果商家投放100个广告,都未必能换来一个订单,为什么不把这笔钱,拿来补贴10个刚好需要的消费者呢?这就是拼多多正在做的事。

    为什么拼多多商品价格全网最低?网上有人说是商品不好,其实我们的商品全网都是一批货,只是因为平台帮商家省钱,然后要求商家帮消费者省钱。

    至于拼多多未来会不会坚持这条路,我们也不知道,但是从我的视角看,目前来说,拼多多的这套玩法对于整个快消品行业都是非常有启发意义的,整个行业未来会在移动互联网和新玩法的冲击下有更多变化,我们也在研究和适应这些变化。

    $拼多多(PDD)$



    本话题在雪球有32条讨论,点击查看。
    雪球是一个投资者的社交网络,聪明的投资者都在这里。
    点击下载雪球手机客户端 http://xueqiu.com/xz

    Airbnb深度学习搜索引擎实践-模型发展历程 – Semocean

    $
    0
    0

    Applying Deep Learning for Airbnb Search engine

    该文章是KDD 2019上发表的Airbnb的搜索引擎主要算法的文章,主要介绍了Airbnb算法的演进历程。还是Airbnb一贯的朴实无华的风格:不在乎有多少创新,更多是工业界结合业务上的算法工程,该文章很难的是文章中不仅介绍了Airbnb的算法,以及使用该算法的出发点和考虑,同时还记录了中间的各种坑,甚至一些失败的实验,真的是经验的无私分享,写作手法更像各大厂内网的技术总结分享文章。对于广大研发有较强的借鉴作用。
    再具体到技术细节,Airbnb的场景是低频,且作为平台需要同时考虑需求侧(用户/网民)同时还要考虑供给侧(Airbnb中是民宿),另外民宿预订有很强的地理位置属性,所以文中的算法对于低频场景,LBS场景的搜索推荐都有较强的借鉴意义。低频场景例如飞猪,携程,马蜂窝的酒店,旅游预订;LBS属性例如Google Map,百度地图,高德地图等场景。

    Abstract

    搜索引擎一直都是airbnb成功的重要的因素,之前的实现主要是使用树模型来实现核心的算法,但是出现了瓶颈,所以后来airbnb就使用深度学习来优化其搜索引擎。
    本文不会针对深度学习的算法进行创新,更多的是在使用深度学习的构建核心引擎中的一些细节的探讨。bon voyage

    Introduction

    搜索场景是airbnb的重要的场景,最开始系统使用的是人工的打分函数。之后使用gbdt进行特征的组合,这是一个比较大的进步,并且经过了比较多的迭代。现在开始转移到深度学习。

    图:搜索session示例
    典型的搜索引擎,在用户看了一系列的listing(相当于其它文章中的item)之后,完成了booked的工作。
    系统运行中间的日志都被记录下来,之后使用离线的方式训练新的模型模型,尽量的将booked的listing的排序排到最靠前。之后在线上使用ab test的方式进行验证。
    本文叙述的方式是从feature engineering和system engineering的方式进行的介绍。最后再对内容进行回顾。

    Model Evolution

    模型的迭代也是一步接一步的。深度学习是顶峰的表现,是最终逐步迭代后的结果,过程中也走了很多弯路。
    图:展示了在各个模型迭代上离线ndcg的提升幅度:

    图:展示了各个模型在线转化的相对提升幅度:

    Dustinsea: 可以看到,在全面DeepNN前,就已经拿到了比较多的受益,DeepNN让效果更上一层楼

    第一阶段:simple NN

    论文12提到don’t be a hero,但是我们一开始就从复杂的nn模型出发,到最后只是得到了复杂结构,还有花时间的循环。
    在nn上也也花了比较多的时间,gbdt模型输出作为nn模型的输入。该过程最重要的贡献,就是把特征的pipeline给建立起来。

    第二阶段:lambdarank nn

    使用lambda rank,直接对离线的ndcg进行优化。

    第三阶段:gbdt/fm nn

    gbdt作为另外一条线,在进行优化中间发现一个有意思的现象:从指标上gbdt的效果和nn的效果比较类似,但是他们排序出来的结果是不一样的。受这一现象的启发,将gbdt/fm和nn的架构进行了融合,FM的最终输出直接作为nn的特征,同时树模型的节点index作为nn的特征输入(和2014年facebook发表论文中gbdt+lr的思路异曲同工)。模型结构图如下:

    图:NN和GBDT模型融合方法示例

    第四阶段:DEEP NN

    模型
    最终使用具有两个隐藏层的nn。配置如下:

    特征
    大部分的特征都直接进行输入,没有进行太多的feature enginering,少部分的特征作为其他模型的输出,会进行特殊的处理。
    price特征:使用模型进行处理。
    similarity features:使用功现的embedding进行处理。
    使用17亿样本进行训练,以ndcg作为评估指标的情况下,能够达到收敛的效果。

    在评估过程中一个非常困难的点就是我们如何评判模型的结果和人的认知评判的结果的效果的对比。在图像中人是可以作为一个评判标准的绝对增值进行评价的,但是在我们的数据里边却看不出来绝对的增值,因为这些绝对的因素都是隐藏的比较深的。这和video或者audio领域不一样。

    失败的模型

    一般大家在叙事的时候都是在讲成功的案例,但这其实只是整个过程的很少的一部分,下面就向大家介绍一下失败的尝试,因为失败的尝试比较多,所以这个地方挑了两个模型。

    第一种失败尝试:直接使用listing ids embedding

    在nlp中或者电商视频推荐中,对于item的embedding使用是比较成熟的,并且证明效果比较好。但在airbnb的环境中,因为数据量比较稀少,就算最火的民宿一年也只能有365个预定,更多的民宿数据都是非常少的,所以很难学出稳定的embedding,基本上都是Over fitting,所以listing ids使用会失败。
    Dustinsea:所以Airbnb进行embedding的时候,更多是对人群/POI群进行embedding,而非用户/单个POI进行embedding.

    图:增加listing id embedding后,over fitting问题明显严重

    第二种:multi-task learning

    多任务是现在很多推荐搜索场景中常用的技术,多任务是现在比较fancy的技术,听起来也是make sense的。Airbnb也进行了尝试。
    进一步讲,在文中尝试的方向:是认为浏览时间比较长的listing应该会和booked行为有比较强的相关性。所以进行了多任务的学习,在学习的过程当中有两个子任务,一个是booked的子任务,另外一个是预估用户浏览时长的子任务。
    多任务模型在低层共用embedding,在上层分成两个任务,并且在loss function中将booked的样本进行加权。线上使用的时候只使用booked子任务进行预估。
    但最终线上的结果是用户的浏览是浏览市场的确变长,但是预定基本上没有什么变化,经过分析可能的原因如下
    第一是推荐出来的内容描述会比较长,或者描述中带有一些比较独特的东西,或者甚至是比较搞笑,这样用户浏览的时间就变成了,但是并不会影响到对应的预定。
    第2个可能的原因,是模型倾向于推荐价格比较高的listing,这样用户会进行浏览,但是最后也没有预定。所以多任务是一个比较有挑战的方向,需要继续进行研究。
    Dustinsea: multi-task learning是大趋势,从理论上也是符合逻辑的,但真正应用的时候,需要的投入也比较多,包括对于问题的细致分析,所以可以作为系统成熟阶段需要突破的手段,但在系统的拓荒阶段,不一定是很好的选择。

    图:下单率分布
    特征工程
    传统的feature engineering需要很多的时间以及经验,并且中间有很多的tricks才能提升目前的效果,但是这些经验和方法不一定还适用于最新的变化的数据(因为用户的行为是动态变化的,之前人工feature engineering的人工经验知识可能已经迁移)
    nn的一个优势就是它能对特征进行自由的组合,不过我们还是需要一部分的特征工程,只是我们的特种工程不再聚焦在我们选择以及如何进行特征变化,更多的是对数据进行统一的预处理,这样nn能够更正确的对特征进行转换和组合。
    feature nomalization
    gbdt值和特征的相对顺序有关,但是nn会和特征的值有关,所以进行特征的规范化。

    图:特征归一化方法
    第1种相对进行z score的处理
    第2种,如果分布符合指数分布,则进行log的处理
    feature distribution

    从特征的角度保证特征是平滑的,是比较重要的。因为如果一般特征不平衡,都是存在问题。检查特征是否平滑,有以下好处:
    检查数据种是否有bugs
    检查如何进行特征变换,例如文中将lng/lat转变为用户和listing的distance

    图:经纬度特征分布

    超参数

    dropout: 一般dropout在nn中都是防止过你和的标配,但在该场景中效果不佳,文中给出的解释是dropout比较像数据增强,相当于引入噪音。文中后续引入了人工构造的噪音, 线下ndcg有1%提升,但线上无变化
    initialization:使用xavier initialization方法,比参数默认置0好
    Optimizer:文中最后使用的是LazyAdamOptimizer,因为实验中使用Adam发现效果很难再优化
    文中最后还是推荐dnn是一个方向,因为能够让大家很大程度上摆脱特征工程,而站到更高的角度上去考虑优化目标的问题。但是整个过程也是比较耗时的,作者认为他们DNN的工作也才刚刚开始。

    图:发展历程

    reference

    原论文参见:https://pan.baidu.com/s/1C0I6AhEWB9h3PV5ZmSPcbQ 提取码:56l4
    更多内容参见: www.semocean.com
    P.S. 急招推荐,搜索,语音算法人才,阿里P6~P8,欢迎推荐和自荐,简历请发至 haibo.lihaibo@alibaba-inc.com


    微服务的脚手架Jhipster使用(一) - 陆陆起飞啦 - 博客园

    $
    0
    0

    随着微服务的普及以及docker容器的广泛应用,有传统的soa服务衍生出微服务的概念,微服务强调的是服务的独立性,屏蔽底层物理平台的差异,此时你会发现微服务跟容器技术完美契合。在此基础上衍生出的云原生以及DevOps的概念,废话不多说介绍一个非常牛叉的springCloud脚手架- -jhipster。

      

    •     安装 
    1. 安装Java 8 from  the Oracle website.
    2. 安装Node.js from  the Node.js website (请安装 64-bit version)
    3. 安装npm包:  npm install -g npm
    4. 如果你想使用jhipster应用市场, 请安装 Yeoman:  npm install -g yo
    5. 最后安装JHipster:  npm install -g generator-jhipster
    •          生成项目
    1. 选择一个空的文件夹打开cmd:jhipster  
    2. 根据一步步step提示选择构建自己的服务项目
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      <strong>windows下:</strong><br>以下demo选择微服务应用。实际中根据自己需求生产项目。
      1: Which *type* of application would you like to create? (Use arrow keys)
         Monolithic application (recommended for  simple projects)  //简单项目
         Microservice application // 微服务应用
         Microservice gateway // 微服务网关
         JHipster UAA server (for  microservice OAuth2 authentication) // 微服务认证
      2  :What is the base name of your application? (huhuawei)
          输入服务名称
      3: As you are running in a microservice architecture, on which port would like        
          your server to run? It should be unique to avoid port conflicts. (8081)
          设置服务的端口号
      4:What is your default  Java package  name? (com.mycompany.myapp)
          设置包名
      5:Which service discovery server do  you want to use? (Use arrow keys)
           JHipster Registry (uses Eureka)
           Consul
           No service discovery
          选择注册中心。一般选择Registry比较多
      6:Which *type* of authentication would you like to use? (Use arrow keys)
           JWT authentication (stateless, with a token)  // jwt
           OAuth 2.0  / OIDC Authentication (stateful, works with Keycloak and    
           Okta)//Oauth2 OIDC 认证服务
           Authentication with JHipster UAA server (the server must be generated 
           separately) // Oauth2+jwt Uaa认证服务
           选择授权中心
      7: Which *type* of database would you like to use?
            SQL (H2, MySQL, MariaDB, PostgreSQL, Oracle, MSSQL)
            MongoDB
            Couchbase
            No database
            Cassandra
            选择数据库支持Nosql跟常见RDMB数据库
      8:? Which *production* database would you like to use? (Use arrow keys)
            MySQL
            MariaDB
            PostgreSQL
            Oracle
            Microsoft SQL Server
            选择数据库,这边会出现两次第一次是production 第二次是devlopment
      9:Do you want to use the Spring cache abstraction?
           根据需求选择缓存
      10:Do you want to use Hibernate 2nd level cache? (Y/n)
           是否支持二级缓存
      11: Would you like to use Maven or Gradle for  building the backend? (Use
            arrow keys)
            Maven
            Gradle
      12:Which other technologies would you like to use?
             安装一些其他的组件。如ES,KAFKA之类的
      13:Would you like to enable internationalization support? (Y/n)
             支持国际化?
      14: Please choose the native  language of the application (Use arrow keys)
              English
              Estonian
              Farsi
              French
              Galician
              ........
              选择本地支持的语言包含中文
      15:Please choose additional languages to install
             可以额外安装其他语言
      16:Besides JUnit and Jest, which testing frameworks would you like to use?
               Gatling
               Cucumber   
             选择测试框架,针对微服务http接口测试,生成测试报告
      17:Would you like to install other generators from the JHipster Marketplace?
             从jhipster市场中选择组件安装
             
    3. 如果你觉得安装这些环境太麻烦,你又熟悉docker的基本命令,那建议使用docker去生成项目;
      复制代码
      选择linux服务器,安装docker;
      yum install -y yum-utils device-mapper-persistent-data lvm2
      yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
      yum list docker-ce --showduplicates | sort -r
      sudo yum install -y docker-ce
      sudo systemctl start docker
      sudo systemctl enable docker
      
      拉取jhipster官方镜像
      docker pull jhipster/jhipster:master
      
      启动jhipster镜像,选择一个空文件/jhipster夹挂载到容器中
      docker container run --name jhipster
      -v  /jhipster:/home/jhipster/app 
      -v  ~/.m2:/home/jhipster/.m2 
      -p 8080:8080 
      -p 9000:9000 
      -p 3001:3001 
      -d  -t jhipster/jhipster
      
      进入容器中
      docker container exec -it --user root jhipster bash
      然后就可以生成项目了。与windows上操作无差别
      复制代码

       

    •          项目的组成简单介绍

      Gateway: springcloud Zuul Proxy  进行动态路由微服务

      Registry:主要封装了Eureka以及配置中心Config Server。

            Jhipster Console:封装了Elk监控 以及 sleuth zipkin 等分布式链路监控组件。

            Jhipster Uaa:  采用UAA用户登录认证 OAUTH2集中式认证,默认不使用的话则是JWT无状态认证

          

    •          总结

              上述仅仅是大体的架构,Jhipster内部使用了很多插件来进行敏捷开发,包括实体类JDL快速生成从数据库到Controller代码,开发效率非常之高。适合中小型企业采用,而且Jhipster支持DockerFile与Compose                    文件生成,可以帮助我们快速容器化服务部署。

    一切从用户出发,重新理解“增长本质”和“会员体系”

    $
    0
    0

    编者按:本文来自微信公众号“ 九合创投”(ID:jiuheguancha),36氪经授权发布。

    在移动互联网的下半场,新的平台红利不断出现,快速变化的流量入口对创业公司提出了前所未有的挑战:如何理解增长的本质?如何实现增长的交付?如何解决用户留存的问题?如何运营社群、建立高粘合度的会员体系?

    2019年11月7日,在九合创投第三期“私董会”的闭门会上,前阿里、百度产品设计总监相辉、前雅虎中国、腾讯产品总监、滴滴顺风车事业部总经理Jelly Huang,和今日头条创始团队成员陈韬,分别围绕增长的本质、会员体系与服务设计等问题进行了深度分享。

    现场大合影

    我们根据此次内部分享实录整理了以下干货,以飨读者。

    • 增长的本质是什么?

    • 如何建立商业模式?

    • 影响增长交付的要素有哪些?

    • 会员体系设计出现了哪些重大转变?

    • 如何理解会员体系的设计?

    增长问题备受关注的原因是增长越来越难实现,而创新型平台产品的稀缺又导致流量愈来愈贵。增长的难点在于它和行业、流量的变化有着紧密的关联性,而增长模式的变化,也具有非常强的时效性。

    做业务操盘最难的是节奏感,即什么阶段解决什么问题。把握节奏感首先需要了解行业内的三个逻辑。

    从资本逻辑来看,投资人需要规模和利润同时增长。但从行业逻辑来看,可能规模和利润无法同时增长,保增长还是保利润是很重要的选择。而用户的逻辑是既不关心利润也不关心规模,用户只关心以合适的价格买到服务。

    大部分的企业都需要解决这三者之间的问题。不同阶段需要解决的关键问题大不相同,但任何阶段都不太可能同时解决这三个问题。如果价格和利润都高,用户体验可能不好;如果用户体验好,增长速度快,可能要耗费更多的资金。谁能更好的处理这个复杂的关系,谁就能获得最大的收益。这就是企业家精神,依靠的是创新。

    Jelly 在活动现场分享

    解决这个问题的核心,要回归到用户逻辑,即用户购买产品和服务最重要的理由是什么。这是增长的本质,也是企业的创新导向,是壁垒和护城河。作为创业者,撬动用户所获得的杠杆更高。企业需要发现新的需求,或产生新的供给,亦或创造新的连接交易的方式。

    如果以上三项都发生巨大的变化,会成就跨时代的伟大公司;如果某两项发生巨大变化,也有机会创造出某一个时代的伟大公司;如果其中一项发生巨大变化,可能会出现成功的独角兽。如果三项都没有变化,虽然可能是一门好生意,但是很难成为估值非常高的公司。创业后期,创始人一定要理性看待自己的赛道和解决方案,是否有达到某一级别的可能性。

    • 建立商业模式的三个步骤

    第一步是交易市场建立的选择。创造新的供给是最好的商业模式。而且从壁垒上来讲,创造新的供给是最难以被后来者抄袭的。从投入产出比来看,短期比较容易产生增量的是创造新的需求,比如增加新的品类。但在这种增长方式中,本质上供给没有发生变化。

    第二步是规模增长的可能性。建立起商业模式后,能否实现规模增长是企业需要思考的第二个问题。重要的是企业是否具有非常强的增长闭环。企业要有正确的供给和需求的逻辑。一般的逻辑是,供给是严重过剩的,企业要在供给中跳出来,找到用户的需求。

    第三步是规模增长的可持续性。理论上讲并不存在可以无限持续的规模增长,增长一定是有周期的。那么哪些指标能证明规模增长的可持续性呢?是规模增速、渗透率还是利润率?什么样的指标在行业里具有可持续性?

    • 影响增长交付的要素

    第一个因素是组织。创业公司经常会面临执行力的问题,而执行力的背后是组织健康与否。若要解决这个问题,第一步是组建团队。不同的模式和阶段需要不一样的人才,将满足D轮需求的人才放到A轮便是错配,这本质上不是对人的判断出了问题,而是对事情的判断有偏差。企业明确当前阶段的发展目标后,才能快速建立合适的团队。

    企业在组建团队时容易产生的误区包括:企业缺少和现有团队能力互补的人才;管理层不了解新员工所负责的领域,疏于管理;寻找人才的渠道过于单一;以及信息量不足的问题。

    第二个因素是管理。在增长交付的管理过程中,企业应该把组织当作一个产品去管理,明确各项工作的负责人,关键的决策节点在何处流转,并重视组织设计、架构设计和流程设计。

    做好以上这些方面之后,才会涉及到内部KPI的设置,包括管理的常规化和专业化等。没有管理机制的保证,便无法保证决策的落地和执行。企业需要加强这方面的意识,从初创阶段起就在内部建立“明规则”。

    第三个因素是人才。人才是一个“甜蜜的烦恼”。从内部培养人才可能比选择空降高管更好,一般的创业公司未必有适合空降的土壤。大公司内部治理相对规范,业务多元化。而小公司创始人的风格会直接影响公司的文化。如果找一个空降高管,失败率可能非常大,反而内部提拔年轻人更适合目前的阶段。

    当企业从宏观角度理解了增长的本质之后,横亘在业务操作层面的难题之一是会员体系的设计。会员体系是从商业到人文的交付。

    近几年,会员体系设计出现了以下四个方面的转变:从流量思维到超级用户思维、从粗放运营到分层服务、从产品供给到生活提案、从品牌分发到品牌共建。会员体系的设计过程非常复杂,但只要掌握了上述四个核心思想,就抓住了设计的关键。

    企业在设计会员体系时,需要从以下几方面进行深入的思考。

    首先,会员体系的设计是生活场景的定义,而不是权益的堆砌。

    只有形成用户认知,才会让用户体系更有力量。这就需要企业去思考如何搭建认知场景,如何利用用户力和用户体验,抓住最底层的用户反馈。当企业设计一个会员场景的时候,需要留出足够的发展空间。任何新的场景设计都要通过一个逐渐扩容的过程,建立起用户能够感知的场景。

    第二,要用数据颗粒度重新看待商业健康度。

    如果只关注新增、日活、留存、转化和传播,数据会相对粗糙。只有细腻的数据才能给我们更直观的判断,需要像观察一个社会一样去重新看待商业的健康程度。此外,企业要把用户成长路径明细化。用户的行为习惯在不断的发生转变,企业应该根据用户行为习惯调整和提升产品策略,这是会员体系要重点讨论的内容。

    第三,用情感设计提升商业效率。

    首先要在会员体系设计上具有独特识别性,可以让用户快速记住产品,并不断的重复使用。同时,情感设计具有复利性,可以通过每个故事不断的加深情感。

    情感设计会使得用户与企业之间的沟通更加活跃。这种相互之间的深层沟通和用户得到的情感体验,远非单纯的文案和现金补贴所能获得。如果会员体系的设计希望打动用户、让用户沉浸在体验里,就一定要给他们感情上的共鸣。

    相辉在活动现场分享

    第四,运营生态不能只考虑GMV。

    如果企业想让生态长出高雅,不能只看成交、消费、GMV、现金流,还要看生态贡献。有些用户是信念贡献,他们会促进生态价值观的表达和传播。在C2C的社群中,有的用户贡献价值观,有的用户则贡献实际的商业效果。

    当企业在运营生态时,一定要坚持红线的规划,底线不容触碰。同时鼓励用户之间互相贡献,实现生态用户之间良好的相互促进。用户各自贡献自己的价值,这才会是一个长久的健康生态。

    第五,对抗短期利益,明确长期逻辑。

    企业要理性看待短期收益和长期逻辑的问题,否则容易被短期逻辑牵引,只低头耕耘不抬头看路。只有企业把内部业务梳理清楚了,用户才能对企业有完整的预期,服务才有边界。会员体系在不同消费场景中的机制不同,基于用户的场景是本源。在此基础上,企业需要考虑会员体系使用单轨制还是双轨制,是购买制还是积累制。

    最后,会员体系本质是商业模式设计。

    会员体系设计的底层逻辑是由产品思维或流量思维,向可持续性服务思维转变,服务超级用户,形成长期契约,让用户可运营自己的场景行为,使其每一次行为都转变为用户的资本。更加高层次的方式是使用生态自我净化和升级体系。

    企业应该交付给用户一个完整的、长久性、可经营并具有良好用户体验的产品,而不是一个流程化的产品。艺术,解决人与心的问题,而设计,解决的是人与物的问题,用心雕琢,就会成就有魅力的商业。

    在闭门会上,嘉宾与九合系Portfolio的朋友们也就一些具体赛道的增长问题展开了讨论,以下为部分精彩问答。

    会员的核心逻辑,就是让消费行为变成积累资产,把用户当成个体而非流量来看待。而社区便利柜的特点是购买行为结束了,用户就会离开。在您的这种场景里,将重点放在低价上可能比较好,可以直接做成积分制。我曾经给苏宁小店做会员体系,做了每个小店周边很多低频服务的聚合,如开锁服务等,用这种服务满足社区需求。

    可以考虑围绕生活方式提供其他服务,纯粹的产品促销反而不见得有用户场景。比如转转线下店的活动,用户出售二手手机跟新机型的发布有关。建议做单个用户高频次场景的深挖,提供便利成本比较低的服务,不断的触达用户。根据生活场景对模式进行设计,商业上能维持长期的增长和契约。

    为了快速增长是需要做投放的,同时要设定好增长目标。线上投放是非常好的手段,因为这种手段很成熟,且其它的替代选择比较少。一般来讲高平台产品做补贴,低平台产品做投放,核心其实没有捷径,就是线上投放、线下布点、裂变等几种方式。

    改变产品命运的有时候是赛道型的思考,有时候是效率型的思考。东方是实用思维,我们往往擅长把一个事情的运营做到极致;而西方是推演一个可能性再去做。我觉得,未来做产品的人都要把自己从感性里抽出来,依靠理性去做,但是当交付产品时,要把灵魂装到肉身,去创造打动人的产品,这是未来对每个从事商业的人的要求。

    无论是设计商业策略、产品外观还是体验,都是商业的架构翻译成人文的过程,所以需要在两个思考维度里找到桥梁,这需要商业上的人文,没有技术的人文叫做矫情,没有人文的技术叫做傲慢。

    首先要找到用户在哪里,其次要做好优化,从作坊变成商业模式,从商业模式变成体系生态,最后才是新的架构。所以第一是要分阶段,判断什么阶段做什么事最有价值。像中台一定是在业务扩展的时候建立,这样效率更高。第二是重视品类,我们的价值创造和文化有很深的关联。当形成社区化的时候,社区共同文化的运营就很重要。

    任何的感性都是为理性服务的,所以要判断阶段和品类。目前你们已经明确了阶段,所以需要找到更高效率的方法。

    不同阶段的用户需求不一样,可以考虑为核心用户建立社区机制,帮助他们获得更多的情感认同,使他们交互的体验变成资产。例如支付宝不只是现金流,而是每个人的信用加上数据体系。提升用户的存在感,满足他们的好奇心,使社交关系变成资产,这几方面都非常重要。

    本次活动中,九合创投投资的二十余家 To C 类公司的创始人和高管来到了活动现场,与嘉宾积极讨论,共同深度学习。九合创投愿和被投企业一起进步,互相激励,也希望在未来举办更多有价值、有意义的活动,为心怀梦想的创业者们做到更多切实的帮助与赋能。

    复盘:一次曲折的会员成长体系设计

    $
    0
    0

    存量运营开始逐渐流行,各大公司也开始启动自己的用户运营计划了。笔者最近负责了一个会员成长体系的建设,个中曲折,与大家分享。

    互联网进入到新的时期,存量意识越来越被人群所重视。这种意识不仅在互联网行业甚嚣尘上,甚至最近一家传统行业的公司找到我,要做一套会员激励体系来激活自己的客户!

    这是一家成立16年的文化传播公司,在公益赛事演出传播等领域具有一定的知名度/美誉度,在目标群体中渗透率超过60%,但是近年来竞争对手越来越多,市场环境恶劣,目前正意欲扩展新业务方向。即使这样地位的一家公司目前也面临增长困难的处境,看来19年不是大家的好运年。

    公司负责人给了我之前公司内部设计的但并未通过执行的会员体系,隐去关键信息呈现会员福利部分如下:

    复古风的完美展现,官僚风扑面而来:

    像不像居委会大妈站你面前叫你填表。

    这个会员体系最终没通过,也是可以理解的。这份设计只有团队福利与理事福利两个主要模块,内容官方,并不完善。缺乏消费者等级成长带来的身份荣誉感,会员参与感为零,特权感知仅仅停留在价格和少量礼品上。用户与品牌之间的距离感强烈,不吸引人。

    开始我的分析,分析方法不是唯一的,本次是一次基于互联网方法论的传统行业实践。

    用户会员体系的三个属性: 目标—激励目标行为—激励方法。

    一、首先确定目标

    结合生命周期理论来做判断,看目前这家公司所在阶段。

    企业处在不同的生命周期阶段,结合当时的天时地利人和,才能制定运营策略。

    用户生命周期状态见下图:

    各个阶段详情:

    • 引入期(启动阶段):产品刚上线,默默无闻,拓展种子用户。
    • 成长期(成长阶段):用户增长模式至少找到一条途径,用户量开始稳步增长。
    • 成熟稳定期(成熟阶段):用户量积累到一定程度,或者触达行业天花板,用户增长缓慢,开始思考变现并进行尝试。
    • 流失期(衰落阶段):用户增长停止,开始衰减。

    不同时期的核心业务指标:

    • 引入期(启动阶段):种子用户数量,产品功能迭代提升
    • 成长期(成长阶段):用户数量,用户规模,留存
    • 成熟稳定期(成熟阶段):变现尝试,提升付费用户数和客单价
    • 流失期(衰落阶段):减缓用户流失的出现,存量运营

    用户运营的关键群体和激励方向:

    • 引入期(启动阶段):尝鲜者,激励用户体验目标流程,提出建议,指导产品迭代(案例:乌托邦)
    • 成长期(成长阶段):跨界者,突出产品自身优势特点,强化优势和特点(案例:画世界/彩视)
    • 成熟稳定期(成熟阶段):上瘾者,复购老客户,刺激持续使用关键功能,促进消费复购(案例:抖音/知乎/快手)
    • 流失期(衰落阶段):情怀客户,召回,延缓流失,稳定运营(案例:宝宝树)

    结合公司实际情况,该公司处于 成熟稳定期,会员体系的目的是提升产品与用户的强关系,继续刺激上瘾,加强品牌认知归属,提升用户留存率以及复购率。

    二、确定要激励的目标行为

    梳理用户行为的方法:

    1. 梳理用户交互可能,尽量细致

    从下载注册登陆修改昵称等开始梳理。一般产品经理处会有交互汇总资料。

    2. 研究实际的关键路径以及产品设计的预期路径,进行比较

    产品经理与数据分析都需要加入这个过程,基于你自己平台用户的特征去分析。比如根据我以往的产品经历,注册以后当天更改头像设定昵称上传个人资料的用户留存更好,互动更多。

    根据这些交互特征,可以尝试去激励引导其他用户以提高留存和互动。如果创作内容是我们的关键路径,那么那些热衷内容创作的用户的行为需要重点关注,并将细节添加到会员成长体系中去。

    3. 根据产品阶段和实际情况判断激励行为的优先级

    我们做过一个七天登录转运的抽奖活动。注册登陆后七天内未登录的,第七天会有推送提示登录浮窗抽奖。奖品当中有商城优惠券,积分等礼品。将提升留存和增加商城漏出两个目标结合进行。

    话说回来,手头这家企业需要激励的目标行为是:复购和口播,品牌深化。(传统行业基本都是如此)

    三、确定激励方法

    1. 用户画像决定行为方式

    不同的用户群体对同一刺激的反应完全不同,确定激励方法首先确定目标群体,定性与定量分析相结合。

    基于当下业务情况,以及企业能提供的消费数据,结合网络数据,做一个简单的目标用户画像分析。

    现有企业用户画像分析:40岁-75岁,高净值中老年人群。女性占比70%,男性占比30%。具体省份分布以企业提供的消费数据为准。东部沿海省份明显消费能力强。

    案例:

    简而言之,会员用户是:中高端“大妈”和中高端“大叔”。

    2. 我们设计的内容一定要满足人性8大核心驱动力

    人性是我们一辈子都要去考虑去琢磨的领域。八大核心驱动力可以作为指南针,帮你在无头绪的情况下迅速定位,制定策略。在此简单介绍下,如有兴趣,这些领域需要深入进去仔细理解。

    (1)使命——史诗意义和使命感

    指人类认为自己正在做的事情,其意义比事情本身更重要,他必须身体力行竭尽全力去完成目标以宽慰他内心的世界。

    (2)成就——成长和成就感

    指我们通过使用产品取得进展、学习技能、掌握精通和克服困难的驱动力,挑战尤为重要,没有挑战性而获得的奖杯和勋章毫无意义可言。

    (3)授权——创意和及时反馈

    能驱使玩家全身心投入到创造性的过程,不断找出新事物,并尝试不同的组合。通过不断体验创造的过程,同时注重创造的结果,并获得及时的反馈。

    (4)拥有——所有权和拥有感

    能驱使玩家拥有或控制某样东西,因此而受到激励。当一个人对某一样物品有拥有感时,自然会产生想要提升该物品的各项性能,这一驱动力是人类积累财富的主要欲望来源,也是玩家积累虚拟货币的主要驱动力。

    (5)社交——社交影响和关联性

    是人们所有社交因素的集合体,包括师徒关系、社会认同、社交反馈、伙伴关系、竞争关系。对应马斯洛需求层次理论中的受到尊敬、自我实现。

    (6)稀缺——稀缺性和渴望

    人们想要某样东西原因仅仅是它太罕见,或者无法立刻获得。包括任务机制、游戏时间限制,玩家无法立刻获得奖励,会激励他们一有机会就回到这款产品。即便王者荣耀限制了小孩子玩游戏的时长,可能这反倒会刺激更加痴迷。

    (7)未知——未知性与好奇

    人们一直受到吸引,是因为不知道接下来会发生什么,这就是未知性与好奇心驱动力。当某样东西超出你日常的模式识别系统,你的大脑便会立即进入高速运转模式,来关注这突如其来的事物。

    (8)亏损——亏损与逃避心

    我们都不希望坏的事情发生,就是不希望之前的努力白费,不想承认自己做了无用功,正在消失的机会也是对这一核心驱动力的有效应用。比如:特别优惠、限时抢购。(引自《八角形为分析法》)

    外在动机是我们最常用的刺激点,外在动机用得太过会损害内在动机。正向刺激好于负向刺激。

    结合产品情况和用户画像,确定要使用的动机。我确定使用的动机是:拥有,稀缺,社交,使命。这里带有一定的主观性,不同的运营团队会有不同的选择。

    3. 对用户行为进行量化

    分等级以及制作积分表。等级是可进不可退的,积分是可进可退的。

    一般的用户成长体系两条线并行,等级代表了资历荣耀以及离开成本。

    积分代表了用户在平台的货币,在一些时候实行代币作用,兑换权益等,设计者需要注意设计通货膨胀的抑制措施。因本次会员体系设计内容所限,本段内容不进行扩充。

    4. 设计

    与对方几次深度沟通后,头秃的得出以下结论:传统行业要求简单粗暴,要求一看就懂,不玩概念。以线下进行承接,因为对用户预期不确定,暂时不考虑线上的承接。

    本来预计线上公众号做会员承接,福利权益推送平台,同时可为对方新建立公众号进行引流和客户锁定,但是甲方爸爸无情否定了这个提议。

    其实不论线上还是线下会员体系,几个基本点还是上面的内容中所阐述的,区别在于线下会员动作刺激会更简单直接,因为线下的目标简单直接,就是复购和消费。

    (1)参考京东,知乎,百果园等品牌的会员体系资料,尝试提炼如下方案:

    1. 明确的会员等级
    2. 会员权益(拥有)(稀缺)
    3. 会员活动(稀缺)(社交)
    4. 公益基金池(使命)

    中高端大妈和中高端大叔,即便是中高端人群,也带有那个时期走过来的人的共性,

    (2)会员体系目前有两种:一是免费版。按照消费或者行为升等级,不同等级对应不同权益。

    一是付费版。比如最近大火的costco,权益刺激直接显性的产品适合付费会员。

    本次设计为免费会员体系,只要之前在该公司消费过,自动成为公司会员,按照消费次数匹配等级。因为考虑到品牌的公益性,不采取金额形式评定级别,金额作为一个展示来具体呈现。

    (3)会员权益:体现专属和稀缺的感受,要体现不同等级之间的区别。综合参考costco的会员体系结合个人思考,设计归类如下:

    • 产品类:新产品新功能优先体验,免费试用,孤品预定,限量抢购
    • 服务类:售后退款优先处理,退货免运费,额外修理服务,上门配送
    • 活动类:会员日,会员价,会员生日福利,节日福利
    • 金额类:折扣券,优惠券,满减券,积分换礼,邀请返现
    • 异业合作:同一用户画像用户的其它需求

    (4)在设计的过程中同时考虑到活动体验官和积分兑换两个补充内容。

    活动体验官可与该公司新开发的中高端旅游项目的推广相结合,为高端客户提供仪式感参与感,对提升客户的品牌黏度是一种有效途径,方便激活核心客户。

    积分兑换绑定客户给客户带来额外惊喜的作用有目共睹,线上产品根据用户行为生成积分再进行反馈,形成正向反馈,基于RFM模型来看,积分策略对于中段用户有很好的提升刺激做用。

    积分体系上线后,我们以往产品中的关键指标大幅提升,同时用户会得到相应福利,反馈是双向正面的。

    但最终结合这家企业的情况,这两种方式并不适合他们。这家公司更倾向于采用邮寄手册+电话维护的方式进行目前的客户管理,很谨慎,但这也是他们擅长的部分。

    会员权益可根据情况进行升级调整,一般来说,如非行业霸主,不可将权益降级只能升级。品牌的搭建需要一点一滴维护,任重道远。

    总结

    会员体系和会员关系管理是一家企业发展到一定阶段必须要重视的部分。这个体系不是一成不变的,需要根据企业业务情况与时俱进。

    文章开头就有提到,对于一般的企业来说,目前是存量的争夺时期。通过强调和优化会员体系提高用户留存是不得不去尝试的方法。

    传统行业与互联网行业有区别也有融合:

    1. 对待互动性的区别,传统行业更强调单向传输,让用户接受并不真正在意反馈。
    2. 平等思维,传统行业把用户当作圈养的群体。
    3. 互联网产品可在使用过程中对用户进行教育,传统行业的教育用户的机会非常少,更注重直接缩短买卖过程,极为在意成交。
    4. 传统行业更强调客户概念,互联网企业更强调用户概念。客户可以带来直接收益是公司的命脉,用户可以带来流量收益是互联网概念的直接表现。可以看到,目前互联网企业迫于变现压力越来越强调客户与用户概念以及运营手段的区分。

    多接触不同行业是有必要的,避免陷入惯性思维。

    该行业内暂无竞品可对比参考。如有条件,一定要研究对比竞品的设计理念和细节。知己知彼百战不殆。

     

    本文由 @伙夫安妮 原创发布于人人都是产品经理,未经作者许可,禁止转载。

    题图来自Unsplash,基于CC0协议。

    Doing microservices with JHipster

    $
    0
    0

    微服务与整体架构

    JHipster会问您的第一个问题是您要生成的应用程序类型。您可以在两种架构样式之间进行选择:

    • “单体式”架构使用一个单一的,千篇一律的应用程序,其中包含前端代码和后端Spring Boot代码。
    • “微服务”架构将前端和后端分开,因此您的应用程序更易于扩展和解决基础架构问题。

    “单体式”应用程序更易于操作,因此,如果您没有任何特定要求,则建议使用此选项,并且将其作为默认选项。

    微服务架构概述

    JHipster微服务架构以以下方式工作:

    • 一个 网关是一个JHipster生成的应用程序(使用的应用程序类型 microservice gateway,当你生成它)来处理Web流量,并服务于Angular/React 应用。如果要遵循“  后端为前端”模式,可以有几种不同的网关,但这不是强制性的。
    • Traefik是可与网关一起使用的现代HTTP反向代理和负载平衡器。
    • JHipster Registry是一个运行的应用程序对所有应用程序注册,并得到他们的配置。它还提供了运行时监视仪表板。
    • Consul是服务发现服务以及键/值存储。它可以用作JHipster Registry的替代方法。
    • JHipster UAA是基于JHipster的用户身份验证和授权系统,它使用OAuth2协议。
    • 微服务是JHipster生成的应用程序( microservice application生成它们时使用应用程序类型),用于处理REST请求。它们是无状态的,可以并行启动它们的多个实例以处理重负载。
    • 所述 JHipster控制台是一个监测&警报控制台,基于ELK堆栈上。

    在下图中,绿色组件特定于您的应用程序,蓝色组件提供了其基础结构。

    图表

    被忽视的time命令

    $
    0
    0

    如果要选 Linux 下最容易被忽视的命令,time 应该算一个。简单来说,它是一个用来计算命令运行时间的工具,之所以说它容易被忽视,一方面很多人根本不知道 time 的存在,而是习惯在命令启动前后记录两个时间戳,然后手动计算命令运行时间;另一方面很多人虽然知道 time 的存在,但是却并没有真正理解它的含义。

    下面让我们通过若干例子来理解 time 的真正含义:

    shell> time ls
    
    real	0m0.003s
    user	0m0.001s
    sys	0m0.002s

    大概意思是 ls 命令运行花了 0.003 秒,其中用户态花了 0.001 秒,内核态花了 0.002 秒,看上去似乎「real = user + sys」?此等式是否成立,在回答这个问题之前我们不妨看看 real、user、sys 的确切含义,如下定义源自 Stackoverflow

    • Real is wall clock time – time from start to finish of the call. This is all elapsed time including time slices used by other processes and time the process spends blocked (for example if it is waiting for I/O to complete).
    • User is the amount of CPU time spent in user-mode code (outside the kernel) within the process. This is only actual CPU time used in executing the process. Other processes and time the process spends blocked do not count towards this figure.
    • Sys is the amount of CPU time spent in the kernel within the process. This means executing CPU time spent in system calls within the kernel, as opposed to library code, which is still running in user-space. Like ‘user’, this is only CPU time used by the process.

    总的来说,real 是我们直观感受到的消耗的时间,如果命令运行时被堵塞了,那么堵塞时间也是被统计在内的, user 统计在用户态态模式下消耗的 CPU 时间,如果命令运行时被堵塞了,那么堵塞时间并不被统计在内,sys 统计在内核态模式下消耗的 CPU 时间,如果命令运行时被堵塞了,那么堵塞时间并不被统计在内。

    看上去是否统计堵塞时间是区分 real 和 user、sys 的关键,看看下面这个 sleep 例子:

    shell> time sleep 1
    
    real	0m1.002s
    user	0m0.001s
    sys	0m0.001s

    那么除了堵塞时间,还有别的关键点么,让我们再看看下面两个例子:

    shell> time find /etc -type f | xargs -n1 -I{} cat {} > /dev/null
    
    real	0m2.050s
    user	0m0.626s
    sys	0m1.533s
    
    shell> time find /etc -type f | xargs -n1 -I{} -P2 cat {} > /dev/null
    
    real	0m1.079s
    user	0m0.681s
    sys	0m1.486s
    

    前后两个例子的区别在于后者在使用 xargs 的时候通过「-P」选项激活了多进程,换句话说,后者可以同时用到多个 CPU。

    了解了相关知识之后,我们通过 real、user、sys 的大小就可以判断程序的行为:

    • 如果 real 远远大于 user + sys,那么说明程序可能有严重的堵塞问题。
    • 如果 real 基本等于 user + sys,那么说明程序可能没有用到多 CPU 能力,
    • 如果 real 远远小于 user + sys,那么说明程序可能用到了多 CPU 能力。

    怎么样?看似简单的 time 命令,是不是远比你想的要复杂得多!

    Viewing all 11850 articles
    Browse latest View live


    <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>