API网关【gateway 】

最近在公司进行API网关重写,公司内采用serverMesh进行服务注册,调用,这里结合之前学习对API网关服务进行简单的总结与分析。 由于采用了大量的nginx相关的东西,所以在此记录一下:

在nginx使用openresty

加入nginx模块

编辑nginx下conf配置文件nginx.conf

1# vi nginx.conf 2在server模块加上 3location /helloworld { 4default_type text/html; 5content_by_lua 'ngx.say("hello world")'; 6}

 检查配置文件是否正确

# /usr/local/openresty/nginx/sbin/nginx -t -c /usr/local/openresty/nginx/conf/nginx.conf

重启nginx

# ./nginx -s reload

访问http://ip/helloworld ,输出helloworld

nginx的内部变量

1名称 说明 2$arg_name 请求中的name参数 3$args 请求中的参数 4$binary_remote_addr 远程地址的二进制表示 5$body_bytes_sent 已发送的消息体字节数 6$content_length HTTP请求信息里的"Content-Length" 7$content_type 请求信息里的"Content-Type" 8$document_root 针对当前请求的根路径设置值 9$document_uri 与$uri相同; 比如 /test2/test.php 10$host 请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名 11$hostname 机器名使用 gethostname系统调用的值 12$http_cookie cookie 信息 13$http_referer 引用地址 14$http_user_agent 客户端代理信息 15$http_via 最后一个访问服务器的Ip地址。 16$http_x_forwarded_for 相当于网络访问路径 17$is_args 如果请求行带有参数,返回“?”,否则返回空字符串 18$limit_rate 对连接速率的限制 19$nginx_version 当前运行的nginx版本号 20$pid worker进程的PID 21$query_string 与$args相同 22$realpath_root 按root指令或alias指令算出的当前请求的绝对路径。其中的符号链接都会解析成真是文件路径 23$remote_addr 客户端IP地址 24$remote_port 客户端端口号 25$remote_user 客户端用户名,认证用 26$request 用户请求 27$request_body 这个变量(0.7.58+)包含请求的主要信息。在使用proxy_pass或fastcgi_pass指令的location中比较有意义 28$request_body_file 客户端请求主体信息的临时文件名 29$request_completion 如果请求成功,设为"OK";如果请求未完成或者不是一系列请求中最后一部分则设为空 30$request_filename 当前请求的文件路径名,比如/opt/nginx/www/test.php 31$request_method 请求的方法,比如"GET""POST"32$request_uri 请求的URI,带参数; 比如http://localhost:88/test1/ 33$scheme 所用的协议,比如http或者是https 34$server_addr 服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费) 35$server_name 请求到达的服务器名 36$server_port 请求到达的服务器端口号 37$server_protocol 请求的协议版本,"HTTP/1.0""HTTP/1.1" 38$uri 请求的URI,可能和最初的值有不同,比如经过重定向之类的

测试获取变量

1location /test_url { 2 echo "url:$uri"; 3} 4 5location /test_url { 6 echo "url:$uri"; 7 echo "full url : $host$request_uri"; 8}

openresty 使用redis

连接redis服务器

1---定义 redis关闭连接的方法 2local function close_redis(red) 3 if not red then 4 return 5 end 6 local ok, err = red:close() 7 if not ok then 8 ngx.say("close redis error : ", err) 9 end 10end

建立连接

1local ip = "192.168.31.247" 2local port = 6379 3local ok, err = red:connect(ip, port) 4if not ok then 5 ngx.say("connect to redis error : ", err) 6 return close_redis(red) 7end

调用API设置key

1ok, err = red:set("msg", "hello world") 2if not ok then 3 ngx.say("set msg error : ", err) 4 return close_redis(red) 5end

调用API获取key值

1local resp, err = red:get("msg") 2if not resp then 3 ngx.say("get msg error : ", err) 4 return close_redis(red) 5end

redis连接池

1local function close_redis(red) 2 if not red then 3 return 4 end 5 --释放连接(连接池实现) 6 local pool_max_idle_time = 10000 --毫秒 7 local pool_size = 100 --连接池大小 8 local ok, err = red:set_keepalive(pool_max_idle_time, pool_size) 9 if not ok then 10 ngx.say("set keepalive error : ", err) 11 end 12end

访问频率控制:

我们用redis的key表示用户,value表示用户的请求频次,再利用过期时间实现单位时间

要求10秒内只能访问10次frequency请求,超过返回403

首先为nginx.conf配置文件,nginx.conf部分内容如下:

1location /frequency { 2 access_by_lua_file /usr/local/lua/access_by_limit_frequency.lua; 3 echo "访问成功"; 4}

编辑access_by_limit_frequency.lua

1local function close_redis(red) 2 if not red then 3 return 4 end 5 --释放连接(连接池实现) 6 local pool_max_idle_time = 10000 --毫秒 7 local pool_size = 100 --连接池大小 8 local ok, err = red:set_keepalive(pool_max_idle_time, pool_size) 9 if not ok then 10 ngx.say("set keepalive error : ", err) 11 end 12end 13 14local function errlog(...) 15 ngx.log(ngx.ERR, "redis: ", ...) 16end 17 18local redis = require "resty.redis" --引入redis模块 19local red = redis:new() --创建一个对象,注意是用冒号调用的 20 21--设置超时(毫秒) 22red:set_timeout(1000) 23--建立连接 24local ip = "192.168.31.247" 25local port = 6379 26local ok, err = red:connect(ip, port) 27if not ok then 28 close_redis(red) 29 errlog("Cannot connect"); 30 return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) 31end 32 33local key = "limit:frequency:login:"..ngx.var.remote_addr 34 35--得到此客户端IP的频次 36local resp, err = red:get(key) 37if not resp then 38 close_redis(red) 39 return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis 获取值失败 40end 41 42if resp == ngx.null then 43 red:set(key, 1) -- 单位时间 第一次访问 44 red:expire(key, 10) --10秒时间 过期 45end 46 47if type(resp) == "string" then 48 if tonumber(resp) > 10 then -- 超过1049 close_redis(red) 50 return ngx.exit(ngx.HTTP_FORBIDDEN) --直接返回403 51 end 52end 53 54--调用API设置key 55ok, err = red:incr(key) 56if not ok then 57 close_redis(red) 58 return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis 报错 59end 60 61close_redis(red)

请求地址:/frequency

10秒内 超出10次 ,返回403

10秒后,又可以访问了

如果我们想整个网站 都加上这个限制条件,那只要把

access_by_lua_file /usr/local/lua/access_by_limit_frequency.lua;

这个配置,放在server部分,让所有的location 适用就行了

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid