编译tengine/nginx集群tomcat

本文介绍如何通过离线方式安装部署Tengine、Zlib、PCRE、OpenSSL及Apache Tomcat等组件,并详细说明了每一步的安装过程。此外,还提供了Tengine的配置示例以及常见问题解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编译tengine/nginx集群tomcat

一、本次安装采用离线安装方法,需要准备的包
百度云下载地址
1. tengine-2.1.1.tar.gz
2. zlib-1.2.8.tar.gz
3. pcre-8.37.tar.gz
4. openssl-0.9.8zg.tar.gz
5. apache-tomcat-7.0.64.tar.gz
把zlib、pcre、 openssl 上传到 /usr/local/src/下
二、安装zlib

cd /usr/local/src/
tar xzvf zlib-1.2.8.tar.gz 
cd zlib-1.2.8/
./configure 
makle
make install

三、安装pcre

tar xzvf pcre-8.37.tar.gz
cd pcre-8.37/
./configure 
make
make install

四、安装openssl

tar xzvf openssl-0.9.8zg.tar.gz
cd openssl-0.9.8zg/
./configure 
make
make install

五、编译tengine-2.1.1.tar.gz 安装
把 tengine-2.1.1.tar.gz 上传到/usr/tengine-2.1.1.tar.gz

cd /usr 
tar xzvf tengine-2.1.1.tar.gz
cd tenine-2.1.1
./configure --prefix=/usr/local/tengine --with-http_concat_module --without-http_trim_filter_module --with-pcre=/usr/local/src/pcre-8.37 --with-zlib=/usr/local/src/zlib-1.2.8 --with-openssl=/usr/local/src/openssl-0.9.8zg
make 
make install

六、安装apache-tomcat-7.0.64.tar.gz

tar xzvf apache-tomcat-7.0.64.tar.gz
cd apache-tomcat-7.0.64/bin
./startup.sh 

七、配置tengine

cd tengine/conf/
vi nginx.conf


user root root ;
worker_processes 4;
error_log  logs/error.log  crit;
pid        logs/nginx.pid;
#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 65535;
events
{
  use epoll;
  worker_connections 65535;
}
http
{
  include       mime.types;
  default_type  application/octet-stream;
  #charset  gb2312;
    log_format  access  '$remote_addr - $remote_user [$time_local] "$request" '
              '$status $body_bytes_sent "$http_referer" '
              '"$http_user_agent" $http_x_forwarded_for';
  server_names_hash_bucket_size 128;
  client_header_buffer_size 32k;
  large_client_header_buffers 4 32k;
  client_max_body_size 8m;
  sendfile on;
  tcp_nopush     on;
  keepalive_timeout 60;
  tcp_nodelay on;
  fastcgi_connect_timeout 300;
  fastcgi_send_timeout 300;
  fastcgi_read_timeout 300;
  fastcgi_buffer_size 64k;
  fastcgi_buffers 4 64k;
  fastcgi_busy_buffers_size 128k;
  fastcgi_temp_file_write_size 128k;
  gzip on;
  gzip_min_length  1k;
  gzip_buffers     4 16k;
  gzip_http_version 1.0;
  gzip_comp_level 2;
  gzip_types       text/plain application/x-javascript text/css application/xml;
  gzip_vary on;
  #limit_zone  crawler  $binary_remote_addr  10m;

  upstream t1.zgl.com.cn {
    ip_hash;
      server 192.168.180.130:8080 max_fails=3 fail_timeout=10s;
      server 192.168.180.131:8080 max_fails=3 fail_timeout=10s;
      #server 10.58.56.64:8083 max_fails=3 fail_timeout=10s;
      check interval=3000 rise=2 fall=5 timeout=180000 type=tcp;
  }


  server
  {
    listen       80;
    server_name  192.168.180.130;
    access_log   ./logs/csc.cart.access.log access;

    ssi  on;
    ssi_silent_errors on;

    location / {
      proxy_set_header        Host $host;
      proxy_set_header        X-Real-IP $remote_addr;
      proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
      add_header              X-Cache   "$upstream_cache_status  from  proxy 43";
      add_header              Nginx-Cache "$upstream_cache_status";

      proxy_redirect  off;
      proxy_pass http://t1.zgl.com.cn;
     }

  }
}

八、启动tengine

测试 /usr/local/tengine/sbin/nginx -c /usr/local/tengine/conf/nginx.conf -t
启动 /usr/local/tengine/sbin/nginx -c /usr/local/tengine/conf/nginx.conf
关闭 kill -9 `ps -ef |grep nginx|grep -v grep|awk '{print $2}'`
重启/usr/local/tengine/sbin/nginx -c /usr/local/tengine/conf/nginx.conf -s reload

九、访问192.168.180.130
这里写图片描述

十、经过压测 频繁出现 502 504错误

nginx proxy: connect() to ip:80 failed (99: Cannot assign requested address)

modify /etc/sysctl.conf:

net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_tw_buckets = 10000
net.ipv4.ip_nonlocal_bind = 1

sysctl -p

<think>我们需要编写一个脚本,用于在Nginx配置中查找指定站点对应的后端主机(非注释行)。 主要步骤: 1. 确定Nginx主配置文件路径:/usr/local/tengine/conf/nginx.conf 2. 在nginx.conf中,通常会通过include指令引入其他配置文件,特别是站点配置(server块)和upstream配置。 根据描述,站点配置文件在/usr/local/tengine/conf/vhosts/servername,upstream配置文件在/usr/local/tengine/conf/vhosts/upstream。 3. 我们要实现的功能:给定一个站点域名(server_name),找到该站点配置(在servername目录下的某个文件中),然后从该站点配置中提取upstream名称,再根据upstream名称在upstream目录下的配置文件中找到对应的后端主机列表(非注释行)。 具体步骤: a. 遍历servername目录下的所有文件,查找包含目标server_name的server块。 b. 在找到的server块中,定位到proxy_pass指令,提取upstream名称(例如:proxy_pass http://my_upstream; 则提取my_upstream)。 c. 在upstream目录下的配置文件中查找与这个upstream名称匹配的upstream块。 d. 从该upstream块中提取所有非注释的server行,得到后端主机列表。 注意:需要忽略注释行(以#开头的行)和空行。 由于Nginx配置的语法比较复杂,我们使用逐行解析的方式,同时注意处理多行配置(但通常upstream和server配置都是单行)。 我们将编写一个函数来提取upstream块中的server行。 脚本执行方式:假设传入参数为要查询的站点域名(server_name)。 例如:./find_backend.sh example.com 输出:该站点对应的后端主机列表,每行一个。 如果遇到多个匹配,我们只取第一个(或者确保每个server_name唯一?实际情况可能有多个,但一般我们按配置顺序取第一个有效的)。 步骤分解: 1. 在servername目录下的所有文件中搜索包含目标server_name的server块。 如何确定server块?我们通过查找"server {"开始,然后在这个块内查找"server_name"指令,并且包含目标域名。 但是,由于配置可能是分散的,我们简化处理:直接查找包含"server_name"并且包含目标域名的行,然后确认该行在server块内(通过向上查找最近的未闭合的块)。 然而,为了简化,我们可以假设每个server块在一个文件中是连续的,并且server_name指令在server块内是单行。 因此,我们可以这样: - 遍历servername目录下的每个文件,逐行读取。 - 当遇到"server {"时,标记进入server块,并记录当前块的行范围(直到匹配的"}")。 - 在server块内,查找包含"server_name"的行,并且该行包含目标域名。 - 如果找到,则在这个server块内查找"proxy_pass"指令,提取upstream名称。 但是,这种方法需要解析块结构,比较复杂。 另一种简化方法:我们假设每个server块是独立的,并且在一个文件中可能有多个server块。我们逐行读取,当遇到以"server"开头且包含"{"的行时,认为是一个server块开始,然后记录直到匹配的"}"。在记录的过程中,检查是否有server_name匹配目标域名,如果有,则在这个块内查找proxy_pass。 考虑到时间,我们采用第二种方法,但注意:匹配大括号需要栈来维护,因为可能有嵌套(如location块)。 因此,我们设计一个函数来提取一个文件中的所有server块。 但是,我们也可以利用nginx -T命令来输出所有配置,然后使用正则表达式匹配。但这里要求不依赖nginx命令,直接解析文件。 考虑到复杂度,我们假设配置格式规范,并且server块不会嵌套其他块(除了location等,但我们只关心proxy_pass,它通常在server块或location块中)。我们只关心proxy_pass,所以我们可以这样: - 在找到server块后,我们在这个块内逐行查找proxy_pass,同时忽略注释行。 具体步骤: 1. 在servername目录下的所有文件中,查找包含目标server_name的server块。 - 打开一个文件,逐行读取,记录当前是否在server块中(通过大括号匹配)。 - 当遇到一行以"server"开头,并且包含"{"时,我们进入一个server块,记录当前块的内容(直到匹配的"}")。 - 在记录块内容的同时,检查该块内是否有server_name包含目标域名。 - 如果有,则在这个块内查找proxy_pass指令。 2. 提取proxy_pass的值,通常格式为:proxy_pass http://upstream_name; 我们需要提取upstream_name。 3. 在upstream目录下的所有配置文件中查找upstream块,该块的名称就是上一步提取的upstream_name。 - 同样,我们打开每个文件,查找以"upstream upstream_name {"开头的块,然后在这个块内提取所有非注释的server行。 4. 从这些server行中提取后端主机地址。 注意:proxy_pass的格式可能有多种,比如: proxy_pass http://upstream_name; proxy_pass http://upstream_name/; proxy_pass http://upstream_name$request_uri; 我们只关心http://后面的部分,直到遇到分号、斜杠或变量等。所以我们提取http://之后,第一个非字母数字下划线(可能还有横线)之前的字符串作为upstream名称。 但是,更安全的做法是:提取http://之后,直到空格、分号、斜杠、{等符号之前的字符串。 我们使用正则表达式:http://([a-zA-Z0-9_-]+) 但注意,可能upstream名称包含点,例如:my.upstream.com,所以允许点:http://([a-zA-Z0-9_.-]+) 5. 在upstream块中,server行的格式通常是:server 192.168.1.1:80; 或者 server backend1.example.com; 也可能有权重等参数,但我们只需要IP或域名。 我们提取非注释的server行,然后提取第一个字段后的第一个词(即server后面的第一个词)。 但是,注意可能有多种写法,比如: server 192.168.1.1:80 weight=5; server 192.168.1.2; server unix:/tmp/backend3; 我们只需要地址部分,所以我们可以这样:提取以"server"开头,然后后面跟着一个非空字符串,直到分号,然后取第一个参数(即地址部分)。 例如:`server 192.168.1.1:80;` -> 地址为192.168.1.1:80 但是,如果后面有参数,我们只取第一个参数(即地址)。 所以,我们可以用正则表达式:server\s+([^; \t]+) 但是,注意可能有多个空格,所以我们这样:`server\s+([^\s;]+)` 然后,我们取这个匹配的第一个分组。 6. 最后输出所有找到的后端地址。 由于一个站点可能有多个proxy_pass(比如多个location),我们这里简化处理:只取第一个非注释的proxy_pass(在server块内,按顺序第一个遇到的)。 同样,一个upstream块内可能有多个server行,我们都要提取。 脚本结构: 定义函数:find_server_block_with_servername(servername_dir, target_domain) 遍历servername_dir下的每个文件 读取文件内容,解析出所有server块(包括块内容) 对每个server块: 检查server_name指令是否包含target_domain(注意:server_name可能有多个域名,用空格隔开) 如果包含,则在这个server块中查找proxy_pass指令,提取upstream名称,并返回(找到第一个匹配的即可) 定义函数:find_upstream_servers(upstream_dir, upstream_name) 遍历upstream_dir下的每个文件 读取文件内容,查找以"upstream upstream_name {"开头的块(注意可能有空格和换行) 在这个upstream块中,提取所有非注释的server行,并提取出地址 主程序: target_domain = 第一个命令行参数 servername_dir = "/usr/local/tengine/conf/vhosts/servername" upstream_dir = "/usr/local/tengine/conf/vhosts/upstream" upstream_name = find_upstream_name_by_servername(servername_dir, target_domain) 如果找到,则调用find_upstream_servers(upstream_dir, upstream_name)得到后端列表,并输出 否则,输出未找到 注意:我们假设配置文件中没有使用变量来定义upstream名称,且都是静态配置。 由于配置解析可能比较复杂,我们简化处理:不处理大括号嵌套(因为upstream块内部一般不会嵌套其他块,server块内部可能有location,但我们只关心proxy_pass在server块或location块中的情况,但这里我们只搜索整个server块内的所有行,包括location块内的proxy_pass?这可能会导致找到多个proxy_pass,但我们只取第一个)。 因此,在server块内,我们逐行查找proxy_pass,只要找到第一个非注释的proxy_pass,就提取upstream名称。 为了避免location块内的proxy_pass干扰,我们可以只搜索server块的第一层(不进入location块),但这样可能找不到proxy_pass。所以,我们简单处理:在整个server块内查找第一个proxy_pass。 具体实现: 步骤1:解析server块 - 使用一个栈来记录大括号,当遇到"server {"时,将栈置为1,然后继续读取直到栈为空。 - 在读取过程中,记录块内的所有行。 步骤2:在块内逐行检查server_name行,判断是否包含目标域名。 例如:server_name example.com www.example.com; 我们检查该行中是否有目标域名(注意:目标域名可能出现在多个地方,所以用空格分割后逐个比较,同时注意行末分号)。 步骤3:在同一个块内逐行查找proxy_pass,使用正则表达式提取upstream名称。 步骤4:在upstream块中,我们同样使用栈来提取整个块内容,然后逐行查找server行。 考虑到时间,我们编写一个简化版本,假设配置格式规范,且没有嵌套的块(在upstream块中不会有嵌套,server块中我们只关注proxy_pass,不管嵌套)。 但是,server块内可能有location块,而proxy_pass可能在location块内。所以我们在整个server块内容中搜索(包括子块)是合理的。 下面开始编写代码: 注意:我们使用bash脚本还是Python?根据需求,这里使用Python更合适,因为要解析块结构。 我们使用Python编写。 代码结构: 1. 导入必要的模块:os, re, sys 2. 定义函数:parse_blocks(file_path, block_type, block_name=None) 这个函数用于解析指定类型的块(如server块,不需要名字;或者upstream块,需要名字) 返回块内容(字符串列表的列表,每个块是一个字符串列表) 但是,由于server块没有名称,我们只能通过关键字"server"来识别。而upstream块有名称。 因此,我们分别写两个函数: find_server_blocks(file_path): 返回文件中的所有server块(每个块是一个字符串列表,包括块的所有行) find_upstream_blocks(file_path, upstream_name): 返回指定名称的upstream块(如果存在,返回块内容) 然后,我们写一个函数:extract_upstream_name(block_lines): 从server块内容中提取proxy_pass并解析出upstream名称 写一个函数:extract_servers_from_upstream(block_lines): 从upstream块中提取所有server行中的地址 主函数: target_domain = sys.argv[1] servername_dir = "/usr/local/tengine/conf/vhosts/servername" upstream_dir = "/usr/local/tengine/conf/vhosts/upstream" 遍历servername_dir下的所有文件: 对于每个文件,调用find_server_blocks,得到所有server块 对于每个server块: 检查该块中是否有server_name包含target_domain(写一个函数:check_servername_in_block(block_lines, target_domain)) 如果有,则调用extract_upstream_name(block_lines)得到upstream_name 如果得到upstream_name,则跳出循环(不再查找其他块) 如果没找到,继续下一个文件 如果找到了upstream_name,则遍历upstream_dir下的所有文件: 对于每个文件,调用find_upstream_blocks(file_path, upstream_name)得到upstream块 如果找到,则调用extract_servers_from_upstream(block_lines)得到服务器列表,然后输出 注意:一个文件中可能有多个server块,我们按顺序检查,一旦找到匹配的server_name,就使用它。 下面我们编写具体函数。 由于时间关系,我们只写关键函数,并注意错误处理。 开始编写代码:</think>以下是一个用于查找 Nginx 站点对应后端主机的 Python 脚本,该脚本会解析 Nginx 配置文件并提取非注释的后端主机信息: ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import re import sys import argparse from collections import defaultdict # 配置路径 NGINX_CONF_DIR = "/usr/local/tengine/conf" SERVER_DIR = os.path.join(NGINX_CONF_DIR, "vhosts/servername") UPSTREAM_DIR = os.path.join(NGINX_CONF_DIR, "vhosts/upstream") def parse_config_file(file_path): """ 解析配置文件,提取非注释内容 :param file_path: 配置文件路径 :return: 解析后的配置内容列表 """ config_lines = [] try: with open(file_path, 'r', encoding='utf-8') as f: in_block_comment = False for line in f: # 处理块注释 if '/*' in line: in_block_comment = True # 跳过注释行和空行 stripped = line.strip() if not stripped or stripped.startswith('#') or in_block_comment: if '*/' in line: in_block_comment = False continue # 移除行尾注释 clean_line = re.sub(r'#.*$', '', line).strip() if clean_line: config_lines.append(clean_line) except Exception as e: print(f"Error reading {file_path}: {str(e)}") return config_lines def find_upstreams(upstream_dir): """ 查找所有 upstream 配置 :param upstream_dir: upstream 配置目录 :return: upstream 名称到后端主机的映射字典 """ upstreams = defaultdict(list) for filename in os.listdir(upstream_dir): if not filename.endswith('.conf'): continue file_path = os.path.join(upstream_dir, filename) lines = parse_config_file(file_path) current_upstream = None for line in lines: # 匹配 upstream 定义 upstream_match = re.match(r'upstream\s+(\S+)\s*{', line) if upstream_match: current_upstream = upstream_match.group(1) continue # 匹配 server 定义 if current_upstream and line.startswith('server'): server_match = re.search(r'server\s+(\S+);', line) if server_match: upstreams[current_upstream].append(server_match.group(1)) return upstreams def find_server_backends(server_dir, upstreams): """ 查找所有 server 配置及其对应的后端主机 :param server_dir: server 配置目录 :param upstreams: upstream 名称到后端主机的映射 :return: 站点到后端主机的映射字典 """ site_backends = {} for filename in os.listdir(server_dir): if not filename.endswith('.conf'): continue file_path = os.path.join(server_dir, filename) lines = parse_config_file(file_path) server_name = None upstream_name = None for line in lines: # 提取 server_name server_match = re.match(r'server_name\s+(.*?);', line) if server_match: server_name = server_match.group(1).split()[0] # 取第一个域名 continue # 提取 proxy_pass 中的 upstream proxy_match = re.search(r'proxy_pass\s+http://(\w+);', line) if proxy_match: upstream_name = proxy_match.group(1) continue # 如果找到匹配的 server 和 upstream if server_name and upstream_name: if upstream_name in upstreams: site_backends[server_name] = { 'config_file': filename, 'upstream': upstream_name, 'backends': upstreams[upstream_name] } else: site_backends[server_name] = { 'config_file': filename, 'error': f"Upstream '{upstream_name}' not found" } return site_backends def format_output(site_backends): """ 格式化输出结果 :param site_backends: 站点到后端主机的映射字典 """ print("\nNginx Site Backend Mapping Report") print("=" * 50) for site, info in site_backends.items(): print(f"\nSite: {site}") print(f"Config File: {info['config_file']}") if 'error' in info: print(f" Error: {info['error']}") else: print(f" Upstream: {info['upstream']}") print(" Backend Servers:") for i, backend in enumerate(info['backends'], 1): print(f" {i}. {backend}") print("\n" + "=" * 50) print(f"Total sites found: {len(site_backends)}") def main(): parser = argparse.ArgumentParser(description='Find Nginx site backend servers') parser.add_argument('--site', help='Specific site to search for') args = parser.parse_args() # 检查目录是否存在 for path in [NGINX_CONF_DIR, SERVER_DIR, UPSTREAM_DIR]: if not os.path.exists(path): print(f"Error: Directory not found: {path}") sys.exit(1) # 查找所有 upstream upstreams = find_upstreams(UPSTREAM_DIR) print(f"Found {len(upstreams)} upstream configurations") # 查找所有 server 配置 site_backends = find_server_backends(SERVER_DIR, upstreams) # 处理特定站点查询 if args.site: if args.site in site_backends: print(f"\nBackend for site '{args.site}':") info = site_backends[args.site] if 'backends' in info: for backend in info['backends']: print(f" - {backend}") else: print(f" Error: {info.get('error', 'Unknown error')}") else: print(f"\nSite '{args.site}' not found in configurations") else: format_output(site_backends) if __name__ == "__main__": main() ``` ### 脚本功能说明 1. **配置解析**: - 解析 Nginx 配置文件,跳过注释行和空行 - 支持处理行内注释(`#`)和块注释(`/* ... */`) - 提取有效的配置指令 2. **upstream 查找**: - 扫描 `/usr/local/tengine/conf/vhosts/upstream` 目录 - 提取所有 upstream 定义及其后端服务器列表 - 返回格式:`{upstream_name: [server1, server2, ...]}` 3. **server 配置查找**: - 扫描 `/usr/local/tengine/conf/vhosts/servername` 目录 - 提取 server_name 和对应的 proxy_pass 指令 - 将站点映射到 upstream 后端服务器 4. **命令行参数**: - `--site`:可选参数,指定要查询的特定站点 - 无参数时:输出所有站点及其后端映射关系 5. **输出格式**: - 清晰展示站点、配置文件、upstream 名称和后端服务器列表 - 错误处理:当 upstream 未找到时显示错误信息 ### 使用示例 1. **查找所有站点配置**: ```bash python3 nginx_backend_finder.py ``` 2. **查找特定站点**: ```bash python3 nginx_backend_finder.py --site example.com ``` ### 输出示例 ``` Found 3 upstream configurations Nginx Site Backend Mapping Report ================================================== Site: example.com Config File: example.conf Upstream: backend_example Backend Servers: 1. 192.168.1.10:8080 2. 192.168.1.11:8080 Site: api.example.com Config File: api.conf Upstream: backend_api Backend Servers: 1. 10.0.0.5:9000 2. 10.0.0.6:9000 Site: test.example.com Config File: test.conf Error: Upstream 'missing_backend' not found ================================================== Total sites found: 3 ``` ### 脚本特点 1. **健壮性**: - 处理各种注释格式 - 错误捕获和友好提示 - 目录存在性检查 2. **灵活性**: - 支持查询特定站点或全部站点 - 清晰的输出格式 - 可扩展的正则表达式匹配 3. **效率**: - 使用 defaultdict 自动初始化数据结构 - 一次性解析所有配置文件 - 避免不必要的重复操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值