后端是什么

261 阅读5分钟

后端主要包括

  • 计算
    • 通过编程语言告诉计算机该怎么算
  • 记忆
    • 数据库
    • 静态文件

计算

计算机只能读懂机器码,不认识各种编程语言

编程语言

  • 低级语言
    • 机器语言
      • 俗称机器码,可执行二进制文件,直接操作绝对地址和绝对操作码
      • image.png
    • 汇编语言
  • 高级语言
    • 编译型语言
      • 需要将代码编译成机器码
      • 支持跨平台,不同系统编译不同机器码
      • 如:c,c++,c#,go等
    • 解释型(脚本)语言
      • 不用编译,需要程序解释运行的语言
      • 如:js、node用chrome v8引擎解释,java用jvm解释,python用CPython解释
  • 应用场景
    • PHP
      • 擅长构建低成本WEB,也是世界上最好的语言(狗头)
    • c
      • 擅长操作系统、嵌入式
    • Go
      • 天生高并发属性
    • R
      • 科学计算、统计无人能及
    • Python
      • 在AI领域独占鳌头
    • Java
      • 工业级应用服务及Android
    • node
      • 事件驱动、非阻塞式 I/O 的模型
      • 擅长io密集型场景,不擅长计算密集型

效率

  • 执行效率
    • 机器语言 > 汇编语言 > 编译型语言 > 解释型语言
    • 解释型语言里,静态类型 > 动态类型
    • 执行效率越高,内存、cpu消耗更少,响应更快,服务器成本更低
  • 开发效率
    • 与执行效率正好相反
    • 开发效率越高,人工研发成本更低,交付更快
  • 生态
    • 生态越丰富,轮子越多,开发效率越高
  • 总结
    • 开发应用不能单纯追求 执行效率 或 开发效率,而是在两者和领域生态之间取平衡

后端语言现状

  • java凭借多年积累优化和丰富生态排名第一
  • php凭借生态和较高的开发效率,
  • go凭借类型推断、简洁的语法和编译型语言的高性能,增长较快
  • node用的人不多,但我觉得早晚会火,能用js写的最终都会用js写

记忆

数据库

  • 类型
    • 关系型
      • mysql
        • 最常用数据库
        • 数据量大之后,速度会很慢,需要分库分表分片,运维麻烦。
      • PolarDB
        • 存储计算分离
        • 支持跨国同步数据
        • 比较方便横向扩展,可以替代mysql(如米哈游原神),但成本较高
      • Oracle
        • 逐渐被淘汰
    • 非关系型(nosql)
      • mongodb
        • 常用非关系型数据库
      • redis
        • 内存读写,快
      • tablestore
        • 按量付费
        • 存储计算分离
        • 必须建立索引才能查询,否则只能主键查询
        • 异步更新索引有延迟,即数据与索引不一致
      • LedgerDB
        • 中心化“区块链”数据库,数据不可篡改,适合记账等场景
        • 思路不错,但处于公测阶段,不适合生产使用
    • 类型区别
      • 关系型数据库 事务支持、数据一致性更好,可以连表查询
      • 非关系型数据库 性能更高,扩展性更好,可以复杂查询
    • 展望
      • 未来的数据库应该会往 存储计算分离 方向发展,以应付数据量的增长带来的横向扩展问题
      • 云原生数据库是大趋势
        • 基于云计算的海量扩展能力,及其优化
        • 基于硬件、协议创新的性能提升,如 绕过cpu,直接访问内存

静态文件

  • 特点:占用网络io,读写io
  • 一般使用云存储,不与后端接口部署在一起,避免占用接口网络io
  • cdn加速,更快访问速度,更低成本,PCDN更便宜

技术选型

  • 稳健
    • 语言用java或php,生态丰富
    • 数据库用mysql,缓存用redis或本地文件
    • 数据量变大后,mysql要分库分表,或换PolarDB
    • 并发量变高后,买服务器,用k8s做分布式服务
  • 激进
    • serverless架构,并发量变高后,自动扩容
    • 语言用node,
      • 一般后端接口可以说99%的时间都是在等待数据库的网络io,计算费时极少。
      • 后端是io密集型,正适合node,开发效率也高。
      • node生态 npm包丰富
      • 某些计算密集型场景用go写
    • 用uniCloud的免费云函数,MongoDB,云存储,CDN

任务

目标

  • 点击服务员,客人+1
  • 点击经理,显示客人总数

流程

  • 创建阿里云函数计算 image.png
  • customRuntime自带node,可以删掉bin/node,加快部署 修改bootstrap
#!/bin/bash
node index.js

删除bin目录

  • 安装koa
yarn add koa
let Koa = require('koa')
let app = new Koa()
...
app.listen(9000)
  • 添加静态文件
yarn add koa-static-router
let static = require("koa-static-router")
app.use(static({
     dir:"static",  //静态资源目录对于相对入口文件index.js的路径
     router:"/"   //路由命名
 }))

static/index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <!-- import CSS -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>

<body>
    <div id="app">
        <div style="display: flex;align-items: center;justify-content: center;height: 100vh;">
            <div style="position: relative;width: 400px;height: 400px;display: flex;flex-wrap: nowrap;align-items: flex-end;">
                
                <img v-for="(item,key) in 我" :src="`http://static-da62cb94-518a-45ab-ae1e-f76afc49948d.bspapp.com/21-10/what'sFrontEnd/${key}.png`" 
                    :style="{
                        position:(item.左||item.右||item.上||item.下) ? 'absolute':'',
                        left:item.左+'px',
                        right:item.右+'px',
                        top:item.上+'px',
                        bottom:item.下+'px',
                    }"
                    @click="()=>item.说?item.说():''"
                >
            </div>
        </div>
    </div>
</body>

<script>
    let 我 = {}
    let 欢迎光临=()=>{
        console.log("欢迎光临");
        console.log("");
        
    }
    let vm = new Vue({
        el:"#app",
        data(){
            return {
                我:我,
            }
        },
    })

Vue.set(vm,"我",{
    脸:{},
    左眼:{
        左:60,
        上:40,
    },
    右眼:{
        右:60,
        上:40,
    },
    嘴:{
        左:100,
        下:20,
        说:欢迎光临
    },
})

</script>
<style>
    img{
        object-fit: contain;
    }
</style>
</html>
  • 部署代码

image.png

  • 配置域名(不配置域名,会自动下载,导致不能访问静态html,阿里的免责措施) dns解析 image.png 添加自定义域名

image.png

用自定义域名访问

  • 安装router
yarn add koa-router
let router = require("koa-router")()
...
app.use(router.routes()).use(router.allowedMethods());
  • 实现 客人+1 添加接口 addGuest
let guestCount = 0
router.post("/api/addGuest", async ctx => {
  guestCount++
  ctx.body={
      code:200,
      msg:`客人+1`,
      
  }
});

前端添加点击事件

axios.post("/api/addGuest").then(res=>{
  console.log(40,res)
  let {code} = res.data
  if(code!==200){
    return vm.$message({
      message:"添加失败 "+res.data.msg,
      type: 'error',
    })
  }
  vm.$message({
    message:res.data.msg,
    type: 'success',
  })
})
  • 显示客人总数

统计接口 guestCount

router.get("/api/guestCount", async ctx => {
  ctx.body={
      code:200,
      msg:`共${guestCount}个客人`,
  }
});

添加static/manger.html 添加点击事件

axios.get("/api/guestCount").then(res=>{
  console.log(40,res)
  let {code,data} = res.data
  if(code!==200){
    return vm.$message({
      message:"获取失败 "+res.data.msg,
      type: 'error',
    })
  }
  vm.$message({
    message:res.data.msg,
    type: 'success',
  })
})

访问hz-h.gg1st.top/manager.htm…

因为是用变量guestCount存储客人总数在内存中,所以一重启,客人总数就会丢失,所以需要数据库来存储客人总数

  • 添加gg-thinkorm
yarn add gg-thinkorm
global.M=(name)=> {
    const {BaseModel} = require("gg-thinkorm");
    // console.log(16, BaseModel);
    let modelClass = class extends BaseModel {
        init() {
            this.modelName = name;
        }
    };
    let re = new modelClass({
        db_type: 'mysql', //support  postgresql,mysql...
        db_host: '',
        db_port: 3306,
        db_name: 'test',
        db_user: '',
        db_pwd: '',
        db_charset: 'utf8'
    });

    return re.field("*");
}

写入mysql链接密码

  • 修改接口addGuest,改用数据库存储添加客人记录
router.post("/api/addGuest", async ctx => {
  await M("guest").add({
      creat_time:parseInt(Date.now()/1000),
  })
  ctx.body={
      code:200,
      msg:`客人+1`,
  }
});
  • 修改统计接口 guestCount
router.get("/api/guestCount", async ctx => {
    let guestCount = await M("guest").count()
    ctx.body={
        code:200,
        msg:`共${guestCount}个客人`,
    }
});
  • 加个需求,点眼睛只统计今天的客人 static/manger.html 引入moment.js
<script src="https://cdn.bootcss.com/moment.js/2.20.1/moment.min.js"></script>

添加点击事件

右眼:{
        右:60,
        上:40,
        说:()=>{
            let startStr = moment().format("YYYY-MM-DD 00:00:00")
            let start = moment(startStr ).unix()
            console.log(75,start,startStr)
            axios.get("/api/guestCount",{
                params:{
                    start:start
                }
            }).then(res=>{
                console.log(40,res)
                let {code,data} = res.data
                if(code!==200){
                    return vm.$message({
                    message:"获取失败 "+res.data.msg,
                    type: 'error',
                    })
                }
                vm.$message({
                    message:"今天"+res.data.msg,
                    type: 'success',
                })
            })
        }
    },

修改接口

let {query} = ctx
let guestCount = await M("guest").where({
    creat_time: {
        ">=":query.start || 0
    }
}).count()