Leebber

Lyu Sen's Personal Blog Website

0%

QCon 2022 Note

For me, I split all the talks I listened this time in QCon, into 3 categories:

  • Tech Architecture Optimization
    • Tidy First
    • Scaling Bottleneck
  • System Design Concept
    • Microservices Patterns
    • Orchestration vs Choreography
  • System Design Implementation
    • Adopting Continuous Deployment
    • Distributed In-Process Cache
    • Leveraging Determinism
    • Service Mesh
    • DynamoDB in Amazon
    • CosmosDB in Azure
    • Event Processing Service in Doordash
    • Blob Storage Service in Dropbox

The categories are ordered from abstraction to concretization. I know most of the engineers like me are more interested in the low level of the implementations. And yes, some talks here(like the Determinism one is really really good), however, this time the first two categories’ talk gave me the biggest influence. I think listening to these talks help me to understand the career path better. Sometimes people have to view things out of the box.

I really appreciate this time my company, Meta, sponsors me for this event.

TL;DR

I spent 3 days at the conference. The first day is more about academic work form professors and PhD students. The other two days are more about best practice in the industry world. The topics among AI, Distributed System, Advanced Tooling, Product Introduction and Personal Experiences.

I find conferences really help people to think out of the box. And I hope I joined Meta earlier and understand our own implementations so that I could have a deeper understanding of the problem and better compare solutions.

Research Topics:

AI content generation:

Generally, it gets more and more popular. However, the idea is already there. The topic is focused on the gaming content generation. Talk about the best practice of that. Talks about setup rules and how can make it generate more “comfortable” contexts for better game experience

Breakbeats analysis

A topic talks about AI works in breakbeats(pieces background music used in songs). How the company could use that to better understand songs evolution and help them to get song’s patent fees

Textual analyze on code

A talk about how people better understand what code from language-side of view is. And how this kind of thinking could provide people with a new way to understand our code pattern and code practice. Eg:

  • Trace is one pattern for people to understand the story, it is also a way we used to find bugs.

  • When we do bottom-up implementation, we always start from the central piece in the structure. This is reasonable from the language side

Product Introduction

Google’s universal IPC language: FIDL in fuchsia

A system very like thrift, but it is used in a deeper system, for IPC. Also doing the binding, so it will support different languages. And easy to extend to other languages.

Workflow:

A new way for making a durable system

  • A practice that brings “transaction” in DB into service codes, easier for people to write concurrent code. It will be easier to do error handling.

  • The idea is to make actions more atomic. And for the actions that could change the states, make them idempotent

Filibuster:

An End to End test tool, more focus on testing error cases in end-to-end test cases, to help understand big system’s errors

Talk about in a big system, how end to end testing is needed especially for error cases. Those tests need to cover multiple failing situations.

RLBox:

A way to run native code in sandbox to avoid native code’s memory issues

  • Talk about how native code is unsafe, and how many safe languages are built on them

  • Try to run all the native code in the sandbox to make it safer.

  • It is already used in firefox

  • A way of coding, so it will be very easy and clear to add to exist system

Akita software:

A product/practice to add API listeners for developers to understand old systems.

eBPF mode to add listeners to the APIs in the old system. And their product provides a solution to better understand the system based on those listeners.

Shopify solution for flash sale:

solution in both LB layer and service layer to ensure capacity, starvation and fairness problem

Very good topic to talk about flash sale, talked very detailed about how they choose from different solutions.

Runtime Checker:

Java best practice to enhance system in observation, watchdogs and in prod regression tests

  • Very good talk about why we need runtime checker in system, and why sometimes even current wide used system could have bugs

  • Talk about fix them in three topics

  • In observation, the idea is that using some static code analysis tools, to find those errors handled locally but not reported to any response.

  • In watchdog, talks about better catch errors, so the errors could report those error into some monitoring system

  • In tests, define some testing rules to describe the system, and when running the test to verify whether those rules are still valid. (like behaviors testing along the workflows)

WNFS:

a guide on creating a local-based encrypted file system

  • Talks about how to create a good file system, including files and directory. And how to keep the history and how to merge versions

  • Also, talks on how to encrypt those files

Coding Best Practice:

Polymorphism:

different language, different solutions for better polymorphism: Overloading, Override, Interface, Parametric, Structure, Union type, ADT, Multiple dispatching…

Python Performance: scalene

要不要准备DP

我的感受是收益率很低。
近期我参加了9家公司的面试,有7家完成VO,剩下两家止步店面,加起来有31道算法面试,其中只有google vo中1题是dp,而且是较简单的dp。
面试dp其实是很好的机会,因为dp题的代码都很好写,基本上状态转移的核心部分代码不会超过10行。所以会有更多时间去解释dp。然后结合画图,也属于较容易把思维说清楚的情况。建议大家把基础的题目的思路多说几遍,然后根据视频里面学到的多画画图,面试会更容易得到认可。
大家自己选择要不要准备dp

我花在DP上的

我看的资料,首先是课堂教学型

  • 首先我看的*NOIP的资料,这位老师讲的很好 b站 动规的部分大概从9.62到9.100多
  • 然后是MIT open course,youtube

    然后是非教学型

  • 这个人的youtube channel大家应该在很多地方都能找到推荐,其中也有dp部分 youtube
  • C++的专门题解集 github
  • 背包九讲,我觉得大家一定要去看看这个,实在是讲得好,很好的背包dp入门教材
  • 最后就是 oi 竞赛的部分我没有过多深入,不过简单了解一下还是有帮助的

    剩下就是做题

  • algo export上做了112题,其中dp 13题。 11%
  • leetcode上做了210题,其中dp 65题。 30%
  • 总计24%的题目都是dp,并且后期做的leetcode,更偏重dp。

总结

时间上基本上1个月到1个半月花在dp上面。基本做到了常见题型能够解题,简单的变形dp能够比较快转化为基础题型。


NOIP 大家对NOIP可能比较陌生,我稍微介绍一下,NOIP是初中生计算机竞赛,在国内已经办了超过15年了,dp是每年的考题。经过多年的研究,老师们已经可以把基本的dp讲解到初中生都能理解的程度。而且难度并不简单,大家可以自己感受一下。然后也请大家想一个问题,如果大厂对员工的面试中体现的业务能力的要求也就是初中生的学术要求,那么还有什么是你在初中毕业后这么多年读书获得的能够让你超越初中生而被公司录取?


我对dp的一些理解

dp是难的递推。不严谨的通俗来说递推能够继续下去,体现了重叠子问题,而递推能有一个合理的路径,体现了最优子结构。

推的路径

最简单的推的路径就是线性的,其中可以是一个状态推一个状态,也可以是几个状态推一个未来状态。这样的题一般可以表述为从“左推到右”或者从“开始推到结束”。
有时候就算数据变成了图形,其实仍然适用。从“左上推到右下”,仍然可以认为是线性的推广。
树形的推,更多是从小集合推到大集合,有一种合并的感觉,体现在树上就是从叶子往根推。


这里讲的推和树形dp,图形dp等不一定一致。这里是推的方向,也就是状态转移的方向,并不一定等同于数据结构


状态不是一个量,是一组量

我们常用数组表示状态的集合,然后一般数组里面存一个数字,我们就感觉状态其实是一个量,其实不然,状态可以扩展为好几个量。当然你可以最后做成多维数组来写。比如:我们有a,b,c 3个数据来表示一个状态
dp[i].a = 1, dp[i].b = true, dp[i] = "hello"也可以写成一个二维的多类型数组dp[i] = [1, true, "hello"]甚至写成三个数组dpa[i] = 1, dpb[i] = true, dpc[i] = "hello" 这个和根据数据结构来想到dp需要二维,在思维上是不一样的
这类题中的经典就是股票买卖

压缩

上面讲了扩展,那么思维上再过度一下就是压缩了。压缩,用通俗的话讲就是不需要了。思维上就是,如果我需要前三个值算第四个值,那么算到第四个的时候第一个值就不用了。所以就可以通过减少存的状态而节省空间了。
更进一步,上面提到的一个状态里面的某些量可能只需要用一次,那我就直接存就好,不需要用数组存了,那么就变成状态之外的量的感觉。这是通过减少存状态的量减少空间。比较经典的题就是最长不下降子序列,其中维护的数组其实是随着状态变而一直在变的,但是没有必要每一次存一个数组(估计也没有会这么干)。

优化

prefix优化 与 单调队列优化

dp中所有的优化里面,我只能理解这一种优化。这种情况多发生在多重循环下,在目前这个循环内需要再做循环来算一些值,一般是最值。而我们可以发现(先是直觉,然后是数学计算)这些最值的计算可能会用到一些相同的量(prefix或是维护一个单调队列或者单调栈),所以可以将内循环的逻辑简化,一般是O(m*m)-> O(m)计算prefix或是其他 + O(m)计算剩下内容。

Design Chinese health code system 设计健康码

I found a very interesting post here: https://www.v2ex.com/t/834691
Talking about design a chinese health code

Feature

  1. Large amount user could search for their health code status
  2. Change user’s health code to unhealthy code based on their time and location if they contact with other unhealthy code

Requirement

  1. User’s health code change could happen with certain delay. ( If I contact with a unhealthy code people, I might get update to unhealthy code 1 day after )
  2. Assume user need to show their health code to get into some place, which means that user’s phone is always opening and providing their data to us. ( There will not be if people go to one place and we cannot get the data )

Design

The whole system could be separate into 2(3) parts:

  1. Part that support user check their own code. Heavy read.
  2. Part that collect user’s time and location data. Heavy write.
  3. When time goes by, one certain range of data collected in part-2 will be complete. And according to requirement-2, we can assume all the data in that time range is in the database and no more to write in. That time we could get the data out and put into an offline batch process, where we will find all the unhealthy code’s movement and get all contacted health code user. We could let automatic process or human administrate to determine the final code change.

Summary

The design helps to separate the read, write, and online, offline, so each part could optimize itself.



我发现一个很有趣的帖子:https://www.v2ex.com/t/834691
提到设计健康码的问题。

功能:

  1. 海量用户查询自己的码
  2. 根据用户的时空查询是否接触黄码/红码用户而标红或者标黄用户

    需求:

  3. 更新查询过程可以存在一定延迟
  4. 假设用户进入某些地方必须扫码,也就是说用户的时空间数据是比较实时的(不会有长时间停机不传数据的情况)

设计思路:

整个过程分为2(3)个大的部件:

  1. 查询自己码。该部件为读远大于写
  2. 收集用户时空信息。该部件为写远大于读
  3. 当时间过去之后,从2中收集到的某一时间段的写已经全部完成,根据需求2可以认为该时间段所有信息已经录入,此时对这个时间段数据来说没有了写入,所以可以将数据取出来进入离线过程,收集红黄码用户位置,比对,从而获得所有交叉用户名单,由系统自动过程或者管理员决定是否写入1中的数据库

补充:

主要是将读写过程分离,将数据处理离线化,每个部分可以各自优化而不影响。

Coding Lover or Coding Worker or Both?

Recently, my new project is pushed to production. You might think that I would be exciting about it. Because it is the second project that I designed & developed & tested, and it finally pass the review from senior engineers and goes to the production. But I am very exhausted these days about this project. I have to admit I was 100% exiting about it at the beginning, but at the end now, I was not excited at all. So what happened?
At beginning, when I get the project, I would say it is a very good project for me. The requirement is mostly focused on system designing, because the old version is already solve the core algorithm, but people are not appreciated for the stability. What I need to enhance is the system. It needs a more stable and scalable structure, so it will fits more about the production situation. So I was very exiting about this “message queue - worker” pattern implement. I draw the design diagram, I worked on the API document, I create the schema of mongo database collections. And because I learnt a lot from the bugs from the first project I worked. So I think I covered all the corner case and it should be perfect.
So after the development finished, I start to push it to production. I was behaved like the project owner, I talked with customer success team to understand their needs and requirements and of course the timeline. Then I talked with cloud ops about the deployment requirements. After that I believed the project is good to go. So I push it to the channel to go production.
But the things turned ugly at this point. As I described before, this is not a brand new deployment, but a upgrade, though it is a overall upgrade. But apparently our senior engineers are not agree with that. After a week of silence, My new design is heavily challenged. At first I feel it’s OK, because people’s concern is all reasonable. For example, the structure of the message queue. I will say my message queue is well designed, because I carefully review the code from a open source message queue implementation, and I used message queue from my first project, so I was well prepared to explain my design. But their concern is from the other pointer of the view, the reason they wish I change the structure is because they want to apply the auto scaling policy they are using now to fit for my workers. I never thought of that. This indeed is a very good suggestion, so I changed the code and message queue to fit for the standard message queue structure so they could apply the auto scaling policy to it. ( For a little more explain about this, the other service will monitoring the message queue, and if the queue is slow, they will add machine as queue consumer, so a standard queue will help to determine whether the queue is slow or not )
So I took 4 suggestions at this point and go back to enhancement my code. and after two weeks, I push the code again. After that I waited for a week and people agree to proceed to deployment again. And they required a small change at friday afternoon, so I said that I will changed it next Monday. And I did the change next Monday, but cloud team disappear again, I waited two weeks, and they came back requiring stress test and very strict code review.
So this project is delayed and delayed, I tried my best to fit for their suggestions but the bar is higher and higher, and I need to wait more on their deployment plan. I was so exhausted on the waiting. And from this point, I was not excited and try to be like the project owner, I went back as a developer, I just tell everyone what I did and waits for requirements from the others.

What I real feels, is that from that point, I changed from a code lover to a code worker. Yes, before I LOVE to code, so I did the job, and I was really happen about the results. But now, I was more and more standardized. I have to say that I learned a lot from the standards and they are very useful. But I lost my love of this project. I appreciate this change made me a better software engineer but I don’t appreciate this project to made me a code-worker. I hope I could get experience and won’t lose my love of coding.

我的疫苗第一针

资格

话说我也是个年轻小伙,本以为肯定是最后一批疫苗,结果3月就可以打上疫苗,真的是幸运。
稍微解释一下,我住在北卡州。北卡州在两周前爆出即将开始内部group 4的疫苗分配。

group 4 具体支持的有这些

对高血压就是其中之一,而我偏偏有高血压:

高血压的问题之后可以再聊,但是阴差阳错使我有了这一次疫苗的资格

话说啥也离不开抢这一件事,当时我记得是说周三开放group4的疫苗预约。我周二晚上就开始了看了,当时医院的网站就500了。看来美国人下手也挺快的。
基本上我看的就是三个网站,分别是cvs,walgreen和自己的医院。其实还有本地的一家超市也提供,叫harris teeters。只是自己最后没有去找。
cvs预约一直是没有位置的,所以我最后就放弃了
walgreen我其实刷到了一个预约,但那个是第二针的预约。本想直接按照第二针的预约去打第一针,反正也一样
最后大概在10点我刷到了几个医院的位置,最后刷到了这个时间上很早的3月的预约。估计是有人放弃了吧。不过距离挺远的,我要开1个小时到打针的地方。还计较什么呢?反正就是尝鲜先打了,周末开车兜兜风了

打针

周末我就出发了,开了一会到了。到那里是在医院的停车场内,工作人员给了我一份资料,核对了我的信息,然后问了我过敏的事情,然后告诉我不用担心我的对猫过敏。之后我开车进入这样一个绿色的停车棚:

对了里面是禁止拍摄的,我摇下车窗脱下外套,挨了一针,当时没啥感觉,然后排队在停车场等了15分钟离开。

之后和副作用

回家我就开始打state of decay游戏,一款病毒丧尸游戏。看着里面的丧尸和注射解药,不知道为什么觉得真的非常的应景。持续打了大概3个小时游戏,当天我强迫自己睡一个午觉。脱衣服的时候惊觉自己的手臂抬起来已经很痛。之后晚上开始看4小时的超长无聊电影。
第二天正常在家工作,干到下午5点,手上活干完了,想着稍微休息一下准备看一下明天的安排,突然发现自己眼皮非常酸,就开始躺床上休息。此时大概是疫苗打后30小时,然后开始发冷,我记得当时我看室外温度是21摄氏,室内我一直开空调是76华氏度也就是25摄氏。但是我必须要盖我冬天盖的毛毯,不然就会觉得冷。睡了一会到7点,丧失皮肤的冷热感觉,开始口干,但是手臂酸痛开始缓解。然后我就开始了喝水上厕所的循环,我的饮水量大概是一般时候的一倍。期间我量过自己口腔体温,36.6并没有发烧,但是窝在被窝里开始发汗,我换了薄被子仍然发汗,总体感觉就像感冒。
然后就是今天,起床时候已经没有发冷和疲惫状态,手臂酸痛更轻了,洗了一个澡后正常上班。到目前没有什么异样。

Routing with ubuntu server

Goal & Requirement

  1. I bought a NAS, I am going to use it to do backups, in the meantime, enhance the whole networks.
  2. I have an VPN server, I hope I could use that to access home service from outside, instead of using DDNS or static ip.
  3. I wish to open some service from my home networks, eg: vs code server, jupyter notebook server, so that I only need chrome for mobile devices. And for some small projects like this blog project, I could put the code in the server and use one machine to maintain the blog.

Design

Old Design and Problem

The old design is showed above,
Solution is to used a server to run ubuntu as a middle router, and it needs to provide:

  1. connection with the outside internet
  2. connection with the VPN server
  3. provide dhcp assignment for inner-network

Speed become the biggest problem of this. I found that OpenVPN has a speed limit here, normally 100Mbps is the limits. That is unacceptable. And the VPN server is not physically near my home, there already lag, but I thought I could do compromise about the lag. But not the speed, never compromise the speed.

New Design and solution

The new design is showed above:
The solution is to separate the whole inner-network into three parts:

  1. modem will assign/lease the ips of 192.168.1.xxx, this will be used for most the device to connect to the internet, it is a full speed network.
  2. raspberry pi will assign/lease the ips of 192.168.2.xxx, which will be used to auto connect to VPN, it is a limited speed network.
  3. vpn server will assign/lease ips of 10.8.0.xxx. Inner service will be open to this network.

So, if want to get full speed, choose modem network, if want to get vpn, choose raspberry network. Raspberry pi will forwarding ports to VPN networks, so when connection from VPN, they could access inner-network service. And even though we expose this service, they are still inside the VPN, so it is very safe.

ubuntu useful tools

As we mentioned before, the core of this design is in the raspberry pi. There are many manipulate on the ubuntu server in raspberry. I read a lot to learn this. So I have this part as a reference for next steps, here we will talk about some tools for future use.

crontab

cronis a very common ubuntu command for timer behavior. It provide a trigger, so at a certain time, it could trigger a action. We introduce it here because it has a config option @reboot, which could be used to add some command at the time of the server boot up, this is much easy to create a ubuntu service to do the same thing.

install:

1
apt-get install cron

run this

1
crontab -e

add this line in the file:

1
@reboot Your-Command

screen

This is a very common ubuntu tool for running a long-live service, it will help you to keep a service alive, even when you close the terminal.
Here are some common command:

  1. Check all exist screens
    1
    screen -ls
  2. Add a detached screen and run a command
    1
    screen -dmS sessionName command
  3. Connect back to detached screen
    1
    screen -x sessionName
    Three command will be enough for now.

openvpn

Install openvpn server in your machine is this a very good blog from digital ocean, to set up a openvpn server.

openvpn client:
This command will help you to start the client, still you will need to provide configs and password before execution.

1
sudo openvpn --config xx.ovpn --askpass pass.file

ubuntu netplan && network

If you used ubuntu desktop and change to ubuntu server, you will find this netplan is introduced after 16.04(?) and replace of the network. Still you could change back to edit /etc/networks/interfaces with some extra settings, but we will talk about netplan here.
netplan provides some configs in different files.

1
2
00-installer-config.yaml
50-cloud-init.yaml

And you can use one command to create combined rules for test run

1
sudo netplan --debug generate

At the end you could apply the rules

1
sudo netplan apply

And each file is a yaml file,there is a example for a static ip connection setting:

1
2
3
4
5
6
7
8
9
10
network:
ethernets:
eth0:
addresses:
- 192.168.1.2/24
gateway4: 192.168.1.1
nameservers:
addresses:
- 8.8.8.8
version: 2

iptables

iptables is used to setup ip transfer and port forwarding.
Let’s see some example of the command for iptables.

check

When you need to check the nat status

1
sudo iptables -t nat -vnL

POSTROUTING && PREROUTING

When you need to set routings:

1
2
sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
sudo iptables -t nat -A PREROUTING -p tcp --dport 21 -j DNAT --to-destination 192.168.1.2:21

The first one means that, when all the connection in the post-routing status, set them to handled by network interface tun0. So that all the network will pass to tun0 to handle.
The second one means in the phrase of pre-routing, forwarding all the request for port 21 to port 21 in 192.168.1.21.

And if you want to delete the rule above when you make some mistakes, simply change A to D here

1
2
sudo iptables -t nat -D POSTROUTING -o tun0 -j MASQUERADE
sudo iptables -t nat -D PREROUTING -p tcp --dport 21 -j DNAT --to-destination 192.168.1.200:21

Implementation

I followed this blog to start, and did some adjustments on my own:
Base

  1. Change ip
  2. Set up dhcp server
  3. Config ip transfer
  4. Setting NAT routing

Most of the steps are the works for me in 1-3 steps, and I will need to do some more the step 4.

How I setup my NAT routing rules

Let’s talk about network interfaces first

I have three network interfaces, they are represent to three networks, two of them set in netplan, and tun0 is created automatically when vpn connection set up:

  • eth0 is used for 192.168.1.xxx
  • tun0 is the vpn, used for 10.8.0.xxx
  • eth1 is used for 192.168.2.xxx

And my post-routing is very easy, like this:

1
2
3
4
5
Chain POSTROUTING (policy ACCEPT 14213 packets, 1060K bytes)
pkts bytes target prot opt in out source destination
39 2702 MASQUERADE all -- * eth0 0.0.0.0/0 192.168.1.0/24
2 96 MASQUERADE all -- * eth1 0.0.0.0/0 192.168.2.0/24
4101 2089K MASQUERADE all -- * tun0 192.168.2.0/24 0.0.0.0/0

Some explains:

  • For all connection target 192.168.1.xxx they will be change to eth0 to handle
  • For all connection target 192.168.2.xxx they will be change to eth1 to handle
  • The rest will go to tun0
    First two will used in port forwarding next, the last one is used for inner network connection

Then you could use command like this sudo iptables -t nat -D PREROUTING -p tcp --dport 21 -j DNAT --to-destination 192.168.1.2:21 to do port forwarding. Here I forwarding connection to port 21 to 192.168.1.2

How to save all routing settings persistently

First of all, beside tun0, all the rest settings could saved as the blog talked before using iptables-persistent. Base the only problem is, when updating the rules, I have to reinstall iptables-persistent and saved again, otherwise it wont saved, I dont know whether this is a bug.
However, this cannot work for rules related to tun0, because tun0 only exist when the VPN connection is established. So if you saved the operation above, when you do the restarting, it will auto change will is tun0 to eth0.

1
2
3
4
5
Chain POSTROUTING (policy ACCEPT 14213 packets, 1060K bytes)
pkts bytes target prot opt in out source destination
39 2702 MASQUERADE all -- * eth0 0.0.0.0/0 192.168.1.0/24
2 96 MASQUERADE all -- * eth1 0.0.0.0/0 192.168.2.0/24
4101 2089K MASQUERADE all -- * eth0 192.168.2.0/24 0.0.0.0/0

So what we will do is to used auto start to start VPN client first, then add the NAT routing rule. The way to do it is to use crontab -e to add a command to do execution.

1
@reboot bash /home/xxx/start-client.sh

And the file /home/xxx/start-client.sh is like:

1
2
3
screen -d -m -S openvpn sudo openvpn --config /home/xxx/xxx.ovpn --askpass /home/xxx/openvpnpass.txt
sleep 10
sudo iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o tun0 -j MASQUERADE

Some tips

When you try to setup network, you might lose the connection to the server if you make mistakes. Before this I didnt bought the hdmi cable for raspberry pi, so I have to reset it several times to get connection back. So I highly recommend you put a plan B here when network connection broken, use a hdmi to change the mistake back.
Also, when you do some changes for the whole networks, you might still have a wifi connection from the top level. So if connection is error, you still have a connection to the internet from wifi, you can still do some search on the problem. And it will be easy to set it back when you finished.


ubuntu server实现路由

目标和需求

  1. 买了一个nas,想用来做备份,加强一下家庭网络
  2. 有一个自己的vpn服务器,想用这个代替公网IP/DDNS,来做家庭网络的户外接入
  3. 想在内网开放一些服务,比如vs code的服务器端,或者jupyter notebook这类的服务器端,这样移动设备只需要chrome,而且处理blog的代码也就可以放在一处了。

设计

旧设计与问题

旧设计如图,
思路是用一台跑ubuntu server的服务器作为中间的路由器。它能够:

  1. 连接外网
  2. 连接VPN服务器
  3. 提供内网的ip分配

实现下来发现最大问题是网速。我使用的OpenVPN的网速是有上限的,100Mbps是一般情况下的极限。这个网速是完全不够的,况且本身vpn服务器的地理位置也不是我目前家里的位置,延迟本就很高,本来还想勉强接受一下延迟,但是这个网速肯定不行。

新设计与解决问题

新设计如图:
思路是将整体分为三个部分:

  1. 光猫分配192.168.1.xxx网段,作为大多数设备的主要上网网段,这个网段是全速的。
  2. 树莓派分配的192.168.2.xxx网段,作为自动连接vpn的网段,这个网段是vpn的。
  3. vpn服务器分配的10.8.0.xxx网段,作为外部连接连回时候使用的网段,这个网段主要是要开放内网服务的。

这样解决的是,如果内网要全速就走光猫网段,如果要vpn就走树莓派网段,换个无线连接就可以了。树莓派上面转发内网的服务给vpn网段,这样在外面连上vpn就可以用内网的服务了,这些服务虽说是暴露,但其实是面向vpn内网的,也比较安全。此外树莓派我是买一个usb网络转换器的。

ubuntu server有关的工具

如图所示,我们的核心就是被色彩包围的树莓派的操作,这部分涉及很多ubuntu server的尝试。我也是看了很多资料,边看边学。这部分先整理一下,主要围绕很多必要的工具的介绍和使用方法。

crontab

cron是一种常用的ubuntu定时执行命令的工具。它提供一种触发,在某个时间点,能够执行一个动作。这里提到它是因为它有一个@reboot的选项,可以用来插入一段命令,做ubuntu的自启动。这个的配置比写ubunt的服务要方便的多。

安装:

1
apt-get install cron

运行这个

1
crontab -e

然后在文档里面添加:

1
@reboot Your-Command

screen

ubuntu里面非常常用的跑常驻程序的工具,它让你不会因为终端的断开就结束运行着的程序。
这里介绍几个命令:

  1. 检查已有的screen
    1
    screen -ls
  2. 添加一个screen并运行命令,且离开
    1
    screen -dmS sessionName command
  3. 连接screen
    1
    screen -x sessionName
    有了这里的几个命令就可以很快上手screen

openvpn

首先是服务器部分,digital ocean有一个很好的openvpn server搭建的教程。我就不在多言。

openvpn客户端:
一条命令可以让客户端跑起来。当然你要把配置和密码存好

1
sudo openvpn --config xx.ovpn --askpass pass.file

ubuntu netplan && network

如果你用过ubuntu桌面版,再使用ubuntu服务器版,就会发现,可能是16.04以后新引入了netplan的写法代替了network的default写法。当然可以取消掉netplan的配置仍然编辑/etc/networks/interfaces,不过这里说一下我理解的netplan的配置。
netplan提供了不同等级的配置文件:

1
2
00-installer-config.yaml
50-cloud-init.yaml

之后使用命令来生成一个综合了以上规则的plan

1
sudo netplan --debug generate

最后在用apply来实现

1
sudo netplan apply

具体写法是yaml语法,这里给一个网络接口与静态ip设置的简单例子:

1
2
3
4
5
6
7
8
9
10
network:
ethernets:
eth0:
addresses:
- 192.168.1.2/24
gateway4: 192.168.1.1
nameservers:
addresses:
- 8.8.8.8
version: 2

iptables

iptables是用来做ip变换的设置工具。
iptables的一般规则使用方法如下,但也不是所有的选项在一条命令内都存在:
iptables [-t 表名] <-A|I|D|R> 链名 [规则编号] [-i|o 网卡名称] [-p 协议类型] [-s 源ip|源子网] [--sport 源端口号] [-d 目的IP|目标子网] [--dport 目标端口号] [-j 动作]

其中动作的选择有:

1
2
3
4
5
6
7
ACCEPT          接收数据包
DROP             丢弃数据包
REDIRECT      将数据包重新转向到本机或另一台主机的某一个端口,通常功能实现透明代理或对外开放内网的某些服务
SNAT             源地址转换
DNAT             目的地址转换
MASQUERADE       IP伪装
LOG               日志功能

以及操作类型的解释

1
2
3
4
-A 增加
-I 插入
-D 删除
-R 替换

我们来看一些具体的例子

check

当你需要查看nat的情况时

1
sudo iptables -t nat -vnL

POSTROUTING && PREROUTING

当你需要设置routing操作的时候

1
2
sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
sudo iptables -t nat -A PREROUTING -p tcp --dport 21 -j DNAT --to-destination 192.168.1.2:21

第一条的意思是将所有的信息在postrouting过程中,将出口设置为tun0网卡来处理。这样所有的网络都会通过tun0网卡来发送。
第二条的意思是在prerouting阶段,对该服务器的21端口的请求转发到192.168.1.2的21端口上

如果你要删去上述两条:

1
2
sudo iptables -t nat -D POSTROUTING -o tun0 -j MASQUERADE
sudo iptables -t nat -D PREROUTING -p tcp --dport 21 -j DNAT --to-destination 192.168.1.200:21

具体实现过程

我的实现,是这位大神实现的一个扩展:
Base

  1. 修改ip
  2. 配置dhcp
  3. 配置ip转发
  4. 设置NAT routing

其中前三项基本没有什么改变,所有的额外操作都在第四条的时候。

如何设置我的NAT routing规则

首先是网卡

我有三张网卡,对应着三个不同的子网,这些配置在netplan之中设置好了(tun0是vpn client自动生成的):

  • 网卡1是eth0,对应 192.168.1.xxx
  • vpn是tun0,对应 10.8.0.xxx
  • 网卡2是eth1,对应 192.168.2.xxx

然后我的post routing很简单

1
2
3
4
5
Chain POSTROUTING (policy ACCEPT 14213 packets, 1060K bytes)
pkts bytes target prot opt in out source destination
39 2702 MASQUERADE all -- * eth0 0.0.0.0/0 192.168.1.0/24
2 96 MASQUERADE all -- * eth1 0.0.0.0/0 192.168.2.0/24
4101 2089K MASQUERADE all -- * tun0 192.168.2.0/24 0.0.0.0/0

解释一下,

  • 所有目的地是 192.168.1.xxx 这类的请求走eth0,
  • 所有目的地是 192.168.2.xxx 的请求走eth1,
  • 剩下的从内网发出来的信息走tun0。
    前两条为之后实现内网端口转发作准备,后一条是实现内网都是vpn连接

然后就是用类似这样的请求 sudo iptables -t nat -D PREROUTING -p tcp --dport 21 -j DNAT --to-destination 192.168.1.2:21把你要转发的端口转发出去

如何永久保存routing信息

首先跟tun0无关的所有信息都是可以利用Base这里的方法进行保存,即iptables-persistent来保存,不过我这里有一个问题,每次更新的时候我需要重装iptables-persistent,再保存,不然就会消失。我不请求是不是bug。
不过跟tun0有关的信息就不能这样了,因为tun0只有在vpn启动的时候才会出现,所以如果你保存了上述的操作,重启后,会看到默认把tun0的地方改成eth0

1
2
3
4
5
Chain POSTROUTING (policy ACCEPT 14213 packets, 1060K bytes)
pkts bytes target prot opt in out source destination
39 2702 MASQUERADE all -- * eth0 0.0.0.0/0 192.168.1.0/24
2 96 MASQUERADE all -- * eth1 0.0.0.0/0 192.168.2.0/24
4101 2089K MASQUERADE all -- * eth0 192.168.2.0/24 0.0.0.0/0

所以我们要利用自启动来启动vpn,再增加这条命令。具体就是利用crontab添加一条执行,执行内容是openvpn,并且写入nat crontab -e 添加

1
@reboot bash /home/xxx/start-client.sh

具体执行脚本/home/xxx/start-client.sh:

1
2
3
screen -d -m -S openvpn sudo openvpn --config /home/xxx/xxx.ovpn --askpass /home/xxx/openvpnpass.txt
sleep 10
sudo iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o tun0 -j MASQUERADE

额外的坑

调试网络很麻烦的点就是网络配置错了,就连不上了。我当时没有买视频线,所以重置了几次树莓派。比较建议一定要用视频线直接连接,你在尝试的时候指不定就掉了。
此外,在做全局调整的时候也要用wifi先保证一个点可以接入互联网,这样也方便查阅资料,不然总机网络错了全部都连不上了。

三个月一重构

game

我还记得很早以前我第一次改已有的代码,那是一个api接口。我还记得那时候需要的是对不同的接口做api传递,要带着它的cookie。那是我刚开始写代码。所以我给所有的api都写了一个转接代码。之后回去看的时候,我才意识到,ok,一个转换函数就可以搞定所有的情况。于是我把它重写到了一个函数之中。虽然那个函数还是很大,不过比之前5-6个函数要舒服多了。
第二次重构是第二个项目业务逻辑大调整。这个倒是没什么说头,因为整个业务逻辑变化了,必须要重写。之前的demo模式不可行,于是删掉了一大半的代码,开始重新写了。其实这很好,当初写的时候有很多解法都太直接了,有很多过程可以抽象化的,重构就帮我解决了之前的问题。
第三次重构还是第二个项目,我学习了async/await写法,代替了之前的promise写法。async比promise好的一个地方就是promise链处理条件过程很复杂,会写出树型的结构。如果用async来写就能避免这个问题。多提两句,async function会将后面的返回结果也变成promise,所以处理同步过程的时候需要用function和promise而不是直接用async。而且new Promise里面有些部分的代码也是直接执行。
然后就是目前在写的项目。这个项目我一开始就设计了是比较抽象的模式。但这个项目也经历过重写,最重要的一次就是引入了multi processing。多进程加入了很多其他的控制元素,信息交换元素。
之前的一次,我重写了其中很复杂的一部分,加入了复杂的异步错误处理,异步的数据库不同步比较复杂,还加入了错误重试,系统的稳定性增加了。
最近的这次重写主要是agent worker模式的改写。修改的更加稳定。以及整体的错误处理。

每次重写都能发现很多好的模式将来可以复用,每次重写都能发现很多不好的习惯需要去掉。我觉得重写就是之前积累的一次总爆发。可惜,就是太累了。

How I Build This Blog Second Part.

This post will provide many basic concepts for entry level blog user. I believed that before you thinking about how to implement something, you have to understand what you are building and why you needs to do that. Back to the days when I know nothing about web or blog, many tutorials I was followed will simple tell you to do step one, step two, but I dont know anything about what this step for. So this time, I will be first talk about these basics, and try to make them unrelated with the languages. If you already have good understanding of networking, you should skip this post.

Website

My way to understand the website is that the website is the resources on the server. When user using the browser, they open the resources which come from the remote server, like images, texts. Then the browser will download the resources and do some manage and they will show you the web page. Image you are using MS Word, you open that, then you choose a file to open. The browser is just like MS Word, the address you put in browser is the address your file you opened. Only difference is that you opened a remote file and you cannot edit but read-only.

Server

Server is just a remote computer. You are not using your usb-mouse or usb-keyboard to interact with them, instead you are using internet signals. In server, you need to put on your web pages and open them to everyone, so people could get this by internet. Start from here, your website is open to visit.
Every server in internet will have a ipv4 string, mostly. And if you rent server from others, they will provide that. You can think of that is the unique name of your server, using which everyone will find this particular server, and using which you could login this server. When you buy/rent a server, I strongly recommend you to read this to do basic settings.
Some server providers are AWS from amazon, azure from MS. And Linode, Vultr. For me, I use digital ocean. I would recommend you AWS, because it is the most used provider. And digital ocean is good to entry levels, they have many posts and instructions for documents. Here I will provide my refer code for digital ocean.

Domain && DNS

Your server’s ipv4 is just like a phone number, apparently no one could remember all the phone numbers, so no one will remember your ipv4, everyone will remember something like google.com / facebook.com. So the domain is used to replace that.

  • The biggest domain provider is goddady. and I am using google domain now, they both are good domain providers.
  • There are some domain provided free, like Freenom have some domains are free to use, they are good for you to play around.
    After this you will need to link your domain with you server, this could be done with DNS configuration. In some cases, domain provider may not provide DNS for you, you may need to find yourself a free DNS provider. It is not difficult, you just need to set something called A record. Most DNS provider will have documents to tell you how to do that. A record is just like put your number into the phone book.

SSL certificate

Most website nowadays will provide something called certificate, that is ssl certificate, it is used to encrypt you webpage. Image online shopping, when you request your website from your server, is just like shopping online, the delivery guy is delivery your resources to you. If you dont have a ssl certificate, it just like no box of the package, so the delivery guy will know what it is right away.
There is a very easy way to get ssl and totally free, that is let’s encrypt. They have a very easy way for you to do it, I strongly recommend you include that in your website.

Non-server implement

Some instruction you might read tells you that you dont need a remote server nor a domain. So why is that? Actually, these two things is provided by others. Let’s take a look at this very good example github page.
Every github page will provide you a domain like xxx.github.io. This domain is actually a sub-domain for github.io( all domain comes from back to front, normally you see them in the format of xxx.xxx, here you see aaa.bbb.ccc, you will know that is sub-domain for bbb.ccc). However, the subdomain actually does the same thing as normal domain, they all replace the complex ipv4.
In the similar way github also provide the server, because you actually post your page data to repo in github, so the git is just like a server, it contains the resources, it could be managed by git, it could also managed by web.
So no server implement is also have server and domain.

Frontend & Backend

Here we use a not strict definition here. As we talked before, open a website is: find the server, request the resources, get the resource and show them to users. In this process, backend is referring to when people find the server, backend will be that one to response to provide resources from server to people. And frontend is actually the resources, when the browser gets the resources, frontend code tells the browser how to manage the resources and show the web page to the user.

Image Hosting Service

You put your resources in server, but that does not mean you have to get all your recourses from one server. FOr example for the pictures, you can post them on your server, but also you could use a image hosting service. So the images won’t takes all your storage.

Google Analytics & Other third party

Google Analytics are very easy to use tool for the website owner to do virtual analyses to learn about the usage of their website. Those service, including salesforce, are main source for data used for marketing campaign. They will gather data from people who visiting the website, normally they will get location info, time info and click info from the user. Web analytics are very big area, I like to recommend you to install it and try, it is totally free.
And about installment of these kind of third party service is really easy. First you need to register in their website, and get a id to represent the data you will get from the page. Then you will ingest a code, which they will provided to you and the id together into your webpage, that’s all. Then you just need to go back to their website to see the results and beautify charts.

RSS

RSS is a kind old stuff, but I still think it is cool. You could get a abstract from every posts in web in certain rule and put them all into one file. That file will increase when you write new posts. So other people by listen to the changes of this file to know that you provided new posts. They could use RSS reader to read the abstract of your posts and even open your post to read more. Creating RSS file is also very easy, you just need to make that file to public.



我如何搭建这个blog系列 第二篇

这篇文章将面对新手,提供很多常识性概念。我一直认为必须要先明白你在做什么,为什么需要做这个,最后才是如何实现这个。当我还是一无所知的菜鸟的时候,很多blog上来就是第一步第二步就开始了,而我当时都不明白第一步第二步是什么。所以我这篇文章要先来写清楚这些问题。接下来我会以最简单的方式,来讨论很多常见的概念,争取做到与具体的实现技术无关,让读者明白到底blog是怎么来的。对于已有网络基础知识的人可以跳过。

网站基本

最简单的网站理解,网站是一个服务器上的资源。用户使用浏览器,打开了远程服务器上的资源,包括图片文字信息等。然后浏览器做一定的整合这些信息生成看到的网页。想象你打开一个MS Word,然后选择文件,打开你的一篇具体的文章。浏览器就像是MS Word,你输入的地址就是你想要打开的文件位置,有一点区别的就是,回车之后你就打开了服务器上的文件,而且你不能修改他网站上的文件,你只能看。

服务器

服务器就是一台远程的计算机。对它的访问不是通过链接usb的鼠标和键盘,而是通过网络信号。在这个服务器上面,你需要放上你的网页,并且将它们向所有人公开。这样所有人将可以通过网络访问这些内容(但他们不可以修改)。由此你的网站就可以被访问了。
每一台在网络中的服务器,大部分都会有一个叫做ipv4地址的字符串,如果你租用别人的服务器,他们会给你这个地址,你可以将这个字符串理解为你的服务器全球唯一的名字。利用这个名字大家都可以找到这台服务器。而你利用这串数字就可以登录你的服务器。
当你购买了服务器之后,我强烈建议你阅读这篇文章来做最基础的设置。
一般的服务器提供商有amazon的aws,MS的azure,还有一些你在翻墙指南中会听到的名字,比如Linode,Vultr,板瓦工。而我自己经常使用的是digital ocean。我觉得aws是最大的最普遍的提供商,我比较推荐。还有就是digital ocean,对新手很友好,教程很多。我这里也贴一下我的digital ocean的refer
我不建议购买国内的提供商,因为还要备案管理。国内比较有名的就是阿里云,腾讯云。

域名 & DNS

你的服务器ipv4就像是一串电话号码,很显然没几个人记得每个好友的电话号码,所以属于你的服务器的无逻辑的一串数字是不可能让人记得的,大家记得住都是baidu.com,qq.com,这样的网址。域名就是用来替代的,所以你需要买一个域名来代替。

  • 最大的域名提供商是godaddy,我目前在使用的是google domain。
  • 国内的域名也一样不推荐因为备案原因。不过如果你想买.cn的就得考虑国内的域名提供商,比如阿里云。
  • 当然有一些域名是免费的。比如Freenom旗下的有一些域名是免费的,免费域名挺适合新手作为练手使用。
    有了域名接下来的任务就是将域名与你的服务器绑定。这个是通过修改DNS配置来操作的。有些情况下,域名提供商可能不提供具体DNS服务,你可能需要自己寻找免费的DNS解析提供商。不要着急,这里并不复杂。具体是添加一种叫做A记录的东西。一般提供商都会提供介绍如何操作,操作这里就不展开了。你可以理解整个DNS解析就是让整个世界知道你的域名是连接着你定义好的服务器的,不然他们还会以为你的域名跟没被购买一样,没有连接到任何的电话号码。

SSL证书

现在的网站你可以看到多半有一个叫做证书的东西,那个就是ssl证书,它是用来加密网页信息的。想象一下,你向服务器请求的时候就像是在网上下单购物,快递员将你需要的网页,如同送快递一样送达你手里。如果没有ssl证书,就像没有包装盒,快递员一眼就看到你买的东西,虽然他每天运送几万个包裹,可能并不会感兴趣你的内容是什么,但你肯定不想他知道对吧。
ssl证书有一个很简单的获得方式,是完全free的,叫做letsencrypt,有配套的教程非常方便,强烈推荐。

所谓无服务器搭建

我们可以看到一些教程说的不需要服务器的搭建,很多教程也说不需要域名。那到底是怎么一回事呢?其实他们是都提供了。举个最简单的例子,github page。
github会提供给你一个类似xx.github.io的域名。这个域名其实是github.io的一个次级域名(域名都是从后向前的,一般只有两级xxx.xxx的形式,所以当你看到是aaa.bbb.ccc形式的域名,你就知道了其实是bbb.ccc的域名的次级域名)。但次级域名功能性上来说和一般域名是一致的,因为都是替代了“电话号码”——复杂的ipv4。
同样的github其实也提供了服务器,因为你将会将你生成的页面数据提交到github的repo之中,而git其实就是一个服务器一样,存放着资源,只不过是以git的规则存放。所以一样可以用来作为网页内容来存放。
所以无服务器搭建不是真的没有服务器没有域名,只是你在利用他们的改进来省力。

前端 & 后端

这里只讲一个不严谨的讲法。我们之前说了,浏览网站的行为就是,找到服务器,询问服务器的资源,获得服务器的资源,将资源展示给用户看。所以后端在其中的任务就是当有人找到了服务器,后端负责把资源交给那个人。而前端就是这些资源,当浏览器收到了这些资源,浏览器根据这些资源,生成用户看到的一切,所以前端指引着浏览器,生成最终用户看到的一切。

资源 & 图床

服务器上存放着资源,但这不代表你的网页中的资源必须从一个服务器上读取。比如说图片,你当然可以放在你的服务器上,同样的你也可以将图片放到其他的地方去存放(一般来说网页中最大的资源就是图片),有一种俗语叫“图床”就是形容这种图片存放服务。如果你的网站上的资源太多,而显得臃肿,你可以考虑使用图床。

Google Analytics & 其他第三方服务

Google Analytics是一种很方便的数据统计可视化软件来帮助网页管理者查看网页的使用情况。这种服务还有saleforce等目前是市场运动很主要的工具和数据来源。他们通过收集访问网页的人的信息(位置信息,时间,点击内容等等)来分析网站。比如如何调整用户界面等等。web analytic是一个很大很新的一个市场,这里就不过多展开了,只是建议大家可以装一下体验一下。
像这类的第三方服务安装有一种共同的方式。首先用户在对方平台注册,获得一个代表将来从我方网站上获取数据的标识。然后将网站上提供你给你的代码和这串标识合起来,插入到前端页面之中。这样就完成了,简单吗?之后就只需要在对方网站查看数据的结果就行了。

RSS

RSS是一种比较老的东西,但我认为是非常有意思的技术,这里提一下。每个blog,将它的文章的摘要以一种固定方式生成一个文件。所以这个文件会随着你的文章数量越来越多而增长。而其他人通过有间隔的监听这个文件的变化而得知你的文章更新。其他人将会用rss阅读器了解文章的摘要,并且可以打开文章继续阅读。生成很容易,使用也只需要暴露这个文件即可。

How I Build This Blog First Part.

Requirements:

After nearly 2 years at this field, now I know how to speak before anything to be done. Yes, you need to ask the million dollar question: could you clarify your requirements?
Before I build this Blog, I asked myself what is the requirements for this blog? Here are some of mine requirements:

  1. First of all, easy to build, easy to maintain. The reason I built this blog is to write stuff, not fixing the blog all the time. I don’t want to waste all my time on blog system, I want to focus on the writing, Ok, I didn’t write much
  2. It should be easy to write, so I will be willing to write the blogs. If the blog is hard to use, than I may hardly use the blog.
  3. It has to support my personal domain: senlyu.com . Yes, this domain is so damn cool, why not using it?
  4. It need to be flexible, right now it is a blog, but one day if I find something interesting, I dont want to open another system to support that feature. The potential features I am referring to here is the API system.

Choices:

Ok, let have a look for some choices:

WordPress

It has been a while for me to look back to wordpress. The first blog I build is using wordpress. I think I followed the digital ocean instruction, step by step, and build a stable wordpress, even though I dont know much about apache and front end style. Still I get a nice webpage and using that to get this job.
WordPress is good at writing blog, even you know nothing about blog system, you can write in docs, you can write WordPress. But the building process is a pain in the ass, I don’t want to maintain a apache system for this. And it it not flexible for me. Although, I could choose online version from wordpress.com. But if I want to use my own domain, they gonna charge me for that. SO, bye bye WordPress.

Ghost

My first project from my job is to build a system, which is using ghost. So ghost is a old friend to me.
Ghost one of the biggest blog project is JS community. Easy to write like WordPress, very easy to post a post. And I am very familiar with the system.
The problem I am facing is that the installment. At first I tried digitalocean auto install, this install process will provide you installment including database, ssl cert and all other necessaries. However, the validation of ssl cert always blocked me to install. Because when I link the machine with the domain, it will take some time for dns to setup the link, but the install process will be right away to install everything. So I go and check the documents they have, I found it is outdated. So I think this is a dead end. If the installment is ready this hard, no way it will be a easy maintain.
By the way, there is a way I could do using ghost, just like I did in my first project, is to use something like this. This is very cool, although the biggest problem is that this could only run in demo/development mode. it is not a production solution. Still this is enough for most of the blog use case. But I wish I could do it better. So see you Ghost.

hexo + express

So I came to the last choice, md2html blog system + backend support. I use express all the time in work, I am already very familiar with it, ( by saying familiar I mean I worked on more than 1 year on 3 projects all using express, and read all the documents on web, especially on deployment recommendation, and even a little bit source code). So why not express?
And hexo, is a md2html blog system. It is not easy to write like above two options, but still good for me.

So

My final choice will be hexo + express. That will be the most easy way for me to start this project.



我如何搭建这个blog系列 第一篇

需求

工作了两年之后,我终于知道在开始做任何事之前必须要说出口的事情。永远不要忘了问:是否能再跟我明确一下需求?
在我开始搭建工作之前,我就问了自己这个问题,如今我有这几个需求:

  1. 首先,容易安装和维护。为什么这个放第一,就是因为我懒,我不想经常更新blog配置,或是担心部署的问题,我想多写blog其实也没有写很多文章,关注点应该在文章上面,而不是blog的技术上面。
  2. 第二,一定要写文章简单。很简单,写文章简单的话就会让我更容易去写文章。如果写起来很复杂只会让人不想用。
  3. 第三,一定要支持我的个人域名,我这么吊的域名买了不是白买的,我一定要上个人域名。
  4. 第四,要灵活。不一定什么时候我可能要用这个blog的服务器做点啥事,这个服务器不能是死的,要比较容易来拓展,而这个对我而言就是用node js做base,这个语言我最熟(呼应第一点)。

选择:

我目前的一些选择

WordPress

wordpress是很久之前用的了。我的第一个blog就是用的wordpress,我当时应该是按照digitalocean上面的教程一步一步的安装了完整的wordpress,虽然我根本不懂大多数步骤到底是干嘛的,包括apache和前端。但我仍然搞出一个漂亮的页面让我得到了我如今的工作。
WordPress用来写blog真的方便,就算你不懂blog,只要你能写word文档,你就能谢blog。只是这个安装过程很麻烦,而且我也不想管理一个apache。我也不懂apache。
当然,也可以偷懒选择wordpress.com官网上的版本。不过如果我要用自己的domain就要收费。所以再见了您WordPress。

Ghost

我工作的第一个项目就是一个含有ghost系统的项目。所以我非常熟ghost。
Ghost是js上面最大的做的最好的blog项目了。写起来跟wordpress一样方便。
但是我真正遇到的问题就是安装,我试了用digitalocean的自动安装过程,它会自动帮你装好数据库,ssl等所有用到的工具。但是验证ssl的过程老是卡住,因为连接云主机和domain的dns设置不是马上起效的。然而我翻阅了他们的文档,我发现极度过时。这可是大忌,装的时候都是问题,维护怎么办?果断跑路。
额外介绍一种我们工作中用的ghost的方式。是类似如下的ghost as middleware. 但这个是demo/develop版本的ghost,ghost的production版本比较复杂也不适合这个模式。如果使用production版本的ghost,就很难和express相结合。no no

hexo + express

最后我们就来到了这个选项。我对express真的非常熟,我之前工作都在用express,我读过文档和源码。所以还是使用express吧。
至于hexo,我还是使用了md->html的hexo,虽然写起来没有前面两个方便,不过md我也需要去熟练。

最后

所以最后我的最终选择就是hexo+express, 对我而言就是最简单的方法