Service-computing-hw8 《Golang web 应用开发》阅读

这周的作业是阅读《Golang web 应用开发》,Golang web应用开发有很多相关内容,表单、访问数据库、web服务、安全加密、设计web框架等等,本文就其中的一个重点,web基础,用go搭建一个简单的web服务来谈谈自己学习到的知识和理解

1.1 http协议,web的运行原理

​ 想必学习过计算机网络的同学都会清楚web也就是浏览器的工作方式,浏览网页的时候,会打开浏览器,输入网址后按下回车键,然后就会显示出你想要浏览的内容

​ 这其中蕴含的过程简单回忆一下:输入URL的时候,首先浏览器会去请求DNS服务器,通过DNS获取相应的域名对应的IP,然后通过IP地址找到IP对应的服务器后,要求建立TCP连接,等浏览器发送完HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包,服务器调用自身服务,返回HTTP Response(响应)包;客户端收到来自服务器的响应后开始渲染这个Response包里的主体(body),等收到全部的内容随后断开与该服务器之间的TCP连接

​ 其中URL解析和DNS解析,URL按照规定的格式进行解析,集中式域名解析和分布式域名解析,一种是一个一个访问,一种是深度迭代访问DNS服务器,这些都不是重点

​ 当今网络的请求和响应数据传输,都是遵循最常用的http协议,http协议也是web工作的核心,HTTP是一种让Web服务器与浏览器(客户端)通过Internet发送与接收数据的协议,它建立在TCP协议之上,一般采用TCP的80端口。它是一个请求、响应协议–客户端发出一个请求,服务器响应这个请求。在HTTP中,客户端总是通过建立一个连接与发送一个HTTP请求来发起一个事务。服务器不能主动去与客户端联系,也不能给客户端发出一个回调连接。客户端与服务器端都可以提前中断一个连接。例如,当浏览器下载一个文件时,你可以通过点击“停止”键来中断文件的下载,关闭与服务器的HTTP连接。HTTP协议是无状态的。

1.2 如何用go搭建一个web服务器

​ 我们从最基础最简单的那种开始学起,Go语言里面提供了一个完善的net/http包,学会使用这个包就可以搭建起一个基础可运行的web服务器,同时可以对Web的路由,静态文件,模版,cookie等数据进行设置和操作。

package main

import (
	"fmt"
	"net/http"
	"strings"
	"log"
)

func sayhelloName(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()  //解析参数,默认是不会解析的
	fmt.Println(r.Form)  //这些信息是输出到服务器端的打印信息
	fmt.Println("path", r.URL.Path)
	fmt.Println("scheme", r.URL.Scheme)
	fmt.Println(r.Form["url_long"])
	for k, v := range r.Form {
		fmt.Println("key:", k)
		fmt.Println("val:", strings.Join(v, ""))
	}
	fmt.Fprintf(w, "Hello astaxie!") //这个写入到w的是输出到客户端的
}

func main() {
	http.HandleFunc("/", sayhelloName) //设置访问的路由
	err := http.ListenAndServe(":9090", nil) //设置监听的端口
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

build代码后,执行web.exe(已经在9090端口监听http链接请求),在浏览器输入http://localhost:9090查看,Hello astaxie!浏览器的页面输出,通过http的两个函数就可以写一个简单的web服务器了

1.3 接下来介绍底层原理,go如何让web服务器正常工作起来

​ 先来看服务器的几个概念,Request:是用户请求的信息 Response:服务器反馈给客户端的信息 Conn:用户的每次请求链接 Handler:处理请求和生成返回信息的方法

​ 先来看http包运行机制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uEWoApef-1572945943177)(第八周博客.assets/1572945229342.png)]

  1. 创建Listen Socket, 监听指定的端口, 等待客户端请求到来。
  2. Listen Socket接受客户端的请求, 得到Client Socket, 接下来通过Client Socket与客户端通信。
  3. 处理客户端的请求, 首先从Client Socket读取HTTP请求的协议头, 如果是POST方法, 还可能要读取客户端提交的数据, 然后交给相应的handler处理请求, handler处理完毕准备好客户端需要的数据, 通过Client Socket写给客户端。

​ Go是通过一个函数ListenAndServe来处理监听端口、接收客户端请求和分配handler这三件事情的,这个底层其实这样处理的:初始化一个server对象,然后调用了net.Listen("tcp", addr),也就是底层用TCP协议搭建了一个服务,然后监控我们设置的端口。内部源码摘录如下


func (srv *Server) Serve(l net.Listener) error {
	defer l.Close()
	var tempDelay time.Duration // how long to sleep on accept failure
	for {
		rw, e := l.Accept()
		if e != nil {
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return e
		}
		tempDelay = 0
		c, err := srv.newConn(rw)
		if err != nil {
			continue
		}
		go c.serve()
	}
}

我们仔细分析分析上面的代码

  • 监控之后如何接收客户端的请求呢?

    上面代码执行监控端口之调用srv.Serve(net.Listener),这个函数就是用来处理用户的请求信息的,函数里有个for{},首先通过Listener接受请求,然后创建一个Conn,最后单独开一个goroutine,把请求的参数扔给Conn服务,go c.serve(),go的高并发也是体现在这里,go的每一次请求都是一个新的goroutine服务

  • 如何分配到具体的函数来处理请求呢?

    conn首先会解析request:c.readRequest(),然后获取相应的handler:handler := c.server.Handler,也就是调用函数ListenAndServe时候的第二个参数,

    我们前面例子传递的是nil时,默认获取handler = DefaultServeMux,这个变量的作用是一个路由器,它用来匹配url跳转到其相应的handle函数,我们调用的代码里面第一句调用了http.HandleFunc("/", sayhelloName)这里就是有过这种设置。这个作用就是注册了请求/的路由规则,当请求uri为"/",路由就会转到函数sayhelloName,DefaultServeMux会调用ServeHTTP方法,这个方法内部其实就是调用sayhelloName本身,最后通过写入response的信息反馈到客户端。

整个函数的运行流程,具体每一块的作用如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uHM2j5ib-1572945943179)(第八周博客.assets/1572945421299.png)]
问题解答后,我们这样就大概知道go如何让web跑起来,至少是如何处理接受和处理请求信息的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值