6 Generic server processes - 2019-05-01 16:32:44

GenServer https://livebook.manning.com/#!/book/elixir-in-action-second-edition/chapter-6/v-2/20 Building a generic server process 构建一个通用的服务器进程 Spawn a separate process. Run an infinite loop in the process. Maintain the process state. React to messages. Send a response back to the caller. 无论您运行什么样的服务器进程,都需要执行这些任务, GenServer 就是干了这些工作 Plugging in with modules 模块名是atom, 可以存到一个变量 iex(1)> some_module = IO iex(2)> some_module.puts("Hello") Hello 实现一个通用的模块 接受模块(callback module)作为参数 在process state 维护 module atom 在需要时调用callback module的函数 Implementing the generic code 实现一个通过的 ServerProcess

7 building a concurrent system - 2019-05-01 16:32:44

对于中等复杂的系统来说,运行几千个进程并不罕见,而较大的系统可能由数十万甚至数百万个进程提供动力 这章通过创建一个todo应用,来演示怎么构建一个并发系统 7.1 Working with the mix project 通过mix创建项目 $ mix new todo 可以使用 mix compile 命令编译项目, 也可以使用 mix test 运行测试 使用 iex -S mix 启动项目 一些项目约定 把所有代码放在一个顶层module里, 比如 Todo.List, Todo.Server 一个文件应包含一个模块, 如果辅助模块很小并且仅在内部使用, 则它可以与使用它的模块放在同一文件中 模块文件名是下划线命令, 模块名使用驼峰, TodoServer todo_server.ex 文件结构要合理, Todo.Server 模块路径应该在 lib/todo/server.ex todo 项目 code https://github.com/sasa1977/elixir-in-action/tree/2nd-edition/code%5Fsamples/ch07/todo 7.2 Managing multiple to-do lists 要管理多个todo, 两个可能的实现 抽象 TodoListCollection Todo.Server 实现新的抽象 每个todo list运行一个genserver实例 第一种方法的问题是, 最终只能有一个 process 来为所有用户提供服务 如果系统被许多不同的用户使用, 它们将经常相互阻塞, 竞争相同的资源, 因为执行任务都是在单个服务器进程内

8 Fault-tolerance basics 容错基础 - 2019-05-01 16:32:44

容错的目的是承认失败的存在,最小化它们的影响,并最终在没有人为干预的情况下恢复 在一个足够复杂的系统中,许多事情可能会出错。偶尔会发生错误,依赖的组件可能会失败,并且可能会遇到硬件故障 最后,如果系统是分布式的,则可能会遇到其他问题,例如远程计算机可能因崩溃或网络链接断开而不可用。 8.1 Rrntime errors 运行时错误 一些运行时错误, 如 模式匹配错误, 无效的算术运算(例如除零),调用一个不存在的函数 处理运行时错误 try-catch Error types 错误类型 BEAM区分三种类型的运行时错误: errors exits throws 以下是一些典型的错误示例: iex(1)> 1/0 ** (ArithmeticError) bad argument in arithmetic expression iex(1)> Module.nonexistent_function() ** (UndefinedFunctionError) function Module.nonexistent_function/0 is undefined or private iex(1)> List.first({1,2,3}) ** (FunctionClauseError) no function clause matching in List.first/1 不可用的算术表达式 调用不存在的函数 模式匹配错误 直接使用 raise/1 宏 抛出错误 iex(1)> raise("Something went wrong") ** (RuntimeError) Something went wrong tips:

Elixir Protocols vs Behaviours - 2019-05-01 16:32:44

Protocols & Behaviours 不同 A protocol is indeed a behaviour + dispatching logic. However I think you are missing the point of behaviours. Behaviours are extremely useful. For example, a GenServer defines a behaviour. A behaviour is a way to say: give me a module as argument and I will invoke the following callbacks on it, which these argument and so on. A more complex example for behaviours besides a GenServer are the Ecto adapters.

Elixir with 笔记 - 2019-05-01 16:32:44

TLDR 简单的说 defp serve(socket) do msg = case read_line(socket) do {:ok, data} -> case KVServer.Command.parse(data) do {:ok, command} -> KVServer.Command.run(command) {:error, _} = err -> err end {:error, _} = err -> err end write_line(socket, msg) serve(socket) end 像这种代码使用 with 可以重构成下面的形式,来避免 case 嵌套 defp serve(socket) do msg = with {:ok, data} <- read_line(socket), {:ok, command} <- KVServer.Command.parse(data), do: KVServer.Command.run(command) write_line(socket, msg) serve(socket) end 代码来自 https://elixir-lang.org/getting-started/mix-otp/docs-tests-and-with.html#with with 接收 <- 右边的值,进行模式匹配,如果匹配成功,则继续下一个表达式,直到所有的匹配成功执行 do 代码块,否则中止返回不匹配的值

Golang flag package notes - 2019-05-01 16:32:44

原文 https://github.com/parsiya/Hacking-with-Go/blob/master/content/03.1.md flag包基本使用 flag 提供命令参数处理功能 可以声明类型有 string int bool 例如 ipPtr := flag.String("ip", "127.0.0.1", "target IP") 如下 Flag 类型是 String ipPtr 指向Flag值的指针 ip Flag的名字 127.0.0.1: Flag 默认名字 target IP: Flag 描述 -h 时显示 也可以直接传递指针 var port int flag.IntVar(&port, "port", 8080, "Port") // 03.1-01-flag1.go package main import ( "flag" "fmt" ) func main() { // Declare flags // Remember, flag methods return pointers ipPtr := flag.String("ip", "127.

JWT - JSON Web Token - 2019-05-01 16:32:44

原文: https://dev.to/siwalik/what-the-heck-is-jwt-anyway--47hg JWT token 结构,分为三部分,通过 . 分隔 header.payload.signature header 由两部分组成 token令牌类型 通常是 JWT 使用的哈希算法 HMAC SHA256或者RSA等等 示例 { "alg": "HS256", "typ": "JWT" } 这个JSON被Base64Url编码,构成JWT的第一部分 'use strict'; var header = { "alg": "HS256", "typ": "JWT" }; var enc_header = Buffer.from(JSON.stringify(header)).toString('base64'); // ► "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" Payload 用于存放有效信息 有三种类型的声明(Claims): 保留声明(Registered claims)预定义的声明, 一般如下 iss: 该JWT的签发者 sub: 该JWT所面向的用户 aud: 接收该JWT的一方 exp(expires): 什么时候过期,这里是一个Unix时间戳 iat(issued at): 在什么时候签发的 公有声明(public claims)这些是使用JWT的那些标准化组织根据需要定义的 私有声明(private claims) 这些是自定义的声明,用于在达成共识的多方之间共享信息 示例

Umbrella Projects - 2019-05-01 16:32:44

tldr 用于处理大项目 mix管理依赖,依赖有两种 外部依赖 类似 plug 内部依赖 公司内部私有的项目 内部依赖可以使用 私有的git库 比如在mix里 def deps do [{:kv, git: "https://github.com/YOUR_ACCOUNT/kv.git"}] end 如果把一个大项目分成一个个的私有项目, 维护众多的git库会更加麻烦 Elixir 提供了更好的方案 umbrella, 可以在一个项目下创建子项目, 在一个单独的git库里 umbrella 项目结构, apps 目录下有多个子项目 + kv_umbrella + apps + kv + kv_server Mix 可以统一处理这些项目,也可以每个项目单独构建等 创建 umbrella 项目 $ mix new kv_umbrella --umbrella 生成的mix.exs 会不一样, 特别之处 apps_path 定义了子项目路径 apps defmodule KvUmbrella.MixProject do use Mix.Project def project do [ apps_path: "apps", start_permanent: Mix.

leetcode - 2019-05-01 16:32:44

https://leetcode-cn.com problems 重复 N 次的元素 - 力扣 (LeetCode) golang func repeatedNTimes(A []int) int { n := len(A)/2 result := make(map[int]int) for _, v := range A { val, ok := result[v] if ok { result[v] = val + 1 } else { result[v] = 1 } } for k,v := range result { if v == n { return k } } panic("error") } rust vec example: https://doc.

使用 GB 构建 Go project - 2019-05-01 16:32:44

GB 介绍 Site: https://getgb.io/ Github: https://github.com/constabulary/gb 官网首页介绍 A project based build tool for the Go programming language. 所以gb 是一个构建工具,依赖管理插件完成的 gb-vendor doc 为什么用gb,最喜欢的一点是 Project based workflow 基于 project bashd,而不是 GOPATH based 项目不需要必须在 GOPATH 下 项目结构 两个重要的目录 $PROJECT/src/ 我们自己的业务代码 $PROJECT/vendor/src/ 第三方的依赖在这 比如 一个 名字叫 redeem 的项目, 项目结构 . ├── README.md ├── bin │ └── redeem ├── src │ └── redeem │ └── main.go └── vendor ├── manifest └── src ├── github.