There are new requirements for API gateways in the field of microservices: higher flexibility, higher performance requirements, and cloud native.
Apache APISIX is based on etcd to save and synchronize configuration, not relational databases such as Postgres or MySQL.
This not only eliminates polling, makes the code more concise, but also makes configuration synchronization more real-time. At the same time, there will be no single point in the system, which is more usable.
In addition, Apache APISIX has dynamic routing and hot loading of plug-ins, which is especially suitable for API management under micro-service system.
One of the goals of Apache APISIX design and development is the highest performance in the industry. Specific test data can be found here:benchmark
Apache APISIX is the highest performance API gateway with a single-core QPS of 23,000, with an average delay of only 0.6 milliseconds.
Yes. Apache APISIX has an experimental feature called Apache APISIX Dashboard, which is an independent project apart from Apache APISIX. You can deploy Apache APISIX Dashboard to operate Apache APISIX through the user interface.
Of course, Apache APISIX provides flexible custom plugins for developers and businesses to write their own logic.
For the configuration center, configuration storage is only the most basic function, and Apache APISIX also needs the following features:
See more etcd why.
There are two possibilities when encountering slow luarocks:
For the first problem, you can use https_proxy or use the --server
option to specify a luarocks server that you can access or access faster. Run the luarocks config rocks_servers
command(this command is supported after luarocks 3.0) to see which server are available. For China mainland users, you can use the luarocks.cn
as the luarocks server.
We already provide a wrapper in the Makefile to simplify your job:
make deps ENV_LUAROCKS_SERVER=https://luarocks.cn
If using a proxy doesn't solve this problem, you can add --verbose
option during installation to see exactly how slow it is.
An example, foo.com/product/index.html?id=204&page=2
, gray release based on id
in the query string in URL as a condition:
There are two different ways to do this:
vars
field of route to do it.curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/index.html", "vars": [ ["arg_id", "<=", "1000"] ], "plugins": { "redirect": { "uri": "/test?group_id=1" } } }' curl -i http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/index.html", "vars": [ ["arg_id", ">", "1000"] ], "plugins": { "redirect": { "uri": "/test?group_id=2" } } }'
Here is the operator list of current lua-resty-radixtree
: https://github.com/api7/lua-resty-radixtree#operator-list
traffic-split
plugin to do it.Please refer to the traffic-split.md plugin documentation for usage examples.
An example, redirect http://foo.com
to https://foo.com
There are several different ways to do this.
http_to_https
in redirect
plugin:curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/hello", "host": "foo.com", "plugins": { "redirect": { "http_to_https": true } } }'
vars
with redirect
plugin:curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/hello", "host": "foo.com", "vars": [ [ "scheme", "==", "http" ] ], "plugins": { "redirect": { "uri": "https://$host$request_uri", "ret_code": 301 } } }'
serverless
plugin:curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/hello", "plugins": { "serverless-pre-function": { "phase": "rewrite", "functions": ["return function() if ngx.var.scheme == \"http\" and ngx.var.host == \"foo.com\" then ngx.header[\"Location\"] = \"https://foo.com\" .. ngx.var.request_uri; ngx.exit(ngx.HTTP_MOVED_PERMANENTLY); end; end"] } } }'
Then test it to see if it works:
curl -i -H 'Host: foo.com' http://127.0.0.1:9080/hello
The response body should be:
HTTP/1.1 301 Moved Permanently Date: Mon, 18 May 2020 02:56:04 GMT Content-Type: text/html Content-Length: 166 Connection: keep-alive Location: https://foo.com/hello Server: APISIX web server <html> <head><title>301 Moved Permanently</title></head> <body> <center><h1>301 Moved Permanently</h1></center> <hr><center>openresty</center> </body> </html>
The default log level for Apache APISIX is warn
. However You can change the log level to info
if you want to trace the messages print by core.log.info
.
Steps:
error_log_level: "warn"
to error_log_level: "info"
in conf/config.yaml.nginx_config: error_log_level: "info"
Now you can trace the info level log in logs/error.log.
The Apache APISIX plugin supports hot reloading. See the Hot reload
section in plugins for how to do that.
By default, Apache APISIX only listens on port 9080 when handling HTTP requests. If you want Apache APISIX to listen on multiple ports, you need to modify the relevant parameters in the configuration file as follows:
Modify the parameter of HTTP port listen node_listen
in conf/config.yaml
, for example:
apisix: node_listen: - 9080 - 9081 - 9082
Handling HTTPS requests is similar, modify the parameter of HTTPS port listen ssl.listen_port
in conf/config.yaml
, for example:
apisix: ssl: listen_port: - 9443 - 9444 - 9445
Reload or restart Apache APISIX
etcd provides subscription functions to monitor whether the specified keyword or directory is changed (for example: watch, watchdir).
Apache APISIX uses etcd.watchdir to monitor directory content changes:
With the help of etcd which incremental notification feature is millisecond-level, Apache APISIX achieve millisecond-level of configuration synchronization.
By default, Apache APISIX will read the instance id from conf/apisix.uid
. If it is not found, and no id is configured, Apache APISIX will generate a uuid
as the instance id.
If you want to specify a meaningful id to bind Apache APISIX instance to your internal system, you can configure it in conf/config.yaml
, for example:
``` apisix: id: "your-meaningful-id" ```
First please make sure the network between Apache APISIX and etcd cluster is not partitioned.
If the network is healthy, please check whether your etcd cluster enables the gRPC gateway. However, The default case for this feature is different when use command line options or configuration file to start etcd server.
--enable-grpc-gateway
.etcd --enable-grpc-gateway --data-dir=/path/to/data
Note this option is not shown in the output of etcd --help
.
enable-grpc-gateway
explicitly.# etcd.json { "enable-grpc-gateway": true, "data-dir": "/path/to/data" }
# etcd.conf.yml enable-grpc-gateway: true
Indeed this distinction was eliminated by etcd in their master branch, but not backport to announced versions, so be care when deploy your etcd cluster.
The high availability of Apache APISIX can be divided into two parts:
The data plane of Apache APISIX is stateless and can be elastically scaled at will. Just add a layer of LB in front.
The control plane of Apache APISIX relies on the highly available implementation of etcd cluster
and does not require any relational database dependency.
make deps
command fail in source installation?When executing the make deps
command, an error such as the one shown below occurs. This is caused by the missing openresty's openssl
development kit, you need to install it first. Please refer to the install dependencies document for installation.
$ make deps ...... Error: Failed installing dependency: https://luarocks.org/luasec-0.9-1.src.rock - Could not find header file for OPENSSL No file openssl/ssl.h in /usr/local/include You may have to install OPENSSL in your system and/or pass OPENSSL_DIR or OPENSSL_INCDIR to the luarocks command. Example: luarocks install luasec OPENSSL_DIR=/usr/local make: *** [deps] Error 1
conf/config.yaml
.The Admin API use a separate port 9180:
apisix: port_admin: 9180 # use a separate port
Note: The Apache APISIX Dashboard service here is listening on 127.0.0.1:9000
.
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uris":[ "/*" ], "name":"apisix_proxy_dashboard", "upstream":{ "nodes":[ { "host":"127.0.0.1", "port":9000, "weight":1 } ], "type":"roundrobin" } }'
uri
for regular matchingThe regular matching of uri is achieved through the vars
field of route.
curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/*", "vars": [ ["uri", "~~", "^/[a-z]+$"] ], "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }'
Test request:
# The uri matched successfully $ curl http://127.0.0.1:9080/hello -i HTTP/1.1 200 OK ... # The uri match failed $ curl http://127.0.0.1:9080/12ab -i HTTP/1.1 404 Not Found ...
In route, we can achieve more condition matching by combining uri
with vars
field. For more details of using vars
, please refer to lua-resty-expr.
This is supported. Here is an example where the FQDN
is httpbin.default.svc.cluster.local
(a Kubernetes Service):
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/ip", "upstream": { "type": "roundrobin", "nodes": { "httpbin.default.svc.cluster.local": 1 } } }'
# Test request $ curl http://127.0.0.1:9080/ip -i HTTP/1.1 200 OK ...
X-API-KEY
of Admin API? Can it be modified?X-API-KEY
of Admin API refers to the apisix.admin_key.key
in the config.yaml
file, and the default value is edd1c9f034335f136f87ad84b625c8f1
. It is the access token of the Admin API.Note: There are security risks in using the default API token. It is recommended to update it when deploying to a production environment.
X-API-KEY
can be modified.For example: make the following changes to the apisix.admin_key.key
in the conf/config.yaml
file and reload Apache APISIX.
apisix: admin_key - name: "admin" key: abcdefghabcdefgh role: admin
Access the Admin API:
$ curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: abcdefghabcdefgh' -X PUT -d ' { "uris":[ "/*" ], "name":"admin-token-test", "upstream":{ "nodes":[ { "host":"127.0.0.1", "port":1980, "weight":1 } ], "type":"roundrobin" } }' HTTP/1.1 200 OK ......
The route was created successfully. It means that the modification of X-API-KEY
takes effect.
By default, Apache APISIX only allows the IP range of 127.0.0.0/24
to access the Admin API
. If you want to allow all IP access, then you only need to add the following configuration in the conf/config.yaml
configuration file.
apisix: allow_admin: - 0.0.0.0/0
Restart or reload Apache APISIX, all IPs can access the Admin API
.
Note: You can use this method in a non-production environment to allow all clients from anywhere to access your Apache APISIX
instances, but it is not safe to use it in a production environment. In production environment, please only authorize specific IP addresses or address ranges to access your instance.
$ curl --output /root/.acme.sh/renew-hook-update-apisix.sh --silent https://gist.githubusercontent.com/anjia0532/9ebf8011322f43e3f5037bc2af3aeaa6/raw/65b359a4eed0ae990f9188c2afa22bacd8471652/renew-hook-update-apisix.sh $ chmod +x /root/.acme.sh/renew-hook-update-apisix.sh $ acme.sh --issue --staging -d demo.domain --renew-hook "/root/.acme.sh/renew-hook-update-apisix.sh -h http://apisix-admin:port -p /root/.acme.sh/demo.domain/demo.domain.cer -k /root/.acme.sh/demo.domain/demo.domain.key -a xxxxxxxxxxxxx" $ acme.sh --renew --domain demo.domain
Blog https://juejin.cn/post/6965778290619449351 has detail setup.
To strip route prefix before forwarding to upstream, for example from /foo/get
to /get
, could be achieved through plugin proxy-rewrite
.
curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/foo/*", "plugins": { "proxy-rewrite": { "regex_uri": ["^/foo/(.*)","/$1"] } }, "upstream": { "type": "roundrobin", "nodes": { "httpbin.org:80": 1 } } }'
Test request:
$ curl http://127.0.0.1:9080/foo/get -i HTTP/1.1 200 OK ... { ... "url": "http://127.0.0.1/get" }
unable to get local issuer certificate
errorconf/config.yaml
# ... apisix: ssl: ssl_trusted_certificate: /path/to/certs/ca-certificates.crt # ...
Note:
apisix.ssl.ssl_trusted_certificate
As an example, if using Nacos as a service discovery in APISIX, Nacos has TLS protocol enabled, i.e. Nacos configuration host
starts with https://
, so you need to configure apisix.ssl.ssl_trusted_certificate
and use the same CA certificate as Nacos.
module 'resty.worker.events' not found
errorInstalling APISIX under the /root
directory causes this problem. Because the worker process is run by the user nobody
, it does not have enough permissions to access the files in the /root
directory. You need to change the APISIX installation directory, and it is recommended to install it in the /usr/local
directory.
plugin-metadata
and plugin-configs
plugin-metadata
is the metadata of the plugin, which is shared by all configuration instances of the plugin. When writing a plugin. If there are some property changes that need to take effect for all configuration instances of the plugin, then it is appropriate to put them in plugin-metadata
.
plugin-configs
is a collection of configuration instances of multiple different plugins. If you want to reuse a common set of plugin configuration instances, you can extract them into a Plugin Config and bind them to the corresponding routes.
The difference between plugin-metadata
and plugin-configs
:
plugin-metadata
works on all configuration instances of this plugin. plugin-configs
works on the plugin configuration instances under configured it.plugin-metadata
take effect on the entities bound to all configuration instances of this plugin. plugin-configs
take effect on the routes bound to this plugin-configs
.