• 当try_files遇上gateway是如何产生火花的


    我们做了多分支管理环境隔离,一套满足开发调试、测试、产品验收、多需求并行开发的千人千面的环境。请求进行精准路由,其中有个环节是需要将前端项目作为一个服务注册到注册中心。
    这个项目用得是nacos 通过shell构建脚本如下:

    #!/bin/bash
    set -e
    SERVICE_ADDR=xxx.xxx.xxx.xxx:8848
    IP=${POD_IP}
    PORT=80
    SERVICE_NAME=portal
    NAMESPACE_ID=xxxx-xxxx-xxx-xxx-xxxxxxxx
    
    METADATA=$(cat <<EOF
    {"preserved.register.source":"shell","branch":"${BRANCH}"}
    EOF
    )
    urlencode(){
    	echo "$1" | tr -d '\n' | od -An -tx1 | tr ' ' '%' | tr -d '[:cntrl:]'
    }
    #registe params
    registerData="serviceName="$SERVICE_NAME
    registerData=$registerData"&healthy=false"
    registerData=$registerData"&ip="$IP
    registerData=$registerData"&port="$PORT
    registerData=$registerData"&weight=1.0"
    registerData=$registerData"&namespaceId="$NAMESPACE_ID
    registerData=$registerData"&ephemeral=false"
    registerData=$registerData"&metadata="$(urlencode "$METADATA")
    #beat params
    beatParam="serviceName="$SERVICE_NAME
    beatParam=$beatParam"&ip="$IP
    beatParam=$beatParam"&port="$PORT
    beatParam=$beatParam"&namespaceId="$NAMESPACE_ID
    beatData=$(cat <<EOF
    {"cluster":"DEFAULT","ip":"$IP","port":$PORT,"metadata":$METADATA,"scheduled":true,"serviceName":"$SERVICE_NAME","weight":1}
    EOF
    )
    beat=$(urlencode "$beatData")
    beatParam=$beatParam"&beat=$beat"
    
    
    function register () {
        curl -X POST "http://$SERVICE_ADDR/nacos/v1/ns/instance?$registerData"
    }
    
    function delete(){
        curl -X DELETE "http://$SERVICE_ADDR/nacos/v1/ns/instance?$registerData"
    }
    
    function beat(){
        while true
        do
            curl -X PUT "http://$SERVICE_ADDR/nacos/v1/ns/instance/beat?$beatParam"
            echo ''
            sleep 3
        done
    }
    
    case "$1" in
        register)
            register
            ;;
        delete)
            delete
            ;;
        beat)
            beat
            ;;    
        *)
            echo "USAGE:${0} register|delete|beat"
        ;;
    esac
    
    
    • 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
    • 69

    docker打包时将脚本打包进容器,并传入必要的环境变量,并授予全部权限

    FROM /basefront:v1.3.0
    RUN echo "Asia/shanghai" > /etc/timezone;
    WORKDIR /root
    ADD dist/ /usr/share/nginx/html
    ARG gitbranch
    ENV BRANCH=${gitbranch}
    COPY dev/register.sh /root/register.sh
    RUN chmod 777 /root/register.sh
    ENTRYPOINT ["nginx"]
    CMD ["-g", "daemon off;"]
    EXPOSE 80
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    k8s环境下我们可以利用生命周期回调来执行脚本,在项目启动成功后执行注册,项目停止前删除实例,由于前端项目不容易挂,所以直接注册一个永久节点,不用临时节点所以,不用心跳

    preStop:
        exec:
          command:
          - "/bin/bash"
          - "-cx"
          - "/root/register.sh delete"
      postStart:
        exec:
          command:
          - "/bin/bash"
          - "-cx"
          - "/root/register.sh register"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这样就完成了前端项目服务化。重点来了此时如果你的前端项目用的时history模式会有个很坑的问题。就是你的nginx配置是这样的,当然如果你是hash模式就不会存在这个问题,因为nginx最终会忽略掉#后面的内容。

    location / {
          root /usr/share/nginx/html;
          if ($request_filename ~* .*\.(?:htm|html)$) {
            add_header Cache-Control no-store;
            add_header Pragma no-cache;
          }
          index index.html;
          try_files $uri $uri/ /index.html;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    try_files指令解析:

    • 当你访问的uri文件能在本地服务器找的到,那么就直接放回.
    • 如果没找到,那么在uri后面加个 / 变成目录,如果目录存在返回一个重定向301 告诉浏览器到这个目录下找index.html.
    • 如果前面都没找到,最后直接返回到根目录的index.html.

    history模式下,将url上的# 去掉了
    http://域名/#/user/login变成了http://域名/user/login

    所以此时走到了第二个参数,发生了301重定向。

    由于此时前端项目是通过gateway进行访问的,而gateway是通过注册中心获取到的容器ip进行访问的,所以此时重定向的地址变成了 http://ip:port/user/login/ 然后在浏览器上直接就跳到了这个地址。即使你用的不是gateway,在双层nginx下也会出现这个问题。所以此时,你需要在改下nginx的配置改成如下方式,为什么在第二个路径后面加index.html。因为history会在每个目录下都放一个index.html。此时找到的是文件就不会发生重定向,而是直接访问了文件。所以就没问题了。还有一种方案就是如果你就是单页应用,索性直接返回 /index.html。把第二个参数去掉也是可以的。

    location / {
          root /usr/share/nginx/html;
          if ($request_filename ~* .*\.(?:htm|html)$) {
            add_header Cache-Control no-store;
            add_header Pragma no-cache;
          }
          index index.html;
          try_files $uri $uri/index.html /index.html;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    fetch-axios简述和简单用法
    Java开源工具库使用之高性能内存数据查找库CQengine
    DHP16P-10-05A/100T-BC、DHP16P-10-23A/35ET-BB电液比例式2级放大式方向控制阀放大器
    vivo 基于 JaCoCo 的测试覆盖率设计与实践
    二叉树进阶oj题
    码蹄集 - MT2320 - 跑图:简单图问题
    Ubuntu下运行adb devices找不到设备的问题
    Spring中JDK与Cglib动态代理的区别
    基于GIS探究环境和生态因子对水体、土壤、大气污染物的影响
    Java【多线程】Callable 是什么, 如何使用并理解 Cllable, 和 Runnable 有什么区别?
  • 原文地址:https://blog.csdn.net/a807719447/article/details/126760519