| --- |
| title: FAQ |
| --- |
| |
| <!-- |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| --> |
| |
| ## Why do I need a new API gateway? |
| |
| As organizations move towards cloud native microservices, there is a need for an API gateway that is performant, flexible, secure and scalable. |
| |
| APISIX outperforms other API gateways in these metrics while being platform agnostic and fully dynamic delivering features like supporting multiple protocols, fine-grained routing and multi-language support. |
| |
| ## How does Apache APISIX differ from other API gateways? |
| |
| Apache APISIX differs in the following ways: |
| |
| - It uses etcd to save and synchronize configurations rather than relational databases like PostgreSQL or MySQL. The real-time event notification system in etcd is easier to scale than in these alternatives. This allows APISIX to synchronize the configuration in real-time, makes the code concise and avoids a single point of failure. |
| - Fully dynamic. |
| - Supports [hot loading of Plugins](/docs/apisix/plugins/#hot-reload). |
| |
| ## What is the performance impact of using Apache APISIX? |
| |
| Apache APISIX delivers the best performance among other API gateways with a single-core QPS of 18,000 with an average delay of 0.2 ms. |
| |
| Specific results of the performance benchmarks can be found [here](benchmark.md). |
| |
| ## Which platforms does Apache APISIX support? |
| |
| Apache APISIX is platform agnostic and avoids vendor lock-in. It is built for cloud native environments and can run on bare-metal machines to Kubernetes. It even support Apple Silicon chips. |
| |
| ## What does it mean by "Apache APISIX is fully dynamic"? |
| |
| Apache APISIX is fully dynamic in the sense that it doesn't require restarts to change its behavior. |
| |
| It does the following dynamically: |
| |
| - Reloading Plugins |
| - Proxy rewrites |
| - Proxy mirror |
| - Response rewrites |
| - Health checks |
| - Traffic split |
| |
| ## Does Apache APISIX have a user interface? |
| |
| Yes. Apache APISIX has an experimental feature called [Apache APISIX Dashboard](https://github.com/apache/apisix-dashboard), which is independent from Apache APISIX. To work with Apache APISIX through a user interface, you can deploy the Apache APISIX Dashboard. |
| |
| ## Can I write my own Plugins for Apache APISIX? |
| |
| Yes. Apache APISIX is flexible and extensible through the use of custom Plugins that can be specific to user needs. |
| |
| You can write your own Plugins by referring to [How to write your own Plugins](plugin-develop.md). |
| |
| ## Why does Apache APISIX use etcd for the configuration center? |
| |
| In addition to the basic functionality of storing the configurations, Apache APISIX also needs a storage system that supports these features: |
| |
| 1. Distributed deployments in clusters. |
| 2. Guarded transactions by comparisons. |
| 3. Multi-version concurrency control. |
| 4. Notifications and watch streams. |
| 5. High performance with minimum read/write latency. |
| |
| etcd provides these features and more making it ideal over other databases like PostgreSQL and MySQL. |
| |
| To learn more on how etcd compares with other alternatives see this [comparison chart](https://etcd.io/docs/latest/learning/why/#comparison-chart). |
| |
| ## When installing Apache APISIX dependencies with LuaRocks, why does it cause a timeout or result in a slow or unsuccessful installation? |
| |
| This is likely because the LuaRocks server used is blocked. |
| |
| To solve this you can use https_proxy or use the `--server` flag to specify a faster LuaRocks server. |
| |
| You can run the command below to see the available servers (needs LuaRocks 3.0+): |
| |
| ```shell |
| luarocks config rocks_servers |
| ``` |
| |
| Mainland China users can use `luarocks.cn` as the LuaRocks server. You can use this wrapper with the Makefile to set this up: |
| |
| ```bash |
| make deps ENV_LUAROCKS_SERVER=https://luarocks.cn |
| ``` |
| |
| If this does not solve your problem, you can try getting a detailed log by using the `--verbose` flag to diagnose the problem. |
| |
| ## How do I build the APISIX-Base environment? |
| |
| Some functions need to introduce additional NGINX modules, which requires APISIX to run on APISIX-Base. If you need these functions, you can refer to the code in [api7/apisix-build-tools](https://github.com/api7/apisix-build-tools) to build your own APISIX-Base environment. |
| |
| ## How can I make a gray release with Apache APISIX? |
| |
| Let's take an example query `foo.com/product/index.html?id=204&page=2` and consider that you need to make a gray release based on the `id` in the query string with this condition: |
| |
| 1. Group A: `id <= 1000` |
| 2. Group B: `id > 1000` |
| |
| There are two different ways to achieve this in Apache APISIX: |
| |
| 1. Using the `vars` field in a [Route](terminology/route.md): |
| |
| ```shell |
| 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" |
| } |
| } |
| }' |
| ``` |
| |
| All the available operators of the current `lua-resty-radixtree` are listed [here](https://github.com/api7/lua-resty-radixtree#operator-list). |
| |
| 2. Using the [traffic-split](plugins/traffic-split.md) Plugin. |
| |
| ## How do I redirect HTTP traffic to HTTPS with Apache APISIX? |
| |
| For example, you need to redirect traffic from `http://foo.com` to `https://foo.com`. |
| |
| Apache APISIX provides several different ways to achieve this: |
| |
| 1. Setting `http_to_https` to `true` in the [redirect](plugins/redirect.md) Plugin: |
| |
| ```shell |
| 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 |
| } |
| } |
| }' |
| ``` |
| |
| 2. Advanced routing with `vars` in the redirect Plugin: |
| |
| ```shell |
| 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 |
| } |
| } |
| }' |
| ``` |
| |
| 3. Using the `serverless` Plugin: |
| |
| ```shell |
| 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"] |
| } |
| } |
| }' |
| ``` |
| |
| To test this serverless Plugin: |
| |
| ```shell |
| curl -i -H 'Host: foo.com' http://127.0.0.1:9080/hello |
| ``` |
| |
| The response 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> |
| ``` |
| |
| ## How do I change Apache APISIX's log level? |
| |
| By default the log level of Apache APISIX is set to `warn`. You can set this to `info` to trace the messages printed by `core.log.info`. |
| |
| For this, you can set the `error_log_level` parameter in your configuration file (conf/config.yaml) as shown below and reload Apache APISIX. |
| |
| ```yaml |
| nginx_config: |
| error_log_level: "info" |
| ``` |
| |
| ## How do I reload my custom Plugins for Apache APISIX? |
| |
| All Plugins in Apache APISIX are hot reloaded. |
| |
| You can learn more about hot reloading of Plugins [here](https://apisix.apache.org/docs/apisix/architecture-design/plugin/#hot-reload). |
| |
| ## How do I configure Apache APISIX to listen on multiple ports when handling HTTP or HTTPS requests? |
| |
| By default, Apache APISIX listens only on port 9080 when handling HTTP requests. |
| |
| To configure Apache APISIX to listen on multiple ports, you can: |
| |
| 1. Modify the parameter `node_listen` in `conf/config.yaml`: |
| |
| ``` |
| apisix: |
| node_listen: |
| - 9080 |
| - 9081 |
| - 9082 |
| ``` |
| |
| Similarly for HTTPS requests, modify the parameter `ssl.listen_port` in `conf/config.yaml`: |
| |
| ``` |
| apisix: |
| ssl: |
| listen_port: |
| - 9443 |
| - 9444 |
| - 9445 |
| ``` |
| |
| 2. Reload or restart Apache APISIX. |
| |
| ## How does Apache APISIX achieve millisecond-level configuration synchronization? |
| |
| Apache APISIX uses etcd for its configuration center. etcd provides subscription functions like [watch](https://github.com/api7/lua-resty-etcd/blob/master/api_v3.md#watch) and [watchdir](https://github.com/api7/lua-resty-etcd/blob/master/api_v3.md#watchdir) that can monitor changes to specific keywords or directories. |
| |
| In Apache APISIX, we use [etcd.watchdir](https://github.com/api7/lua-resty-etcd/blob/master/api_v3.md#watchdir) to monitor changes in a directory. |
| |
| If there is no change in the directory being monitored, the process will be blocked until it times out or run into any errors. |
| |
| If there are changes in the directory being monitored, etcd will return this new data within milliseconds and Apache APISIX will update the cache memory. |
| |
| ## How do I customize the Apache APISIX instance id? |
| |
| By default, Apache APISIX reads the instance id from `conf/apisix.uid`. If this is not found and no id is configured, Apache APISIX will generate a `uuid` for the instance id. |
| |
| To specify a meaningful id to bind Apache APISIX to your internal system, set the `id` in your `conf/config.yaml` file: |
| |
| ```yaml |
| apisix: |
| id: "your-id" |
| ``` |
| |
| ## Why are there errors saying "failed to fetch data from etcd, failed to read etcd dir, etcd key: xxxxxx" in the error.log? |
| |
| Please follow the troubleshooting steps described below: |
| |
| 1. Make sure that there aren't any networking issues between Apache APISIX and your etcd deployment in your cluster. |
| 2. If your network is healthy, check whether you have enabled the [gRPC gateway](https://etcd.io/docs/v3.4/dev-guide/api_grpc_gateway/) for etcd. The default state depends on whether you used command line options or a configuration file to start the etcd server. |
| |
| - If you used command line options, gRPC gateway is enabled by default. You can enable it manually as shown below: |
| |
| ```sh |
| etcd --enable-grpc-gateway --data-dir=/path/to/data |
| ``` |
| |
| **Note**: This flag is not shown while running `etcd --help`. |
| |
| - If you used a configuration file, gRPC gateway is disabled by default. You can manually enable it as shown below: |
| |
| In `etcd.json`: |
| |
| ```json |
| { |
| "enable-grpc-gateway": true, |
| "data-dir": "/path/to/data" |
| } |
| ``` |
| |
| In `etcd.conf.yml`: |
| |
| ```yml |
| enable-grpc-gateway: true |
| ``` |
| |
| **Note**: This distinction was eliminated by etcd in their latest master branch but wasn't backported to previous versions. |
| |
| ## How do I setup high availability Apache APISIX clusters? |
| |
| Apache APISIX can be made highly available by adding a load balancer in front of it as APISIX's data plane is stateless and can be scaled when needed. |
| |
| The control plane of Apache APISIX is highly available as it relies only on an etcd cluster. |
| |
| ## Why does the `make deps` command fail when installing Apache APISIX from source? |
| |
| When executing `make deps` to install Apache APISIX from source, you can get an error as shown below: |
| |
| ```shell |
| $ 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 |
| ``` |
| |
| This is caused by the missing OpenResty openssl development kit. To install it, refer [installing dependencies](install-dependencies.md). |
| |
| ## How do I access the APISIX Dashboard through Apache APISIX proxy? |
| |
| You can follow the steps below to configure this: |
| |
| 1. Configure different ports for Apache APISIX proxy and Admin API. Or, disable the Admin API. |
| |
| ```yaml |
| apisix: |
| port_admin: 9180 # use a separate port |
| ``` |
| |
| 2. Add a proxy Route for the Apache APISIX dashboard: |
| |
| ```shell |
| 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" |
| } |
| }' |
| ``` |
| |
| **Note**: The Apache APISIX Dashboard is listening on `127.0.0.1:9000`. |
| |
| ## How do I use regular expressions (regex) for matching `uri` in a Route? |
| |
| You can use the `vars` field in a Route for matching regular expressions: |
| |
| ```shell |
| 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 |
| } |
| } |
| }' |
| ``` |
| |
| And to test this request: |
| |
| ```shell |
| # uri matched |
| $ curl http://127.0.0.1:9080/hello -i |
| HTTP/1.1 200 OK |
| ... |
| |
| # uri didn't match |
| $ curl http://127.0.0.1:9080/12ab -i |
| HTTP/1.1 404 Not Found |
| ... |
| ``` |
| |
| For more info on using `vars` refer to [lua-resty-expr](https://github.com/api7/lua-resty-expr). |
| |
| ## Does the Upstream node support configuring a [FQDN](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) address? |
| |
| Yes. The example below shows configuring the FQDN `httpbin.default.svc.cluster.local` (a Kubernetes service): |
| |
| ```shell |
| 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 |
| } |
| } |
| }' |
| ``` |
| |
| To test this Route: |
| |
| ```shell |
| $ curl http://127.0.0.1:9080/ip -i |
| HTTP/1.1 200 OK |
| ... |
| ``` |
| |
| ## What is the `X-API-KEY` of the Admin API? Can it be modified? |
| |
| `X-API-KEY` of the Admin API refers to the `apisix.admin_key.key` in your `conf/config.yaml` file. It is the access token for the Admin API. |
| |
| By default, it is set to `edd1c9f034335f136f87ad84b625c8f1` and can be modified by changing the parameter in your `conf/config.yaml` file: |
| |
| ```yaml |
| apisix: |
| admin_key |
| - |
| name: "admin" |
| key: newkey |
| role: admin |
| ``` |
| |
| Now, to access the Admin API: |
| |
| ```shell |
| $ curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: newkey' -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 |
| ...... |
| ``` |
| |
| **Note**: By using the default token, you could be exposed to security risks. It is required to update it when deploying to a production environment. |
| |
| ## How do I allow all IPs to access Apache APISIX's Admin API? |
| |
| By default, Apache APISIX only allows IPs in the range `127.0.0.0/24` to access the Admin API. |
| |
| To allow IPs in all ranges, you can update your configuration file as show below and restart or reload Apache APISIX. |
| |
| ```yaml |
| apisix: |
| allow_admin: |
| - 0.0.0.0/0 |
| ``` |
| |
| **Note**: This should only be used in non-production environments to allow all clients to access Apache APISIX and is not safe for production environments. Always authorize specific IP addresses or address ranges for production environments. |
| |
| ## How do I auto renew SSL certificates with acme.sh? |
| |
| You can run the commands below to achieve this: |
| |
| ```bash |
| curl --output /root/.acme.sh/renew-hook-update-apisix.sh --silent https://gist.githubusercontent.com/anjia0532/9ebf8011322f43e3f5037bc2af3aeaa6/raw/65b359a4eed0ae990f9188c2afa22bacd8471652/renew-hook-update-apisix.sh |
| ``` |
| |
| ```bash |
| chmod +x /root/.acme.sh/renew-hook-update-apisix.sh |
| ``` |
| |
| ```bash |
| 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" |
| ``` |
| |
| ```bash |
| acme.sh --renew --domain demo.domain |
| ``` |
| |
| You can check [this post](https://juejin.cn/post/6965778290619449351) for a more detailed instruction on setting this up. |
| |
| ## How do I strip a prefix from a path before forwarding to Upstream in Apache APISIX? |
| |
| To strip a prefix from a path in your route, like to take `/foo/get` and strip it to `/get`, you can use the [proxy-rewrite](plugins/proxy-rewrite.md) Plugin: |
| |
| ```shell |
| 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 |
| } |
| } |
| }' |
| ``` |
| |
| And to test this configuration: |
| |
| ```shell |
| curl http://127.0.0.1:9080/foo/get -i |
| HTTP/1.1 200 OK |
| ... |
| { |
| ... |
| "url": "http://127.0.0.1/get" |
| } |
| ``` |
| |
| ## How do I fix the error `unable to get local issuer certificate` in Apache APISIX? |
| |
| You can manually set the path to your certificate by adding it to your `conf/config.yaml` file as shown below: |
| |
| ```yaml |
| apisix: |
| ssl: |
| ssl_trusted_certificate: /path/to/certs/ca-certificates.crt |
| ``` |
| |
| **Note**: When you are trying to connect TLS services with cosocket and if APISIX does not trust the peer's TLS certificate, you should set the parameter `apisix.ssl.ssl_trusted_certificate`. |
| |
| For example, if you are using Nacos for service discovery in APISIX, and Nacos has TLS enabled (configured host starts with `https://`), you should set `apisix.ssl.ssl_trusted_certificate` and use the same CA certificate as Nacos. |
| |
| ## How do I fix the error `module 'resty.worker.events' not found` in Apache APISIX? |
| |
| This error is caused by installing Apache APISIX in the `/root` directory. The worker process would by run by the user "nobody" and it would not have enough permissions to access the files in the `/root` directory. |
| |
| To fix this, you can change the APISIX installation directory to the recommended directory: `/usr/local`. |
| |
| ## What is the difference between `plugin-metadata` and `plugin-configs` in Apache APISIX? |
| |
| The differences between the two are described in the table below: |
| |
| | `plugin-metadata` | `plugin-config` | |
| | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | |
| | Metadata of a Plugin shared by all configuration instances of the Plugin. | Collection of configuration instances of multiple different Plugins. | |
| | Used when there are property changes that needs to be propagated across all configuration instances of a Plugin. | Used when you need to reuse a common set of configuration instances so that it can be extracted to a `plugin-config` and bound to different Routes. | |
| | Takes effect on all the entities bound to the configuration instances of the Plugin. | Takes effect on Routes bound to the `plugin-config`. | |
| |
| ## Where can I find more answers? |
| |
| You can find more answers on: |
| |
| - [Apache APISIX Slack Channel](/docs/general/community#joining-the-slack-channel) |
| - [Ask questions on APISIX mailing list](/docs/general/community#joining-the-mailing-list) |
| - [GitHub Issues](https://github.com/apache/apisix/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) and [GitHub Discussions](https://github.com/apache/apisix/discussions) |