设为首页 收藏本站
查看: 996|回复: 0

[经验分享] How Tomcat Works 学习-我们到底能走多远系列(8)

[复制链接]

尚未签到

发表于 2015-8-6 11:39:59 | 显示全部楼层 |阅读模式
我们到底能走多远系列(8)
  扯淡:
  我们到底能走多远?是想提醒自己不要停止学习和博客的更新,这个系列会一直和web开发有关,我的目标是写完100个。慢慢来,阶段性目标15个吧。哈哈
  学得好不如做的好,做得好不如扯得好啊!
  主题:
  在上一轮学习中:Servlet-我们到底能走多远系列(7) 发现要想理解web中的servlet,还是需要深入学习servlet 容器:tomcat(因为它是开源的嘛!)
  为了不迷失在tomcat茫茫的源码中,我先学习下最外围的一些知识,然后先把《How Tomcat Works 》第一章看了。有人评论说这本书就是代码太多,我到很喜欢这个写作风格,程序员嘛,代码就是我们的文章!
  HTTP(Hypertext Transfer Protocol):
      想要自己看http消息可以利用抓包工具比如wireshark来抓取http消息。(wireshark是一个很不错的抓包工具,界面也蛮漂亮的,功能强大。)
    官方下载:http://www.wireshark.org/download.html
  访问网站时抓到的包:包括了request 和 response(没有包括body部分)
DSC0000.jpg
  详细的http协议的学习可以查看:http://www.iyunv.com/tankxiao/archive/2012/02/13/2342672.html
  其中关于method的get还是post可以查看:http://www.iyunv.com/killbug/archive/2012/08/05/2624286.html
  一个简单的webServer:
  知道了http消息的格式,就可以来学习下《How Tomcat Works 》第一章提供的代码了
  分成3部分:
  HttpServer :负责监听服务器的端口,将监听到的消息交给Request处理,然后实例特定的Response返回除去。
  Request :负责把http消息中的Uri取出来。
  Response :根据Request取得的Uri,到到响应的文件中读取内容,把内容返回出去。
  上面的整个流程基本完成了响应 - 返回的效果。
  HttpServer:



package code.tomcat.simpleWebServer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer {
// 项目放置的文件夹
public static final String WEB_ROOT = System.getProperty("user.id") + File.separator + "webroot";
// SHUTDOWN命令
private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
// 判断是否Shutdown标示符,控制程序运行
private boolean isShutdown = false;
// 主程序
public static void main(String[] args) {
HttpServer httpSever = new HttpServer();
// 不能叫wait,你懂的
        httpSever.await();
}
private void await(){
ServerSocket serverSocket = null;
int port = 8080;
try {
// 用ServerSocket等待端口消息
serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
} catch (IOException e) {
e.printStackTrace();
System.exit(1);//异常后,把java虚拟机都关掉
        }
while( ! isShutdown ){
Socket socket = null;
InputStream input = null;
OutputStream output = null;
try {
// 建立socket
socket = serverSocket.accept();
// socket的输入
input = socket.getInputStream();
// socket的输出
output = socket.getOutputStream();
Request request = new Request(input);
request.parse();//Request来解析出uri
Response response = new Response(output);
response.setRequest(request);//把Request放进去,是要用解析出来的uri
response.sendStaticResource();//把产生的返回内容发送出去
// 关闭socket
                socket.close();
isShutdown = request.getUri().equals(SHUTDOWN_COMMAND);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
}
  Request :



package code.tomcat.simpleWebServer;
import java.io.IOException;
import java.io.InputStream;
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input) {
this.input = input;
}
public void parse() {
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
// 把InputStream读出来,放进byte[2048]大小的buffer中
i = input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
i = -1;
}
// 传化成StringBuffer
for (int j = 0; j < i; j++) {
request.append((char) buffer[j]);
}
// 然后再以String的形式传经解析方法中去
uri = parseUri(request.toString());
}
// 真正解析uri出来的方法,相当于是解析request的第一行:GET /killbug/ HTTP/1.1 想要取出“/killbug/”这段,即两个空格之间那一段
private String parseUri(String requestString) {
int index1, index2;
// 第一个空格位置
index1 = requestString.indexOf(' ');
if (index1 != -1) {
// 第二个空格位置
index2 = requestString.indexOf(' ', index1 + 1);
if (index2 > index1)
// 根据两个空格的位置截断出需要的一段
return requestString.substring(index1 + 1, index2);
}
return null;
}
public String getUri() {
return uri;
}
}
  Response :



package code.tomcat.simpleWebServer;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Response {
private static final int BUFFER_SIZE = 1024;
Request request;
OutputStream output;
public Response(OutputStream output) {
this.output = output;
}
public void setRequest(Request request) {
this.request = request;
}
public void sendStaticResource() throws IOException {
byte[] bytes = new byte[BUFFER_SIZE];
//文件输入流
FileInputStream fis = null;
// request.getUri()相当于:“/killbug/”,把路径和文件起来定位到具体的文件,可以是项目中的一个html文件
File file = new File(HttpServer.WEB_ROOT, request.getUri());
if (file.exists()) {
fis = new FileInputStream(file);
int ch = fis.read(bytes, 0, BUFFER_SIZE);
while (ch != -1) {
// 写进socket的output中去,就成了返回值了
output.write(bytes, 0, ch);
ch = fis.read(bytes, 0, BUFFER_SIZE);
}
}else { // 找不到文件的情况相当于404啦
String errorMessage = "HTTP/1.1 404 File Not Found\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 23\r\n"
+ "\r\n"
+ "File Not Found";
output.write(errorMessage.getBytes());
}
}
}


Tomcat外围的一些知识:
  1,tomcat的目录结构:
  window的(linux下目录结构大同小异):
DSC0001.jpg
  
  各文件夹各自的分管作用:
  bin: 存放各种平台下启动和关闭Tomcat的脚本文件.其中有个档是catalina.bat,打开这个windos配置文件,在非注释行加入JDK路径,例如 : SET  JAVA_HOME=C:\j2sdk1.4.2_06 保存后,就配置好tomcat环境了. startup.bat是windows下启动tomcat的文件,shutdown.bat是关闭tomcat的文件.
  work : Tomcat把各种由jsp生成的servlet文件放在这个目录下.
  logs : 存放Tomcat的日志文件
  conf : Tomcat的各种配置文件,最重要的是 server.xml
  lib: 在server/webapps目录中,存放Tomcat自带的两个APP-admin和manager应用,使用来管理Tomcat-web服务用的.在server/lib目录中,存放tomcat服务器所需要的各,web应用不能访问种jar
  temp:存放Tomcat运行时的临时文件;,
  2,tomcat连接数:
  在tomcat配置文件server.xml中的配置中,和连接数相关的参数有:
minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为10
maxProcessors:最大连接线程数,即:并发处理的最大请求数,默认值为75
acceptCount:允许的最大连接数,应大于等于maxProcessors,默认值为100
enableLookups:是否反查域名,取值为:true或false。为了提高处理能力,应设置为false
connectionTimeout:网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。
其中和最大连接数相关的参数为maxProcessors和acceptCount。如果要加大并发连接数,应同时加大这两个参数。
web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。Unix中如何设置这些参数,请参阅Unix常用监控和管理命令
tomcat4中的配置示例:
对于其他端口的侦听配置,以此类推。
  3,如何加大tomcat可以使用的内存
  tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,需要调大。
Unix下,在文件{tomcat_home}/bin/catalina.sh的前面,增加如下设置:
JAVA_OPTS='-Xms【初始化内存大小】 -Xmx【可以使用的最大内存】'
需要把这个两个参数值调大。例如:
JAVA_OPTS='-Xms256m -Xmx512m'
表示初始化内存为256MB,可以使用的最大内存为512MB
  4,关于虚拟主机
  tomcat服务器中在 $CATALINA_HOME/conf/service.xml中配置设置的name属性来配置不同主机名对应的站点:

     
     
     
     
     
      
   
   
service.xml中标签用于配置站点,一个建立一个WEB站点,可以使用多个配置多个站点,但同一个中的name不能相同,name属性对应该站点的主机名称,appBase="webappa"设置了一个路径,该路径将作为嵌套在中的属性docBase的基准路径,docBase可以是绝对路径也可以是相对于appBase的相对路径,如:docBase="Jquery\",当tomcat接受到一个请求,会取出主机名来跟的name值来对应,来访问对应的context中docBase配置的站点,若没有找到对应的host,则会访问在中defaultHost配置的默认站点,将defaultHost值设置为中某个的name值,则该host就会作为该Engine引擎的默认站点。
当配置多个时就不能使用IP来作为主机名来访问tomcat,因为Host的name值对应同一个IP,这时就不知道访问哪一个站点。
  在建立基于主机名的虚拟主机时,除了在service.xml中配置主机名与站点的映射外,还要配置主机名与IP地址的映射,这样在网络中才会找到该WEB服务器。配置主机名与IP地址的映射有两种方式:
  1.通过DNS(域名解析服务器)系统来配置
   2.通过在客户端本地Hosts文件中配置。
  Hosts文件可用于小型的企业内部网,而DNS用于大型网络服务(如:Internet上对外提供服务)。客户机会首先在本地Hosts文件中找主机名与IP的映射,若没有找到才会去DNS系统中去查找。
下面介绍在hosts文件中配置。
  在C:\Windows\System32\drivers\etc下找到Hosts文件,用EditPlus打开该文件会看到默认有127.0.0.1  localhost,这时为什么我们访问http://localhost:8080/,下面我们在新的一行写127.0.0.1 www.iyunv.com   ,就建立起来127.0.0.1与www.iyunv.com主机名的映射。
我们如上面图所示配置Service.xml,就完成了虚拟主机的配置。启动tomcat,访问http://www.iyunv.com:8080/killbug就可以访问killbug站点了。
  
  总结:tomcat 作为容器需要监听http消息,调用响应servlet,做出回应。这个基本的流程似乎只是tomcat的冰山一角,让我们继续前行。
  ----------------------------------------------------------------------
  努力不一定成功,但不努力肯定不会成功。
共勉

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-94778-1-1.html 上篇帖子: Tomcat容器结构及Pipeline机制 下篇帖子: 监控Tomcat解决方案(监控应用服务器系列文章)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表