微服务大逃离, 函数即服务呼风唤雨-01: haskell勇赴云计算faas战场

国庆节开始了,为大家献上一篇!

  1. 前言
  2. 开战函数式-faas on docker!
  3. 开战云计算-faas on k8s!

一. 前言: faas时代已至,云计算领域必将欣起一场血雨腥风。。。

微服务已逐渐被人们所接受,没吃过猪肉的,想必也见过猪跑。。。
大量的人在迷信微服务,把整个系统搞得一团乱,我是非常气愤的!

但是我不排斥微服务,因为我相信

微服务嘛,必将成为函数即服务faas的踮脚石。


1. 计算机原本很简单,最初一个PHP就可以搞定前后端。。。

但是呢,后端怎么可以乱动?前端是可以乱动的!
毕竟用户体验是不断变化的,用户特效是不断变化的,但后台核心功能岂可胡来。。。
所以,在有限的后台服务上,我们可以自由组合出各种前端,并且分工更加明显。
这显然是好事。。。

2. 前后端分离是第一步,随着科技日益发展,后端功能也越堆越多。

部门之间业务更加集密,这时候跨部门的业务集成是非常有必要的了。
SOA的时候已经过去,REST的简单使服务变得如此便宜, oauth2协议也成了标配。。。
所以,不同部门已不再限技术 ,不再限平台,只需要接口的体系。
这也算是好事。。。

3. 各系统之间交互,必然有大量基础设施,这自然也形成了微服务体系标准。

比如验证功能,存储功能,调度功能大家都可以一起用,开开心心。。。
所以,微服务开始呼风唤雨。。。
但是呢,人们慢慢熟悉,慢慢发现,微服务深处,让人可怕。。。

4. 微服务哪里让人可怕了?简单的地方隐藏了无数复杂。。。

比如我要做一个文件格式转码器,很自然可以做成一个微服务,大家一起开心使用。
一切看起来似乎很美好,但是如果你有10个服务,有个服务挂掉了呢?B服务依赖A服务呢?
我靠,什么服务降级?什么熔断机制?什么服务注册?什么配置中心?什么什么,请问,我是在写代码吗?
我的功能本身可以是一个插件JAR包,得到前台请求,运行JAR包里面的功能就可以了,
什么事情都没有,一台服务挂了,另一个来嘛。
所有请求处理都从代码插件包里加载响应,没有额外进程额外开销,没服务你怎么出问题怎么监控!。。。就应该这么简单啊!

5. 微服务有错吗?

微服务有错吗?
微服务从思维上来说,是正确无疑的,服务确实应该被 拆解成可维护可组合的过程。
微服务从技术上来说,就错到离谱了!
服务从本质上来说是分离的,越分离越复杂越难管理,
连接他们需要大量的调试与接线,运维他们需要大量的监控!
等等,可组合?插件是可以组合的,所以插件机制应得得非常广泛。
那么能不能微服务也能像插件一样自由组合呢?
不行,服务本质是来说是分离的,除非,我们无服务!

6.无服务是个什么鬼? 函数即服务!

既然需要组合,那么我们选择像插件一样去响应式加载功能,而不是作为一个独立的服务!
需要了就加载,服务状态各种异常需要监控,函数加载总不会有问题吧,毕竟函数是无状态的?
这次不行,下次重新来,一点问题都没有!

所以,有了函数即服务faas,我们可以像插件一样动态去扩展组合功能,而没有微服务的复杂度!因为我们是无状态的!



听你说得挺简单,那你做给我们瞧瞧 !
本来就很简单嘛。。。
为了体现它的伟大性,我们得用正式的函数式编程语言haskell进行讲解,其它的一样简单!
faas平台挺多,这里选择oracle的fnproject讲解! 因为其它的还没玩过。。。
其它的选择, openwhisk, openfaas。。。
商业的amazon lambda对于我这种开源爱好者,就忽略了。。。

二. 开战函数式-faas on docker!

  1. 构建docker函数
  2. 启动fn服务器
  3. 创建docker函数trigger
  4. 测试检查

是不是很简单呀!直接接着干!

1. 构建docker 函数

目前docker具有较好的封装性,所以大部分平台采用docker来封装函数单元。
docker函数要做什么呢? 接受标准输入,输出标准输出!
是不是很熟悉,shell不就是这玩意,用shell来做docker函数也完全没问题呀!
就是这么简单!

那我们简单用haskell写一个对数据进行base64编码解码的小服务吧。输出输出都用JSON,与rest标准保持一致。
其它语言也一样简单,最终达到的效果就是:

[larluo@larluo-nixos:~/my-repo]$ echo -n '{"action":"encode","content":"larluo"}' | docker run -i my-base64:latest
{"result": "bGFybHVvCg=="}

a. 创建haskell项目my-base64

[larluo@larluo-nixos:~/my-repo]$ stack new my-base64
......
All done.
[larluo@larluo-nixos:~/my-repo]$ cd my-base64/ && rm package.yaml
[larluo@larluo-nixos:~/my-repo/my-base64]$ cat stack.yaml | grep -v ^# | grep -v ^$
resolver: lts-12.10
packages:
- .
allow-newer: true
nix:
  enable: true

[larluo@larluo-nixos:~/my-repo/my-base64]$ cat my-base64.cabal  | grep -v '^--'

name:           my-base64
version:        0.1.0.0
description:    Please see the README on GitHub at <https://github.com/githubuser/my-base64#readme>
homepage:       https://github.com/githubuser/my-base64#readme
bug-reports:    https://github.com/githubuser/my-base64/issues
author:         Author name here
maintainer:     example@example.com
copyright:      2018 Author name here
license:        BSD3
license-file:   LICENSE
build-type:     Simple
cabal-version:  >= 1.10
extra-source-files:
    ChangeLog.md
    README.md

source-repository head
  type: git
  location: https://github.com/githubuser/my-base64

executable my-base64-exe
  main-is: Main.hs
  other-modules:
      Paths_my_base64
  hs-source-dirs:
      app
  ghc-options: -threaded -rtsopts -with-rtsopts=-N
  build-depends:
      base >=4.7 && <5
    , aeson
    , bytestring
    , base64-bytestring
  default-language: Haskell2010
  default-extensions:
    OverloadedStrings
[larluo@larluo-nixos:~/my-repo/my-base64]$ cat app/Main.hs                                                                                                                                                   
{-# LANGUAGE DeriveGeneric #-}                                                                                                                                                                            
{-# LANGUAGE OverloadedStrings #-}                                                                                                                                                                        
{-# LANGUAGE FlexibleContexts #-}                                                                                                                                                                         

module Main where

import Data.Text (Text (..))
import Data.Text.Encoding (encodeUtf8, decodeUtf8)
import Data.Aeson (decodeStrict, FromJSON, encode)
import Data.Maybe (fromMaybe)
import GHC.Generics
import qualified Data.ByteString as B


import qualified Data.HashMap.Strict as HM
import qualified Data.ByteString.Base64 as B64

data Request = Request { action :: Text, content :: Text} deriving (Generic, Show)
instance FromJSON Request

invoke :: Maybe Text -> Maybe Text -> Either Text Text
invoke (Just "encode") (Just content) = Right . decodeUtf8 . B64.encode . encodeUtf8 $ content
invoke (Just "decode") (Just content) = Right . decodeUtf8 . B64.decodeLenient . encodeUtf8 $ content
invoke _ _ = Left "action is null!"

main :: IO ()
main = do
  req <- B.getContents
  let reqJson = decodeStrict req:: Maybe Request
      resp = invoke (action <$> reqJson) (content <$> reqJson)
      mkSuccess message = show . encode $
        (HM.fromList[("status", "success"), ("result", message)]::HM.HashMap Text Text)
      mkError message = show . encode $
        (HM.fromList[("status", "error"), ("message", message)]::HM.HashMap Text Text)
    in putStrLn $ (either mkError mkSuccess resp)

{--
:{
  invoke (Just "decode") $
    either (const Nothing) (Just . id) $
      (invoke (Just "encode") (Just "larluo"))
:}
--}


image.png

image.png

b. 构建docker镜像my-base64:latest

[larluo@larluo-nixos:~/my-repo/my-base64]$ cabal2nix . > docker.nix
[larluo@larluo-nixos:~/my-repo/my-base64]$ cat docker.nix 
{ mkDerivation, aeson, base, base64-bytestring, bytestring, stdenv
, text, unordered-containers
}:
let 
  my-base64=mkDerivation {
    pname = "my-base64";
    version = "0.1.0.0";
    src = ./.;
    isLibrary = false;
    isExecutable = true;
    executableHaskellDepends = [
      aeson base base64-bytestring bytestring text unordered-containers
    ];
    homepage = "https://github.com/githubuser/my-base64#readme";
    license = stdenv.lib.licenses.bsd3;

    enableSharedExecutables = false;
    enableLibraryProfiling = false;
    doHaddock = false;
    postFixup = "rm -rf $out/lib $out/nix-support $out/share/doc";
  } ;
in
dockerTools.buildImage {
  name = "my-base64" ;
  tag = "latest" ;
  config = {
    Cmd = [ "${my-base64}/bin/my-base64-exe" ] ;
  } ;
}

image.png

image.png

image.png

c. 测试docker函数

image.png

2. 启动fn服务器

fnproject github网址: https://github.com/fnproject/fn
下载地址: https://github.com/fnproject/cli/releases

[larluo@larluo-nixos:~/my-repo/my-base64]$ fn --version
fn version 0.5.8
image.png

3. 创建docker函数trigger

[larluo@larluo-nixos:~/my-repo/my-base64]$ fn create app my-fn
Successfully created app:  my-fn

[larluo@larluo-nixos:~/my-repo/my-base64]$ fn create function my-fn base64 my-base64:latest
Successfully created function: base64 with my-base64:latest

[larluo@larluo-nixos:~/my-repo/my-base64]$ fn create trigger --source /base64 --type http my-fn base64 base64
Successfully created trigger: base64

[larluo@larluo-nixos:~/my-repo/my-base64]$ fn list triggers my-fn
FUNCTION        NAME    TYPE    SOURCE  ENDPOINT
base64          base64  http    /base64 http://localhost:8080/t/my-fn/base64

4. 测试检查

image.png

是不是太简单了太好用了!


三. 开战云计算-faas on k8s! (待续)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356

推荐阅读更多精彩内容

  • 摘要:本文中,我们将进一步理解微服务架构的核心要点和实现原理,为读者的实践提供微服务的设计模式,以期让微服务在读者...
    Java架构师Carl阅读 5,785评论 0 20
  • 本文是GitChat《Serverless 风格微服务的持续交付(上):架构案例》部分内容已做修改。文章聊天实录请...
    顾宇阅读 3,221评论 1 13
  • 2018年04月20王雯的感恩日记 1 感恩雨草姐解读的彼尚的功课,每天都有启发。谢谢,谢谢,谢谢 2 感恩小琼告...
    安逸O阅读 222评论 0 0