pass to tengine response http\\n **/\\n Map<String, Object> tengineDubbo(Map<String, Object> httpRequestContext);\\n}\\n\\n
如上所示,Dubbo 接口的定义是固定的。即方法参数中 Map
表示 APISIX 传递给 Dubbo Provider 关于 HTTP request 的一些信息(如:header、body...)。而方法返回值的 Map
表示 Dubbo Provider 传递给 APISIX 要如何返回 HTTP response 的一些信息。
接口信息之后可通过 XML 配置方式发布 DemoService。
\\n<!-- service implementation, as same as regular local bean --\x3e\\n<bean id=\\"demoService\\" class=\\"org.apache.dubbo.samples.tengine.provider.DemoServiceImpl\\"/>\\n\\n<!-- declare the service interface to be exported --\x3e\\n<dubbo:service interface=\\"org.apache.dubbo.samples.tengine.DemoService\\" ref=\\"demoService\\"/>\\n
\\n通过上述配置后,Consumer 可通过 org.apache.dubbo.samples.tengine.DemoService
访问其中的tengineDubbo
方法。具体接口实现如下:
public class DemoServiceImpl implements DemoService {\\n @Override\\n public Map<String, Object> tengineDubbo(Map<String, Object> httpRequestContext) {\\n for (Map.Entry<String, Object> entry : httpRequestContext.entrySet()) {\\n System.out.println(\\"Key = \\" + entry.getKey() + \\", Value = \\" + entry.getValue());\\n }\\n\\n Map<String, Object> ret = new HashMap<String, Object>();\\n ret.put(\\"body\\", \\"dubbo success\\\\n\\"); // http response body\\n ret.put(\\"status\\", \\"200\\"); // http response status\\n ret.put(\\"test\\", \\"123\\"); // http response header\\n\\n return ret;\\n }\\n}\\n
\\n上述代码中,DemoServiceImpl
会打印接收到的 httpRequestContext
,并通过返回包含有指定 Key 的 Map 对象去描述该 Dubbo 请求的 HTTP 响应。
dubbo-samples-tengine
。config.yaml
文件中进行 dubbo-proxy
插件启用。# Add this in config.yaml\\nplugins:\\n - ... # plugin you need\\n - dubbo-proxy\\n
\\ncurl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"nodes\\": {\\n \\"127.0.0.1:20880\\": 1\\n },\\n \\"type\\": \\"roundrobin\\"\\n}\'\\n
\\ncurl http://127.0.0.1:9180/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"host\\": \\"example.org\\"\\n \\"uris\\": [\\n \\"/demo\\"\\n ],\\n \\"plugins\\": {\\n \\"dubbo-proxy\\": {\\n \\"service_name\\": \\"org.apache.dubbo.samples.tengine.DemoService\\",\\n \\"service_version\\": \\"0.0.0\\",\\n \\"method\\": \\"tengineDubbo\\"\\n }\\n },\\n \\"upstream_id\\": 1\\n}\'\\n
\\ncurl http://127.0.0.1:9080/demo -H \\"Host: example.org\\" -X POST --data \'{\\"name\\": \\"hello\\"}\'\\n\\n< HTTP/1.1 200 OK\\n< Date: Sun, 26 Dec 2021 11:33:27 GMT\\n< Content-Type: text/plain; charset=utf-8\\n< Content-Length: 14\\n< Connection: keep-alive\\n< test: 123\\n< Server: APISIX/2.11.0\\n<\\ndubbo success\\n
\\n说明:上述代码返回中包含了 test: 123
Header,以及 dubbo success
字符串作为 Body 体。这与我们在 DemoServiceImpl
编码的预期效果一致。
Key = content-length, Value = 17\\nKey = host, Value = example.org\\nKey = content-type, Value = application/x-www-form-urlencoded\\nKey = body, Value = [B@70754265\\nKey = accept, Value = */*\\nKey = user-agent, Value = curl/7.80.0\\n
\\n说明:通过 httpRequestContext
可以拿到 HTTP 请求的 Header 和 Body。其中 Header 会作为 Map 元素,而 Body 中 Key 值是固定的字符串\\"body\\",Value 则代表 Byte 数组。
在上述的简单用例中可以看出,我们确实通过 Apache APISIX 将 Dubbo Service 发布为一个 HTTP 服务,但是在使用过程中的限制也非常明显。比如:接口的参数和返回值都必须要是 Map<String, Object>
。
那么,如果项目中出现已经定义好、但又不符合上述限制的接口,该如何通过 Apache APISIX 来暴露 HTTP 服务呢?
\\n针对上述场景,我们可以通过 HTTP Request Body 描述要调用的 Service 和 Method 以及对应参数,再利用 Java 的反射机制实现目标方法的调用。最后将返回值序列化为 JSON,并写入到 HTTP Response Body 中。
\\n这样就可以将 Apache APISIX 的 「HTTP to Dubbo」 能力进一步加强,并应用到所有已存在的 Dubbo Service 中。具体操作可参考下方:
\\npublic class DubboInvocationParameter {\\n private String type;\\n private String value;\\n}\\n\\npublic class DubboInvocation {\\n private String service;\\n private String method;\\n private DubboInvocationParameter[] parameters;\\n}\\n\\npublic interface HTTP2DubboService {\\n Map<String, Object> invoke(Map<String, Object> context) throws Exception;\\n}\\n\\n\\n@Component\\npublic class HTTP2DubboServiceImpl implements HTTP2DubboService {\\n\\n @Autowired\\n private ApplicationContext appContext;\\n\\n @Override\\n public Map<String, Object> invoke(Map<String, Object> context) throws Exception {\\n DubboInvocation invocation = JSONObject.parseObject((byte[]) context.get(\\"body\\"), DubboInvocation.class);\\n Object[] args = new Object[invocation.getParameters().size()];\\n for (int i = 0; i < args.length; i++) {\\n DubboInvocationParameter parameter = invocation.getParameters().get(i);\\n args[i] = JSONObject.parseObject(parameter.getValue(), Class.forName(parameter.getType()));\\n }\\n\\n Object svc = appContext.getBean(Class.forName(invocation.getService()));\\n Object result = svc.getClass().getMethod(invocation.getMethod()).invoke(args);\\n Map<String, Object> httpResponse = new HashMap<>();\\n httpResponse.put(\\"status\\", 200);\\n httpResponse.put(\\"body\\", JSONObject.toJSONString(result));\\n return httpResponse;\\n }\\n\\n}\\n
\\ncurl http://127.0.0.1:9080/demo -H \\"Host: example.org\\" -X POST --data \'\\n{\\n \\"service\\": \\"org.apache.dubbo.samples.tengine.DemoService\\",\\n \\"method\\": \\"createUser\\",\\n \\"parameters\\": [\\n {\\n \\"type\\": \\"org.apache.dubbo.samples.tengine.User\\",\\n \\"value\\": \\"{\'name\': \'hello\'}\\"\\n }\\n ]\\n}\'\\n
\\n本文为大家介绍了如何借助 Apache APISIX 实现 Dubbo Service 的代理,通过引入 dubbo-proxy
插件便可为 Dubbo 框架的后端系统构建更简单更高效的流量链路。
希望通过上述操作步骤和用例场景分享,能为大家在相关场景的使用提供借鉴思路。更多关于 dubbo-proxy
插件的介绍与使用可参考官方文档。
Apache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。Apache APISIX 不仅支持插件动态变更和热插拔,而且拥有众多实用的插件。Apache APISIX 的 OpenID Connect 插件支持 OpenID Connect 协议,用户可以使用该插件让 Apache APISIX 对接 Authing 服务,作为集中式认证网关部署于企业中。
\\nAuthing 是国内首款以开发者为中心的全场景身份云产品,集成了所有主流身份认证协议,为企业和开发者提供完善安全的用户认证和访问管理服务。以「API First」作为产品基石,把身份领域所有常用功能都进行了模块化的封装,通过全场景编程语言 SDK 将所有能力 API 化提供给开发者。同时,用户可以灵活的使用 Authing 开放的 RESTful APIs 进行功能拓展,满足不同企业不同业务场景下的身份管理需求。
\\n在传统认证模式下,各个后端应用服务需要单独开发功能以支持身份认证功能,例如与身份提供商进行交互、获取用户的身份信息等功能。
\\n与传统认证模式不同,集中身份认证模式把用户认证从应用服务中抽离了出来。以 Apache APISIX 为例,集中认证的流程如上图所示:首先由用户发起请求(request),然后由前置的网关负责用户认证流程,与身份提供方对接,向身份提供方发送身份认证(authorization)请求。身份提供方返回用户身份信息(user info)。网关完成用户身份识别后,将用户身份信息通过请求头的形式转发至后端应用。
\\n相比较传统认证模式,集中认证模式下有如下优点:
\\n同时结合 Authing 强大的身份认证管理功能,可实现如下功能:
\\n更多具体内容可参考 Authing 应用集成网关。
\\n登录 Authing 账号,选择自建应用,并填入应用名称和认证地址。如果你没有 Authing 账号,请访问 Authing 官网,单击右上角 “登录/注册”,注册一个 Authing 账号。\\n
单击“创建”,创建一个 Authing 应用。\\n
设置登录和登出的跳转 URL。在认证过程中,Authing 将会拒绝除配置以外的回调 URL,由于本次为本地测试,所以将登录回调 URL 和登出回调 URL 都设置为 APISIX 访问地址 http://127.0.0.1:9080/ 。\\n
创建用户(可选)。在用户列表页面,创建用户,账号密码分别为 user1/user1,并且可以在「用户信息-授权管理」页面中设置是否允许应用的访问(默认为允许)。\\n\\n
访问应用页面,获取以下配置,配置 Apache APISIX OpenID Connect 时需要提供这些信息:
\\nclient_id
和 {YOUR_CLIENT_ID}
对应。client_secret
和 {YOUR_CLIENT_SECRET}
对应。{YOUR_DISCOVERY}
对应。\\n你可以通过源码包、Docker、Helm Chart 等多种方式来安装 Apache APISIX。
\\nApache APISIX 的运行环境需要依赖 NGINX 和 etcd,所以在安装 Apache APISIX 前,请根据您使用的操作系统安装对应的依赖。我们提供了 CentOS7、Fedora 31 & 32 、Ubuntu 16.04 & 18.04、 Debian 9 & 10 和 MacOS 上的依赖安装操作步骤,详情请参考安装依赖。
\\n通过 Docker 或 Helm Chart 安装 Apache APISIX 时,已经包含了所需的 NGINX 和 etcd,请参照各自对应的文档。
\\n这种安装方式适用于 CentOS 7 操作系统,请运行以下命令安装 Apache APISIX。
\\nsudo yum install -y https://github.com/apache/apisix/releases/download/2.7/apisix-2.7-0.x86_64.rpm\\n
\\n详情请参考:使用 Docker 安装 Apache APISIX。
\\n详情请参考:使用 Helm Chart 安装 Apache APISIX。
\\napisix-2.7
的目录:mkdir apisix-2.7\\n
\\nwget https://downloads.apache.org/apisix/2.7/apache-apisix-2.7-src.tgz\\n
\\n您也可以通过 Apache APISIX 官网下载 Apache APISIX Release 源码包。 Apache APISIX 官网也提供了 Apache APISIX、APISIX Dashboard 和 APISIX Ingress Controller 的源码包,详情请参考 Apache APISIX 官网-下载页。
\\ntar zxvf apache-apisix-2.7-src.tgz -C apisix-2.7\\n
\\n# 切换到 apisix-2.7 目录\\ncd apisix-2.7\\n# 创建依赖\\nmake deps\\n
\\n运行以下命令初始化 NGINX 配置文件和 etcd。
\\n# initialize NGINX config file and etcd\\nmake init\\n
\\n运行以下命令,启动 Apache APISIX。
\\napisix start\\n
\\n创建路由并配置 OpenID Connect 插件。OpenID Connect 配置列表如下。
\\n字段 | \\n默认值 | \\n使用说明 | \\n
---|---|---|
client_id | \\nN/A | \\nOAuth 客户端 ID | \\n
client_secret | \\nN/A | \\nOAuth 客户端密钥 | \\n
discovery | \\nN/A | \\n身份提供商的服务发现端点 | \\n
scope | \\nopenid | \\n需要访问资源范围 | \\n
relm | \\napisix | \\n指定 WWW-Authenticate 响应头验证信息 | \\n
bearer_only | \\nfalse | \\n是否检查请求头中的 token | \\n
logout_path | \\n/logout | \\n登出的 URI | \\n
redirect_uri | \\nrequest_uri | \\n身份提供商跳转回来的 URI,默认为请求地址 | \\n
timeout | \\n3 | \\n请求超时时间,单位为秒 | \\n
ssl_verify | \\nfalse | \\n是否身份提供商的校验 ssl 证书 | \\n
introspection_endpoint | \\nN/A | \\n身份提供商的令牌验证端点的 URL,不填则将从 discovery 响应中提取。 | \\n
introspection_endpoint_auth_method | \\nclient_secret_basic | \\n令牌自省的认证方法名称 | \\n
public_key | \\nN/A | \\n验证令牌的公钥 | \\n
token_signing_alg_values_expected | \\nN/A | \\n验证令牌的算法 | \\n
set_access_token_header | \\ntrue | \\n是否在请求头中携带 access token | \\n
access_token_in_authorization_header | \\nfalse | \\ntrue 时将 access token 放置在 Authorization 头中,false 时将 access token 放置在 X-Access-Token 头中。 | \\n
set_id_token_header | \\nfalse | \\n是否将 ID token 携带至 X-ID-Token 请求头 | \\n
set_userinfo_header | \\nfalse | \\n是否将用户信息携带至 X-Userinfo 请求头 | \\n
以下代码示例通过 Apache APISIX Admin API 进行创建路由,设置路由的上游为 httpbin.org。httpbin.org
是一个简单的用于接收请求和响应请求的后端服务,下文将使用 httpbin.org
的 get
页面,参考 http bin get。
具体配置项请参考 Apache APISIX OpenID Connect Plugin。
\\ncurl -XPOST 127.0.0.1:9080/apisix/admin/routes -H \\"X-Api-Key: edd1c9f034335f136f87ad84b625c8f1\\" -d \'{\\n \\"uri\\":\\"/*\\",\\n \\"plugins\\":{\\n \\"openid-connect\\":{\\n \\"client_id\\":\\"{YOUR_CLIENT_ID}\\",\\n \\"client_secret\\":\\"{YOUR_CLIENT_SECRET}\\",\\n \\"discovery\\":\\"https://{YOUR_DISCOVERY}\\",\\n \\"scope\\":\\"openid profile\\",\\n \\"bearer_only\\":false,\\n \\"realm\\":\\"apisix\\",\\n \\"introspection_endpoint_auth_method\\":\\"client_secret_post\\",\\n \\"redirect_uri\\":\\"http://127.0.0.1:9080/\\"\\n }\\n },\\n \\"upstream\\":{\\n \\"type\\":\\"roundrobin\\",\\n \\"nodes\\":{\\n \\"httpbin.org:80\\":1\\n }\\n }\\n}\'\\n
\\n访问 \\"http://127.0.0.1:9080/get\\",由于已经开启了 OpenID Connect 插件,所以页面被重定向到 Authing 登录页面(可在 Authing 控制台中 「应用-品牌化」对该页面进行定制)。\\n
输入用户在 Authing 注册的账号密码,或者在步骤一中创建的用户 user1/user1 ,单击“登录”,登录 Authing 账户。
\\n登录成功之后,能成功访问到 httpbin.org 中的 get 页面。该 httpbin.org/get 页面将返回请求的数据如下:
\\n...\\n\\"X-Access-Token\\": \\"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InFqeU55aVdVd2NhbUFxdEdVRUNCeFNsTWxQSWtTR2N1NmkyZzhEUk1OSGsifQ.eyJqdGkiOiJjTy16a0pCS0NSRFlHR2kyWkJhY0oiLCJzdWIiOiI2MWM5OGFmOTg0MjI4YWU0OTYyMDU4NTIiLCJpYXQiOjE2NDA1OTg4NTgsImV4cCI6MTY0MTgwODQ1OCwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSIsImlzcyI6Imh0dHBzOi8vYXBpc2l4LmF1dGhpbmcuY24vb2lkYyIsImF1ZCI6IjYxYzk4M2M0YjI4NzdkNDg2OWRkOGFjYiJ9.l2V8vDWcCObB1LjIhKs2ARG4J7WuB-0c-bnYZG2GP2zcpl6PMAPcId2B76CaXCU58ajGcfRmOlWJ67UaHrfWKv8IM4vcYN1gwhKdokSyrhEM31gQE-MzNEsEbPaVIGXdpR1N2JnAJK5-tKIjopDAXSwArfO6fQKTpjLhCi3COIA169WGRR4CKCwNzzpFAYP2ilNc18D_HRTBLS6UjxZSNUtWE5dbx7uBjblhwIwn5e1fxiEQcknVK8Dxf8NUliFECvr02HX2hNvmuCECkvA_mZYlshAeqidK8tSEXirAWsWS5jlXFqLiBJkhSHFrbxRyqeOSfJCJR_YcCwk9AzgZGg\\",\\n\\"X-Id-Token\\": \\"eyJhdF9oYXNoIjoiRl8tRjZaUVgtWVRDNEh0TldmcHJmUSIsImJpcnRoZGF0ZSI6bnVsbCwiZmFtaWx5X25hbWUiOm51bGwsImdlbmRlciI6IlUiLCJnaXZlbl9uYW1lIjpudWxsLCJpc3MiOiJodHRwczpcL1wvYXBpc2l4LmF1dGhpbmcuY25cL29pZGMiLCJwaWN0dXJlIjoiaHR0cHM6XC9cL2ZpbGVzLmF1dGhpbmcuY29cL2F1dGhpbmctY29uc29sZVwvZGVmYXVsdC11c2VyLWF2YXRhci5wbmciLCJwcmVmZXJyZWRfdXNlcm5hbWUiOm51bGwsInVwZGF0ZWRfYXQiOiIyMDIxLTEyLTI3VDA5OjU0OjE3Ljc3M1oiLCJ3ZWJzaXRlIjpudWxsLCJ6b25laW5mbyI6bnVsbCwibmFtZSI6bnVsbCwiaWF0IjoxNjQwNTk4ODU4LCJuaWNrbmFtZSI6bnVsbCwibm9uY2UiOiJmMTlmZjhjODM5NzdmZjNlMDczMzZmMzg3Y2QxM2EzMSIsIm1pZGRsZV9uYW1lIjpudWxsLCJleHAiOjE2NDE4MDg0NTgsInN1YiI6IjYxYzk4YWY5ODQyMjhhZTQ5NjIwNTg1MiIsImxvY2FsZSI6bnVsbCwiYXVkIjoiNjFjOTgzYzRiMjg3N2Q0ODY5ZGQ4YWNiIiwicHJvZmlsZSI6bnVsbH0=\\",\\n\\"X-Userinfo\\": \\"eyJ3ZWJzaXRlIjpudWxsLCJ6b25laW5mbyI6bnVsbCwibmFtZSI6bnVsbCwicHJvZmlsZSI6bnVsbCwibmlja25hbWUiOm51bGwsInN1YiI6IjYxYzk4YWY5ODQyMjhhZTQ5NjIwNTg1MiIsImxvY2FsZSI6bnVsbCwiYmlydGhkYXRlIjpudWxsLCJmYW1pbHlfbmFtZSI6bnVsbCwiZ2VuZGVyIjoiVSIsImdpdmVuX25hbWUiOm51bGwsIm1pZGRsZV9uYW1lIjpudWxsLCJwaWN0dXJlIjoiaHR0cHM6XC9cL2ZpbGVzLmF1dGhpbmcuY29cL2F1dGhpbmctY29uc29sZVwvZGVmYXVsdC11c2VyLWF2YXRhci5wbmciLCJwcmVmZXJyZWRfdXNlcm5hbWUiOm51bGwsInVwZGF0ZWRfYXQiOiIyMDIxLTEyLTI3VDA5OjU0OjE3Ljc3M1oifQ==\\"\\n...\\n
\\n其中:
\\nX-Access-Token:Apache APISIX 将从用户提供商获取到的 access token 放入 X-Access-Token 请求头,可以通过插件配置中的 access_token_in_authorization_header
来选择是否放入 Authorization 请求头中。
X-Id-Token:Apache APISIX 将从用户提供商获取到的 ID token 通过 base64 编码之后放入 X-Id-Token 请求头,可以通过插件配置中的 set_id_token_header
来选择是否开启该功能,默认为为开启状态。
X-Userinfo: Apache APISIX 将从用户提供商获取到的用户信息,通过 base64 编码之后放入 X-Userinfo,你可以通过插件配置中的 set_userinfo_header
来选择是否开启该功能,默认为开启状态。
由此可以看到,Apache APISIX 将会携带 X-Access-Token
、X-Id-Token
和 X-Userinfo
三个请求头传递至上游。上游可以通过解析这几个头部,从而获取到用户 ID 信息和用户的元数据。
在 Authing 控制台中的 「审计日志-用户行为日志」中可以观察到 user1 用户在 2021.12.27 17:54:17 成功登录。\\n
本文为大家描述了 Apache APISIX 和 Authing 对接的详细操作步骤,通过阅读本文,大家对于在 Apache APISIX 中使用 Authing 有了更清晰的理解。
\\nApache APISIX 不仅致力于保持自身的高性能,也一直非常重视开源生态的建设。目前 Apache APISIX 已经拥有了 10+ 个认证授权相关的插件,支持与业界主流的认证授权服务对接。
\\n如果你有对接其他认证授权的需求,不妨访问 Apache APISIX 的 GitHub,通过 issue 留下你的建议;或订阅 Apache APISIX 的邮件列表,通过邮件表达你的想法。我们也会在每周三晚上 8:00 举行社区周会,欢迎各位参加!
\\n","description":"项目介绍 关于 Apache APISIX\\n\\nApache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。Apache APISIX 不仅支持插件动态变更和热插拔,而且拥有众多实用的插件。Apache APISIX 的 OpenID Connect 插件支持 OpenID Connect 协议,用户可以使用该插件让 Apache APISIX 对接 Authing 服务,作为集中式认证网关部署于企业中。\\n\\n关于 Authing\\n\\nAuthing 是国内首款以开发者为中…","guid":"https://www.apiseven.com/blog/apisix-authing-integration","author":"朱欣欣","authorUrl":null,"authorAvatar":null,"publishedAt":"2022-01-03T16:00:00.206Z","media":[{"url":"https://static.apiseven.com/202108/1639467045776-715e1805-540b-4cef-87c5-6166e2af43a8.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639467122244-d4292436-c5ce-48f6-b1d5-67645f24fbc9.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641275135400-5a11226a-404d-43f7-bde5-6e1b9599cebd.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641275174810-f78469f7-24dd-41c8-bdc7-eb7d5ff58672.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641275642514-65a2205a-22dd-43b2-ba06-e51b249754a8.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641275703261-ec7d98d4-50ee-428c-b73c-a70002e67dfb.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641275703263-90176798-6bb7-40d5-976f-dfc516db020f.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641275800242-e937cfd4-6237-4928-adab-7ec99556bbac.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641276796088-48cb415e-d5dd-4c15-a3da-ecbb4c987b06.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641278494765-139b6ffc-227b-4f02-8b2a-45d762422e15.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641278494768-867dadf3-8ecd-4376-af03-d86b6a7aa698.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641278494771-42567d0c-8424-46e2-9c5b-a12cf1af6bc8.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1641276858261-00fb4d07-751e-42db-bbbf-e8550002466f.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"生态丰富持续进行中,Apache OpenWhisk 集成闪亮登场","url":"https://www.apiseven.com/blog/apisix-integrate-openwhisk-plugin","content":"本文将介绍 Apache APISIX 中新增插件——openwhisk
,并通过详细步骤向大家展示如何将 OpenWhisk 服务与 Apache APISIX 进行集成,来享受无服务器计算的优势。此插件预计在 Apache APISIX 2.12 版本中正式上线,敬请期待!
Apache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。Apache APISIX 不仅支持插件动态变更和热插拔,而且拥有众多实用的插件。
\\nApache OpenWhisk 是一个开源的分布式无服务器平台,可以通过执行函数响应任何规模的时间。它使用 Docker 容器管理基础设施、服务器和规模扩展,助力用户构建出色且高效的应用程序。
\\n在 OpenWhisk 中开发者可以使用多种编程语言来编写函数(称为 Action),这些函数将由 OpenWhisk 负责动态调度并处理来自事件(通过 trigger)或外部请求(通过 HTTP 请求)的响应。
\\nApache APISIX 为便捷集成 Apache OpenWhisk 提供了插件支持,用户可以定义一个包含无服务器插件的路由,并结合 Apache APISIX 提供的多种身份认证插件来实现认证与授权功能。
\\n大体操作原理如下:用户可以使用openwhisk插件在路由中定义一个“动态上游”,当路由匹配到请求时,它将中止到原上游的请求,并向 OpenWhisk 的 API Host 端点发送请求。
\\n请求中将包含用户为插件配置的 Namespace、Action、Service Token 以及原始 HTTP 请求体数据,并将从 OpenWhisk 中获取到的响应内容返回至客户端。
\\ndocker run --rm -d \\\\\\n -h openwhisk --name openwhisk \\\\\\n -p 3233:3233 -p 3232:3232 \\\\\\n -v /var/run/docker.sock:/var/run/docker.sock \\\\\\n openwhisk/standalone:nightly\\n\\ndocker exec openwhisk waitready\\n
\\nok: whisk auth set. Run \'wsk property get --auth\' to see the new value.\\nok: whisk API host set to http://openwhisk:3233\\nok: updated action testme\\nserver initializing...\\nserver initializing...\\n \\"ready\\": true\\nok: deleted action testme\\n
\\ntest.js
用作测试函数。function main(args) {\\n return {\\n \\"hello\\": args.name || \\"\\",\\n };\\n}\\n
\\n# 为 OpenWhisk CLI 工具设置 API Host 和鉴权信息,您可以从这里 https://s.apache.org/openwhisk-cli-download 下载它\\nwsk property set \\\\\\n --apihost \'http://localhost:3233\' \\\\\\n --auth \'23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP\'\\n\\n# 创建测试函数\\nwsk action create test test.js\\n
\\nopenwhisk
插件下面我们将创建一个路由,并为其添加 openwhisk
插件。执行以下命令:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"plugins\\": {\\n \\"openwhisk\\": {\\n \\"api_host\\": \\"http://localhost:3233\\",\\n \\"service_token\\": \\"23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP\\",\\n \\"namespace\\": \\"guest\\",\\n \\"action\\": \\"test\\"\\n }\\n },\\n \\"uri\\": \\"/openwhisk\\"\\n}\'\\n
\\n下面我们将使用 cURL 进行测试。
\\n# 使用 POST 请求并发送数据\\ncurl http://127.0.0.1:9080/openwhisk -i -X POST -d \'{\\n \\"name\\": \\"world\\"\\n}\'\\n\\nHTTP/1.1 200 OK\\nContent-Type: application/json\\nContent-Length: 17\\nServer: APISIX/2.10.2\\n\\n{\\"hello\\":\\"world\\"}\\n\\n# 使用 GET 请求\\ncurl http://127.0.0.1:9080/openwhisk -i\\n\\nHTTP/1.1 200 OK\\nContent-Type: application/json\\nContent-Length: 12\\nServer: APISIX/2.10.2\\n\\n{\\"hello\\":\\"\\"}\\n
\\ntest.js
测试函数function main(args) {\\n return {\\n \\"status\\": \\"403\\",\\n \\"headers\\": {\\n \\"test\\": \\"header\\"\\n },\\n \\"body\\": \\"A test body\\"\\n };\\n}\\n\\n2. 进行测试请求\\n\\n```shell\\n# 使用 GET 请求\\ncurl http://127.0.0.1:9080/openwhisk -i\\n\\nHTTP/1.1 403 FORBIDDEN\\nContent-Type: application/json\\nContent-Length: 12\\ntest: header\\nServer: APISIX/2.10.2\\n\\nA test body\\n
\\n如使用完毕,只需移除路由配置中 OpenWhisk 相关配置并保存,即可关闭路由上的 OpenWhisk 插件。此时您可以开启其他 Serverless 类插件或添加上游等后续操作。
\\n得益于 Apache APISIX 的动态化优势,开启关闭插件的过程都不需要重启 Apache APISIX,十分方便。
\\n本文为大家介绍了关于 openwhisk
插件的功能前瞻与使用步骤,更多关于 openwhisk
插件说明和完整配置列表,可以参考官方文档。
目前,我们也在开发其他 Serverless 插件以便与更多云服务进行集成。如果您对此类集成项目感兴趣,也欢迎随时在 GitHub Discussions 中发起讨论,或通过邮件列表进行交流。
\\n","description":"本文将介绍 Apache APISIX 中新增插件——openwhisk,并通过详细步骤向大家展示如何将 OpenWhisk 服务与 Apache APISIX 进行集成,来享受无服务器计算的优势。此插件预计在 Apache APISIX 2.12 版本中正式上线,敬请期待! 项目介绍\\nApache APISIX\\n\\nApache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。Apache APISIX 不仅支持插件动态变更和热插拔,而且拥有众多实用的插件。\\n\\nAp…","guid":"https://www.apiseven.com/blog/apisix-integrate-openwhisk-plugin","author":"白泽平","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-23T16:00:00.537Z","media":[{"url":"https://static.apiseven.com/202108/1640313816872-b2c018be-5433-4baf-ba6a-8330e160866a.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"再接再厉!Apache APISIX 集成 Open Policy Agent","url":"https://www.apiseven.com/blog/apache-apisix-opa-integration","content":"Open Policy Agent(OPA)是一个开源的轻量级通用策略引擎,可以代替软件中内置的策略功能模块,帮助用户实现服务与策略引擎的解耦。得益于 OPA 完善的生态系统,用户可以很容易地集成 OPA 和其他服务,例如程序库、HTTP API 等。
\\n如下图所示,OPA 首先通过策略语言 Rego 描述策略;然后通过 JSON 存储策略数据,之后用户就可以发送查询请求。收到查询请求后,OPA 将结合策略、数据和用户输入的查询请求内容生成策略决策,并将决策发送至服务。
\\nApache APISIX 提供了一个 opa
插件,用户可以使用这个插件,便捷地将 OPA 提供的策略能力引入到 Apache APISIX,实现灵活的身份认证与准入控制功能。
将 opa
插件配置在路由上后,Apache APISIX 会在处理响应请求时,将请求信息、连接信息等组装成 JSON 数据,并将其发送到策略决策 API 地址。只要在 OPA 中部署的策略符合 Apache APISIX 设定的数据规范,就可以实现如通过请求、拒绝请求、自定义状态码、自定义响应头、自定义响应头等功能。
本文以 HTTP API 为例为大家介绍 opa
插件,并详细说明如何将 Apache APISIX 与 OPA 进行集成,实现后端服务的认证授权解耦。
使用 Docker 构建 OPA 服务。
\\n# 使用 Docker 运行 OPA\\ndocker run -d --name opa -p 8181:8181 openpolicyagent/opa:0.35.0 run -s\\n
\\n创建 example
策略。
# 创建策略\\ncurl -XPUT \'localhost:8181/v1/policies/example\' \\\\\\n--header \'Content-Type: text/plain\' \\\\\\n--data-raw \'package example\\n\\nimport input.request\\nimport data.users\\n\\ndefault allow = false\\n\\nallow {\\n # 具有名为 test-header 值为 only-for-test请求头\\n request.headers[\\"test-header\\"] == \\"only-for-test\\"\\n # 请求方法为 GET\\n request.method == \\"GET\\"\\n # 请求路径以 /get 开头\\n startswith(request.path, \\"/get\\")\\n # GET 参数 test 存在且不等于 abcd\\n request.query[\\"test\\"] != \\"abcd\\"\\n # GET 参数 user 存在\\n request.query[\\"user\\"]\\n}\\n\\nreason = users[request.query[\\"user\\"]].reason {\\n not allow\\n request.query[\\"user\\"]\\n}\\n\\nheaders = users[request.query[\\"user\\"]].headers {\\n not allow\\n request.query[\\"user\\"]\\n}\\n\\nstatus_code = users[request.query[\\"user\\"]].status_code {\\n not allow\\n request.query[\\"user\\"]\\n}\'\\n
\\n创建 users
数据。
# 创建测试用户数据\\ncurl -XPUT \'localhost:8181/v1/data/users\' \\\\\\n--header \'Content-Type: application/json\' \\\\\\n--data-raw \'{\\n \\"alice\\": {\\n \\"headers\\": {\\n \\"Location\\": \\"http://example.com/auth\\"\\n },\\n \\"status_code\\": 302\\n },\\n \\"bob\\": {\\n \\"headers\\": {\\n \\"test\\": \\"abcd\\",\\n \\"abce\\": \\"test\\"\\n }\\n },\\n \\"carla\\": {\\n \\"reason\\": \\"Give you a string reason\\"\\n },\\n \\"dylon\\": {\\n \\"headers\\": {\\n \\"Content-Type\\": \\"application/json\\"\\n },\\n \\"reason\\": {\\n \\"code\\": 40001,\\n \\"desc\\": \\"Give you a object reason\\"\\n }\\n }\\n}\'\\n
\\n运行以下命令,创建路由,并启用 opa
插件。
curl -XPUT \'http://127.0.0.1:9080/apisix/admin/routes/r1\' \\\\\\n--header \'X-API-KEY: <api-key>\' \\\\\\n--header \'Content-Type: application/json\' \\\\\\n--data-raw \'{\\n \\"uri\\": \\"/*\\",\\n \\"methods\\": [\\n \\"GET\\",\\n \\"POST\\",\\n \\"PUT\\",\\n \\"DELETE\\"\\n ],\\n \\"plugins\\": {\\n \\"opa\\": {\\n \\"host\\": \\"http://127.0.0.1:8181\\",\\n \\"policy\\": \\"example\\"\\n }\\n },\\n \\"upstream\\": {\\n \\"nodes\\": {\\n \\"httpbin.org:80\\": 1\\n },\\n \\"type\\": \\"roundrobin\\"\\n }\\n}\'\\n
\\n接下来,请运行以下命令,向 opa
插件发送请求,测试插件运行状态。
# 允许请求\\ncurl -XGET \'127.0.0.1:9080/get?test=none&user=dylon\' \\\\\\n --header \'test-header: only-for-test\'\\n{\\n \\"args\\": {\\n \\"test\\": \\"abcd1\\",\\n \\"user\\": \\"dylon\\"\\n },\\n \\"headers\\": {\\n \\"Test-Header\\": \\"only-for-test\\",\\n \\"with\\": \\"more\\"\\n },\\n \\"origin\\": \\"127.0.0.1\\",\\n \\"url\\": \\"http://127.0.0.1/get?test=abcd1&user=dylon\\"\\n}\\n\\n# 拒绝请求并重写状态码和响应头\\ncurl -XGET \'127.0.0.1:9080/get?test=abcd&user=alice\' \\\\\\n --header \'test-header: only-for-test\'\\n\\nHTTP/1.1 302 Moved Temporarily\\nDate: Mon, 20 Dec 2021 09:37:35 GMT\\nContent-Type: text/html\\nContent-Length: 142\\nConnection: keep-alive\\nLocation: http://example.com/auth\\nServer: APISIX/2.11.0\\n\\n# 拒绝请求并返回自定义响应头\\ncurl -XGET \'127.0.0.1:9080/get?test=abcd&user=bob\' \\\\\\n --header \'test-header: only-for-test\'\\n\\nHTTP/1.1 403 Forbidden\\nDate: Mon, 20 Dec 2021 09:38:27 GMT\\nContent-Type: text/html; charset=utf-8\\nContent-Length: 150\\nConnection: keep-alive\\nabce: test\\ntest: abcd\\nServer: APISIX/2.11.0\\n\\n# 拒绝请求并返回自定义响应(字符串)\\ncurl -XGET \'127.0.0.1:9080/get?test=abcd&user=carla\' \\\\\\n --header \'test-header: only-for-test\'\\n\\nHTTP/1.1 403 Forbidden\\nDate: Mon, 20 Dec 2021 09:38:58 GMT\\nContent-Type: text/plain; charset=utf-8\\nTransfer-Encoding: chunked\\nConnection: keep-alive\\nServer: APISIX/2.11.0\\n\\nGive you a string reason\\n\\n# 拒绝请求并返回自定义响应(JSON)\\ncurl -XGET \'127.0.0.1:9080/get?test=abcd&user=dylon\' \\\\\\n --header \'test-header: only-for-test\'\\n\\nHTTP/1.1 403 Forbidden\\nDate: Mon, 20 Dec 2021 09:42:12 GMT\\nContent-Type: application/json\\nTransfer-Encoding: chunked\\nConnection: keep-alive\\nServer: APISIX/2.11.0\\n\\n{\\"code\\":40001,\\"desc\\":\\"Give you a object reason\\"}\\n
\\n得益于 Apache APISIX 的动态化特性,只需要移除路由配置中 opa
插件相关配置并保存,即可关闭路由上的 OPA 插件。
本文为大家描述了 Apache APISIX 和 Open Policy Agent 对接的详细操作步骤,希望通过本文可以让大家对于在 Apache APISIX 中使用 Open Policy Agent 有了更清晰的理解,方便后续进行上手实操。
\\nApache APISIX 不仅致力于保持自身的高性能,也一直非常重视开源生态的建设。目前 Apache APISIX 已经拥有了 10+ 个认证授权相关的插件,支持与业界主流的认证授权服务对接。
\\n如果你有对接其他认证授权的需求,不妨访问 Apache APISIX 的 GitHub,通过 issue 留下你的建议;或订阅 Apache APISIX 的邮件列表,通过邮件表达你的想法。
\\n","description":"Open Policy Agent(OPA)是一个开源的轻量级通用策略引擎,可以代替软件中内置的策略功能模块,帮助用户实现服务与策略引擎的解耦。得益于 OPA 完善的生态系统,用户可以很容易地集成 OPA 和其他服务,例如程序库、HTTP API 等。 如下图所示,OPA 首先通过策略语言 Rego 描述策略;然后通过 JSON 存储策略数据,之后用户就可以发送查询请求。收到查询请求后,OPA 将结合策略、数据和用户输入的查询请求内容生成策略决策,并将决策发送至服务。\\n\\n插件介绍\\n\\nApache APISIX 提供了一个 opa 插件,用户可以使用这个插件…","guid":"https://www.apiseven.com/blog/apache-apisix-opa-integration","author":"白泽平","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-23T16:00:00.065Z","media":[{"url":"https://static.apiseven.com/202108/1640332208554-40f574e3-0582-48f3-8e07-eb49fbd37ac7.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"捷报频传!Apache APISIX 现已支持对接 Google Cloud Logging","url":"https://www.apiseven.com/blog/apache-apisix-google-cloud","content":"日志是大型分布式系统的重要基础设施,可以帮助开发者检查观测服务运行的状态,提高服务故障排查和诊断效率以及进行多维度的分析,以此提高系统整体的稳定性和运行效率。
\\nGoogle Cloud Logging 是由 Google Cloud 提供的全代管式实时日志管理服务,提供 EB 级的存储、搜索、分析和提醒等服务。通过 Google Cloud Loging 的日志浏览器你可以简单高效的对日志进行对日志进行搜索、排序和分析,并且 Google Cloud Logging 还提供了保存查询和丰富的图表功能可以使日志筛查结果可回溯且有更直观的呈现。
\\nApache APISIX 在此之前已经支持集成了 HTTP Logger 、TCP Logger、Kafka Logger、UDP Logger、RocketMQ Logger、SkyWalking Logger、Aliyun Cloud Logging(SLS)等众多开源及云日志服务解决方案。
\\n最近,Apache APISIX 对 Google Cloud Logging 也完成了支持,在使用 Apache APISIX 作为网关时用户又多了一种新的日志解决方案:使用 google-cloud-logging 插件,将 Apache APISIX 的请求日志转发到 Google Cloud Logging 服务中进行分析和存储。
\\n启用该插件后, Apache APISIX 将在 Log Phase 获取请求上下文信息并序列化为 Google Cloud Logging 的日志格式,然后将序列化后的日志数据提交到批处理队列中,当批处理队列触发用户设置的时间或条目阈值时会将日志数据通过 Google Cloud API 批量转发到 Google Cloud Logging 服务中。
\\n本文将为大家介绍如何在 Apache APISIX 中配置和使用 Google Cloud Logging 服务。
\\ngoogle-cloud-logging. auth_file
配置项上,如下所示:curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\":\\"/logging.do\\",\\n \\"upstream\\":{\\n \\"type\\":\\"roundrobin\\",\\n \\"nodes\\":{\\n \\"127.0.0.1:1980\\":1\\n }\\n },\\n \\"plugins\\":{\\n \\"google-cloud-logging\\":{\\n // Google Cloud Logging 私钥文件\\n \\"auth_file\\":\\"/path/to/apache-apisix-fcafc68c2f41.json\\",\\n // 每个批处理队列最大容纳日志条目数\\n \\"batch_max_size\\": 1,\\n // 刷新批处理队列缓冲区的最大时间(以秒为单位)\\n \\"inactive_timeout\\": 10\\n }\\n }\\n}\'\\n
\\nproject_id
的值配置到 google-cloud-logging. auth_config.project_id
配置项中。private_key
的值配置到 google-cloud-logging. auth_config. private_key
配置项中。如下所示:
\\ncurl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\":\\"/logging.do\\",\\n \\"upstream\\":{\\n \\"type\\":\\"roundrobin\\",\\n \\"nodes\\":{\\n \\"127.0.0.1:1980\\":1\\n }\\n },\\n \\"plugins\\":{\\n \\"google-cloud-logging\\":{\\n // Google Cloud Logging 私钥文件\\n \\"auth_config\\":{\\n \\"project_id\\":\\"apache-apisix\\",\\n \\"private_key\\":\\"-----BEGIN RSA PRIVATE KEY-----your private key-----END RSA PRIVATE KEY-----\\"\\n },\\n // 每个批处理队列最大容纳日志条目数\\n \\"batch_max_size\\": 1,\\n // 刷新批处理队列缓冲区的最大时间(以秒为单位)\\n \\"inactive_timeout\\": 10\\n }\\n }\\n}\'\\n
\\n参数名称 | \\n是否必填 | \\n默认值 | \\n描述 | \\n
---|---|---|---|
auth_config | \\n否 | \\nn/a | \\nGoogle Cloud Logging 私钥文件,必须配置 auth_config 或 auth_file 之一 | \\n
auth_config.private_key | \\n是 | \\nn/a | \\nGoogle Cloud Logging 的私钥参数 | \\n
auth_config.project_id | \\n是 | \\nn/a | \\n谷歌服务帐号的项目 ID | \\n
auth_config.token_uri | \\n否 | \\noauth2.googleapis.com/token | \\n请求 Google Service Account 的令牌的 URI | \\n
auth_config.entries_uri | \\n否 | \\nlogging.googleapis.com/v2/entries:write | \\nGoogle Cloud Logging 写入日志条目的 API | \\n
auth_config.scopes | \\n否 | \\n[\\"https://www.googleapis.com/auth/logging.read\\",\\"https://www.googleapis.com/auth/logging.write\\",\\"https://www.googleapis.com/auth/logging.admin\\",\\"https://www.googleapis.com/auth/cloud-platform\\"] | \\n谷歌服务账号的访问范围, 参考:OAuth 2.0 Scopes for Google APIs | \\n
auth_file | \\n否 | \\nn/a | \\n谷歌服务账号 JSON 文件的路径(必须配置 auth_config 或 auth_file 之一) | \\n
ssl_verify | \\n否 | \\nTRUE | \\n启用 SSL 验证, 配置根据 OpenResty documentation选项 | \\n
resource | \\n否 | \\n{\\"type\\": \\"global\\"} | \\n谷歌监控资源,参考:MonitoredResource | \\n
log_id | \\n否 | \\napisix.apache.org%2Flogs | \\n谷歌日志 ID,参考:LogEntry. | \\n
max_retry_count | \\n否 | \\n0 | \\n从处理管道中移除之前的最大重试次数 | \\n
retry_delay | \\n否 | \\n1 | \\n如果执行失败,流程执行应延迟的秒数 | \\n
buffer_duration | \\n否 | \\n60 | \\n必须先处理批次中最旧条目的最大期限(以秒为单位) | \\n
inactive_timeout | \\n否 | \\n10 | \\n刷新缓冲区的最大时间(以秒为单位) | \\n
batch_max_size | \\n否 | \\n100 | \\n每个批处理队列可容纳的最大条目数 | \\n
curl -i http://127.0.0.1:9080/logging.do\\nHTTP/1.1 200 OK\\nContent-Type: text/html; charset=utf-8\\nTransfer-Encoding: chunked\\nConnection: keep-alive\\nDate: Fri, 10 Dec 2021 09:57:52 GMT\\nServer: APISIX/2.11.0\\n\\nHello, Google Cloud Logging\\n
\\n如使用结束,可以移除 google-cloud-logging
相关配置块进行停用该插件。
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\":\\"/logging.do\\",\\n \\"upstream\\":{\\n \\"type\\":\\"roundrobin\\",\\n \\"nodes\\":{\\n \\"127.0.0.1:1980\\":1\\n }\\n },\\n \\"plugins\\":{\\n }\\n}\'\\n
\\n本文为大家描述了 Apache APISIX 和 Google Cloud Logging 对接的详细操作步骤,希望通过本文可以让大家对于在 Apache APISIX 中使用 Google Cloud Logging 有更清晰的理解,方便后续进行上手实操。
\\nApache APISIX 不仅致力于保持自身的高性能,也一直非常重视开源生态的建设。目前 Apache APISIX 已经拥有了 10+ 个日志相关的插件,支持与业界主流的开源日志项目对接。
\\n如果你有对接其他日志的需求,不妨访问 Apache APISIX 的 GitHub,通过 issue 留下你的建议;或订阅 Apache APISIX 的邮件列表,通过邮件表达你的想法。
\\n强强联合!APISIX 集成 SkyWalking 打造全方位日志处理
\\nApache APISIX 携手 RocketMQ 为实时 API 日志监控功能再下一城
\\n","description":"日志是大型分布式系统的重要基础设施,可以帮助开发者检查观测服务运行的状态,提高服务故障排查和诊断效率以及进行多维度的分析,以此提高系统整体的稳定性和运行效率。 Google Cloud Logging 是由 Google Cloud 提供的全代管式实时日志管理服务,提供 EB 级的存储、搜索、分析和提醒等服务。通过 Google Cloud Loging 的日志浏览器你可以简单高效的对日志进行对日志进行搜索、排序和分析,并且 Google Cloud Logging 还提供了保存查询和丰富的图表功能可以使日志筛查结果可回溯且有更直观的呈现。\\n\\nApach…","guid":"https://www.apiseven.com/blog/apache-apisix-google-cloud","author":"帅进超","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-21T16:00:00.512Z","media":[{"url":"https://static.apiseven.com/202108/1640155567091-2611f8b8-8181-42d8-8756-e892b3768a8d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137078950-3a0b472b-df9f-4f75-9c03-816138860f74.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137136967-effec599-2263-45e7-874d-53a547b83aae.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137177601-6ac703ef-99e4-4ac2-82e3-5b978348f458.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137215687-4a2a4789-09d3-4cc0-85fa-be67762cf9b7.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137733012-6c9808c8-9c96-401e-a680-03a276b964c0.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137784375-e47cbe0e-7735-4e7b-a881-1a9ec1c12ffc.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137834702-76166e6f-ed98-4a85-a759-2ce78f795794.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137883981-0f780040-8398-4d38-9600-a5e54b29b48e.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640137970837-ed1994be-87d0-48b8-bec5-010200fe1f1d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640138660649-cd57da29-5965-4251-9deb-300de830dfd9.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640138732589-1aea201b-de2d-455a-8c04-c3f5a28dfa91.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640138785425-23ee8efe-bc0d-428a-a627-2f428440da37.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640138820163-aa459874-e78e-4156-ab74-58fc7e2ae13f.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1640139014263-fac86f87-d008-475c-aeae-289ab4ba62a8.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"两种方式教你在 K8s 中轻松部署 Apache APISIX","url":"https://www.apiseven.com/blog/how-to-deploy-apisix-in-kubernetes","content":"Apache APISIX 是一个动态、实时、高性能的开源 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。
\\n而 Kubernetes 作为自动部署、扩展和管理容器化应用程序的开源系统,旨在为用户提供跨主机集群的自动部署、扩展以及运行应用程序容器等相关功能支持。如何快速地在 K8s 中部署 Apache APISIX 并通过 Dashboard 进行相关信息的展示,这里我们为大家整理了两种非常容易上手的安装思路。
\\n在正式进入安装部署前,确保网络畅通并准备好相应的 K8s 集群。
\\n在这里,我们推荐使用 Kind 进行本地搭建 K8s 集群测试环境,非常方便且容易上手。根据官方文档步骤安装好 Kind 后,只需一条指令即可搭建好 K8s 集群环境。
\\nkind create cluster\\n
\\nHelm 主要用于管理 Kubernetes 中的应用程序。类似 apt、yum、pacman 这些 Linux 中的包管理器,所以 Helm 也称为 Kubernetes 中的包管理器。
\\n目前 Apache APISIX 已经提供了 Helm Chart 仓库,用户可以非常方便地通过 Helm 来部署和卸载 Apache APISIX。
\\n首先添加 Apache APISIX Helm Chart 地址并更新仓库。
\\nhelm repo add apisix https://charts.apiseven.com\\nhelm repo update\\n
\\n进行安装 Apache APISIX(此处演示是将 Apache APISIX 安装到 Default Namespace,如需自定义 Namespace,可参考相关文档)。
\\nhelm install apisix apisix/apisix\\n
\\n上述指令执行成功后,会得到如下返回信息:
\\n▶ helm install apisix apisix/apisix\\nNAME: apisix\\nLAST DEPLOYED: Sun Dec 5 14:43:19 2021\\nNAMESPACE: default\\nSTATUS: deployed\\nREVISION: 1\\nTEST SUITE: None\\nNOTES:\\n1. Get the application URL by running these commands:\\n export NODE_PORT=$(kubectl get --namespace default -o jsonpath=\\"{.spec.ports[0].nodePort}\\" services apisix-gateway)\\n export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath=\\"{.items[0].status.addresses[0].address}\\")\\n echo http://$NODE_IP:$NODE_PORT\\n
\\n通过上述方式安装部署的 Apache APISIX,Admin API 会暴露在集群中 9180
端口,Gateway 暴露在 80
端口。如果要访问 Admin API,可以使用 kubectl port-forward
将端口转发到本地主机上的端口。
这里演示的是转发到本机 9080
端口情况,主要是为了和 Apache APISIX 官方文档同步,方便后续验证。
kubectl port-forward service/apisix-admin 9080:9180\\n
\\n之后可参考 Apache APISIX 快速入门指南,进行 Upstream 的添加与绑定 Route 等相关操作。
\\n最后进行新建路由的验证环节。
\\n由于在本文演示中使用了 Kind 来搭建本地 K8s 集群,apisix-gateway
的 NodePort 访问不了,所以在验证之前还需要额外一步,即将集群中的 80
端口转发到本机 8080
端口。
kubectl port-forward service/apisix-gateway 8080:80\\n
\\n开始进行验证。
\\ncurl -X GET \\"http://127.0.0.1:8080/get?foo1=bar1&foo2=bar2\\" -H \\"Host: httpbin.org\\"\\n
\\n期望的返回结果可以参考下方示例。
\\n{\\n \\"args\\": {\\n \\"foo1\\": \\"bar1\\",\\n \\"foo2\\": \\"bar2\\"\\n },\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Accept-Encoding\\": \\"gzip\\",\\n \\"Host\\": \\"httpbin.org\\",\\n \\"User-Agent\\": \\"curl/7.64.1\\",\\n \\"X-Amzn-Trace-Id\\": \\"Root=1-61ac63b5-348d3c5567db393462cd0666\\",\\n \\"X-Forwarded-Host\\": \\"httpbin.org\\"\\n },\\n \\"origin\\": \\"127.0.0.1, 192.46.208.201\\",\\n \\"url\\": \\"http://httpbin.org/get?foo1=bar1&foo2=bar2\\"\\n}\\n
\\n与部署 Apache APISIX 一样,通过 Helm 安装 Apache APISIX-Dashboard 也只需执行一条指令。
\\nhelm install apisix-dashboard apisix/apisix-dashboard\\n
\\n接下来转发 Dashboard 端口到本机。
\\nkubectl port-forward service/apisix-dashboard 8080:80\\n
\\n最后访问本地 localhost:8080
就可以看到登录页面了。
注意:这里部署出来的 Apache APISIX-Dashboard 系统信息中不会出现 Apache APISIX 的节点信息。因为通过 Helm 方式进行安装的话默认是没有启用 server-info
插件,如有需要可在 apisix 的configmap 中自行添加。server-info
的配置可参考相关文档。
相较于上述 Helm 方式的部署,使用 yaml 文件来部署 Apache APISIX,可以更加方便地进行自定义配置。
\\n注意:如果已经使用方式一部署过,在进行下述安装前需要先清除 ETCD 的 PVC 存储以方便后续操作。
\\n这里我们已经整理好了在部署 Apache APISIX、APISIX-Dashboard 及 etcd 集群时需要用到的 yaml 文件,大家可通过 apisix-on-kubernetes 仓库进行调用接下来提到的相关文件。
\\n首先克隆上述提到的 apisix-on-kubernetes
仓库。
git clone https://github.com/zaunist/apisix-on-kubernetes.git\\n
\\n然后执行以下命令。
\\nkubectl apply -f etcd.yaml\\nkubectl apply -f apisix.yaml\\nkubectl apply -f apisix-dashboard.yaml\\n
\\n等待 Pod 全部启动,将 apisix-dashboard
端口转发到本机。
kubectl port-forward service/apisix-dashboard 8080:80\\n
\\n最后访问 localhost:8080
,即可查看 Dashboard 相关信息。默认登录账号密码为 admin
、admin
。
提示:在安装过程中为了更直观地看到部署情况,可以尝试利用 Kubernetes Dashboard 在网页端查看 Pod 的运行情况。
\\n本文介绍了两种在 Kubernetes 中部署 Apache APISIX 和 Apache APISIX-Dashboard 的方式。两种方式的最终目的都是一样的,但在使用过程中也各有各的优势。
\\n比如使用 Helm 进行安装非常方便,仅需几条指令就可执行所有操作;通过 YAML 文件部署则比较方便地进行相关自定义配置的修改,更具有可操控性。
\\n具体在实际场景中如何进行 Apache APISIX 的安装与部署,还要看大家的使用习惯,这里也仅为大家提供了两种思路进行参考。希望各位在后续使用 Apache APISIX 过程中可以开发出更多有趣的技巧和方法。
\\n","description":"Apache APISIX 是一个动态、实时、高性能的开源 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。 而 Kubernetes 作为自动部署、扩展和管理容器化应用程序的开源系统,旨在为用户提供跨主机集群的自动部署、扩展以及运行应用程序容器等相关功能支持。如何快速地在 K8s 中部署 Apache APISIX 并通过 Dashboard 进行相关信息的展示,这里我们为大家整理了两种非常容易上手的安装思路。\\n\\n环境准备\\n\\n在正式进入安装部署前,确保网络畅通并准备好相应的 K8s 集群。\\n\\n在这里…","guid":"https://www.apiseven.com/blog/how-to-deploy-apisix-in-kubernetes","author":"喻柏仲","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-14T16:00:00.211Z","media":null,"categories":null,"attachments":null,"extra":null,"language":null},{"title":"使用 Prometheus 监控 APISIX Ingress Controller","url":"https://www.apiseven.com/blog/monitor-apisix-ingress-controller-with-prometheus","content":"无论是之前单体应用的时代,或是云原生大行其道的今天,「监控功能」一直扮演着十分重要的角色。一个良好的监控体系能够帮助工程师们快速了解运行在生产环境中的服务状态,并在服务异常时快速定位问题或者提前预警异常的发生。
\\nApache APISIX Ingress Controller 在最近几个版本中加强了对 Prometheus Metrics 的支持。本文将为大家介绍如何使用 Prometheus 收集 APISIX Ingress Controller 的 Metrics 数据,并通过 Grafana 进行后续可视化呈现。
\\n首先我们通过 Helm 将 Apache APISIX、ETCD 和 APISIX Ingress Controller 部署到本地的 Kubernetes 集群中。
\\nhelm repo add apisix https://charts.apiseven.com\\nhelm repo update\\nkubectl create namespace ingress-apisix\\nhelm install apisix apisix/apisix --namespace ingress-apisix \\\\\\n --set ingress-controller.enabled=true\\n
\\n安装完毕后请等待,直至所有服务都已正常运行。具体状态确认可通过下述命令进行检查。
\\nkubectl get all -n ingress-apisix\\n
\\n大部分情况下,监控功能的涉及面肯定不止 APISIX Ingress Controller 这一个组件,如果需要同时监控 Apache APISIX,可以创建以下 ApisixClusterConfig
资源。
apiVersion: apisix.apache.org/v2alpha1\\nkind: ApisixClusterConfig\\nmetadata:\\n name: default\\nspec:\\n monitoring:\\n prometheus:\\n enable: true\\n
\\n接下来我们将通过 Prometheus Operator 来启用 Prometheus 服务,因此需要先安装 Prometheus Operator(下述命令同时也会安装 Grafana)。
\\nhelm repo add prometheus-community https://prometheus-community.github.io/helm-charts\\nheml repo update\\nkubectl create namespace prometheus\\nhelm install prometheus prometheus-community/kube-prometheus-stack -n prometheus\\n
\\n安装完毕后,需要准备 Prometheus 实例的 RBAC 配置。该配置可赋予 Prometheus 实例向 Kubernetes API Server 获取 Pod 和 Service 资源的能力。
\\napiVersion: v1\\nkind: ServiceAccount\\nmetadata:\\n name: ingress-apisix\\n namespace: ingress-apisix\\n---\\napiVersion: rbac.authorization.k8s.io/v1\\nkind: ClusterRole\\nmetadata:\\n name: ingress-apisix\\nrules:\\n- apiGroups: [\\"\\"]\\n resources:\\n - nodes\\n - nodes/metrics\\n - services\\n - endpoints\\n - pods\\n verbs: [\\"get\\", \\"list\\", \\"watch\\"]\\n- apiGroups: [\\"\\"]\\n resources:\\n - configmaps\\n verbs: [\\"get\\"]\\n- apiGroups:\\n - networking.k8s.io\\n resources:\\n - ingresses\\n verbs: [\\"get\\", \\"list\\", \\"watch\\"]\\n- nonResourceURLs: [\\"/metrics\\"]\\n verbs: [\\"get\\"]\\n---\\napiVersion: rbac.authorization.k8s.io/v1\\nkind: ClusterRoleBinding\\nmetadata:\\n name: ingress-apisix\\nroleRef:\\n apiGroup: rbac.authorization.k8s.io\\n kind: ClusterRole\\n name: ingress-apisix\\nsubjects:\\n- kind: ServiceAccount\\n name: ingress-apisix\\n namespace: ingress-apisix\\n
\\n完成上述实例配置后,需要定义 PodMonitor,也可以根据场景需求选择使用 ServiceMonior。下述 PodMonitor 资源将聚焦于 APISIX Ingress Controller Pod 的 Metrics 收集。
\\napiVersion: monitoring.coreos.com/v1\\nkind: PodMonitor\\nmetadata:\\n name: ingress-apisix\\n namespace: ingress-apisix\\n labels:\\n use-for: ingress-apisix\\nspec:\\n selector:\\n matchLabels:\\n app.kubernetes.io/name: ingress-controller\\n podMetricsEndpoints:\\n - port: http\\n
\\n\\n\\n这里不使用 ServiceMonitor 的原因是
\\nhttp
这一端口没有暴露到 Service 级别。
最后可通过下述指令进行 Prometheus 实例的定义。
\\napiVersion: monitoring.coreos.com/v1\\nkind: Prometheus\\nmetadata:\\n name: ingress-apisix\\n namespace: ingress-apisix\\nspec:\\n serviceAccountName: ingress-apisix\\n podMonitorSelector:\\n matchLabels:\\n use-for: ingress-apisix\\n resources:\\n requests:\\n memory: 400Mi\\n enableAdminAPI: false\\n image: prom/prometheus:v2.31.0\\n
\\n将上述资源全部应用到 Kubernetes 集群后,等待相关组件就绪。
\\n接下来我们通过配置 Grafana 进行可视化呈现。
\\n首先访问 prometheus-grafana
服务。注意,如果没有暴露 Service 到集群外部的手段,可以尝试使用端口转发的方式,Grafana 的管理员用户名和密码保存在 prometheus-grafana
这一 Secret 中。
打开 Grafana 后,导入 APISIX Ingress Controller 的 Dashboard 模版即可看到监控大盘,效果图如下:
\\n\\n创建 Dashboard 模版可参考相关 PR。
目前 APISIX Ingress Controller 的监控指标聚焦于它和数据面 Apache APISIX 实例的交互(配置下发)上,包括配置同步的数量与延迟等相关数据。
\\nis_leader
:当前 APISIX Ingress Controller 实例是否为 Leader 角色。同一组 APISIX Ingress Controller 只会有一个 Leader,其余实例均为 Candidate。sync_operations
:包括 APISIX Ingress Controller 向数据面同步配置时的一些指标,包括推送次数、失败率、延迟等。通过这类指标可以监控配置下发是否正常,以此来帮助研发和运维同学进行监控预警和故障定位。本文介绍了如何使用 Prometheus 监控 APISIX Ingress Controller 的相关步骤和部分指标的展示效果。目前只包含了一些基本的监控指标,我们会在后续继续进行打磨和升级,增加更多的指标项和集成数据面 APISIX 的指标,为大家带来更好的监控体验。
\\n当然也欢迎感兴趣的朋友参与 Apache APISIX Ingress Controller 项目的代码贡献中来,期待我们一起将 APISIX Ingress Controller 打造地更加全面化。
\\n","description":"无论是之前单体应用的时代,或是云原生大行其道的今天,「监控功能」一直扮演着十分重要的角色。一个良好的监控体系能够帮助工程师们快速了解运行在生产环境中的服务状态,并在服务异常时快速定位问题或者提前预警异常的发生。 Apache APISIX Ingress Controller 在最近几个版本中加强了对 Prometheus Metrics 的支持。本文将为大家介绍如何使用 Prometheus 收集 APISIX Ingress Controller 的 Metrics 数据,并通过 Grafana 进行后续可视化呈现。\\n\\n步骤一:安装 APISIX…","guid":"https://www.apiseven.com/blog/monitor-apisix-ingress-controller-with-prometheus","author":"张超","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-13T16:00:00.044Z","media":[{"url":"https://static.apiseven.com/202108/1639381275740-d9e3b2a7-6895-43f2-8119-212ea616dddd.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639381348652-7fb30365-179c-4b68-a168-ec3c9da7324d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639381376926-d6af92c7-16dd-4306-8931-9b83e7e8dce1.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Apache APISIX 集成 Kafka 实现高效率实时日志监控","url":"https://www.apiseven.com/blog/integrate-kafka-with-apache-apisix","content":"Apache Kafka 是由 Apache 管理的开源流处理平台,由 Scala 和 Java 编写,为处理实时数据提供了统一、高吞吐、低延迟的功能特性。
\\n其持久化层本质上是一个“按照分布式事务日志架构的大规模发布/订阅消息队列”,这使它作为企业级基础设施来处理流式数据非常有价值。目前已被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型应用程序等领域。
\\nApache APISIX 早在 1.2 版本开始就已经提供了 kafka-logger
插件的支持,其后又经过多次功能强化,目前已具备非常成熟且完善的功能。支持将 API 请求日志,甚至请求体和响应体以 JSON 格式推送至 Kafka 集群中。
使用 kafka-logger
时,用户可以发送多种数据并自定义发送的日志格式,同时还支持以批处理的方式打包发送日志或进行自动重试等功能。
本文示例只演示了一种启动方式,其他启动方式细节可参考 Kafka 官方文档。
\\n# 使用 docker-compose 启动一个具有 1个 zookeeper 节点、3个 kafka 节点的集群\\n# 同时还启动一个 EFAK 用于数据监控。\\nversion: \'3\'\\n\\nservices:\\n zookeeper:\\n image: confluentinc/cp-zookeeper:6.2.1\\n hostname: zookeeper\\n ports:\\n - \\"2181:2181\\"\\n environment:\\n ZOOKEEPER_CLIENT_PORT: 2181\\n ZOOKEEPER_SERVER_ID: 1\\n ZOOKEEPER_SERVERS: zookeeper:2888:3888\\n\\n kafka1:\\n image: confluentinc/cp-kafka:6.2.1\\n hostname: kafka1\\n ports:\\n - \\"9092:9092\\"\\n environment:\\n KAFKA_ADVERTISED_LISTENERS: LISTENER_DOCKER_INTERNAL://kafka1:19092,LISTENER_DOCKER_EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092\\n KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: LISTENER_DOCKER_INTERNAL:PLAINTEXT,LISTENER_DOCKER_EXTERNAL:PLAINTEXT\\n KAFKA_INTER_BROKER_LISTENER_NAME: LISTENER_DOCKER_INTERNAL\\n KAFKA_ZOOKEEPER_CONNECT: \\"zookeeper:2181\\"\\n KAFKA_BROKER_ID: 1\\n KAFKA_LOG4J_LOGGERS: \\"kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO\\"\\n depends_on:\\n - zookeeper\\n\\n kafka2:\\n image: confluentinc/cp-kafka:6.2.1\\n hostname: kafka2\\n ports:\\n - \\"9093:9093\\"\\n environment:\\n KAFKA_ADVERTISED_LISTENERS: LISTENER_DOCKER_INTERNAL://kafka2:19093,LISTENER_DOCKER_EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9093\\n KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: LISTENER_DOCKER_INTERNAL:PLAINTEXT,LISTENER_DOCKER_EXTERNAL:PLAINTEXT\\n KAFKA_INTER_BROKER_LISTENER_NAME: LISTENER_DOCKER_INTERNAL\\n KAFKA_ZOOKEEPER_CONNECT: \\"zookeeper:2181\\"\\n KAFKA_BROKER_ID: 2\\n KAFKA_LOG4J_LOGGERS: \\"kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO\\"\\n depends_on:\\n - zookeeper\\n\\n\\n kafka3:\\n image: confluentinc/cp-kafka:6.2.1\\n hostname: kafka3\\n ports:\\n - \\"9094:9094\\"\\n environment:\\n KAFKA_ADVERTISED_LISTENERS: LISTENER_DOCKER_INTERNAL://kafka3:19094,LISTENER_DOCKER_EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9094\\n KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: LISTENER_DOCKER_INTERNAL:PLAINTEXT,LISTENER_DOCKER_EXTERNAL:PLAINTEXT\\n KAFKA_INTER_BROKER_LISTENER_NAME: LISTENER_DOCKER_INTERNAL\\n KAFKA_ZOOKEEPER_CONNECT: \\"zookeeper:2181\\"\\n KAFKA_BROKER_ID: 3\\n KAFKA_LOG4J_LOGGERS: \\"kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO\\"\\n depends_on:\\n - zookeeper\\n\\n efak:\\n image: nickzurich/kafka-eagle:2.0.9\\n hostname: efak\\n ports:\\n - \\"8048:8048\\"\\n depends_on:\\n - kafka1\\n - kafka2\\n - kafka3\\n
\\n接下来我们创建 test Topic
用于收集日志。
通过下方命令可进行路由创建与 kafka-logger
插件的开启。
curl -XPUT \'http://127.0.0.1:9080/apisix/admin/routes/r1\' \\\\\\n--header \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' \\\\\\n--header \'Content-Type: application/json\' \\\\\\n--data-raw \'{\\n \\"uri\\": \\"/*\\",\\n \\"plugins\\": {\\n \\"kafka-logger\\": {\\n \\"batch_max_size\\": 1,\\n \\"broker_list\\": {\\n \\"127.0.0.1\\": 9092\\n },\\n \\"disable\\": false,\\n \\"kafka_topic\\": \\"test\\",\\n \\"producer_type\\": \\"sync\\"\\n }\\n },\\n \\"upstream\\": {\\n \\"nodes\\": {\\n \\"httpbin.org:80\\": 1\\n },\\n \\"type\\": \\"roundrobin\\"\\n }\\n}\'\\n
\\n上述代码中配置了 kafka broker
地址、目标 Topic、同步的生产模式和每一批次包含的最大日志数量。这里我们可以先将 batch_max_size
设置为 1,即每产生一条日志就向 Kafka 写入一条消息。
通过上述设置,就可以实现将 /*
路径下的 API 请求日志发送至 Kafka 的功能。
接下来我们通过 API 发送一些请求,并记录下请求次数。
\\n# 向 API 发送 10 次请求\\ncurl http://127.0.0.1:9080/get\\n
\\n通过下图可以看到,有一些日志消息已经被写入到我们创建的 test topic
2 中。点击查看日志内容,可以发现上述进行的 API 请求日志已经被写入了。
当然,在使用过程中我们也可以通过 kafka-logger
插件提供的元数据配置,来设置发送至 Kafka 的日志数据结构。通过设置 log_format
数据,可以控制发送的数据类型。
比如以下数据中的 $host
、$time_iso8601
等,都是来自于 Nginx 提供的内置变量;也支持如 $route_id
和 $service_id
等 Apache APISIX 提供的变量配置。
curl -XPUT \'http://127.0.0.1:9080/apisix/admin/plugin_metadata/kafka-logger\' \\\\\\n--header \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' \\\\\\n--header \'Content-Type: application/json\' \\\\\\n--data-raw \'{\\n \\"log_format\\": {\\n \\"host\\": \\"$host\\",\\n \\"@timestamp\\": \\"$time_iso8601\\",\\n \\"client_ip\\": \\"$remote_addr\\",\\n \\"route_id\\": \\"$route_id\\"\\n }\\n}\'\\n
\\n通过发送请求进行简单测试,可以看到上述日志结构设置已生效。目前 Apache APISIX 提供多种日志格式模板,在配置上具有极大的灵活性,更多日志格式细节可参考 Apache APISIX 官方文档。
\\n如使用完毕,只需移除路由配置中 kafka-logger
插件相关配置并保存,即可关闭路由上的插件。得益于 Apache APISIX 的动态化优势,开启关闭插件的过程都不需要重启 Apache APISIX,十分方便。
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"methods\\": [\\"GET\\"],\\n \\"uri\\": \\"/hello\\",\\n \\"plugins\\": {},\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n }\\n }\\n}\'\\n
\\n本文为大家介绍了关于 kafka-logger 插件的功能前瞻与使用步骤,更多关于 kafka-logger 插件说明和完整配置列表,可以参考官方文档。
\\n也欢迎随时在 GitHub Discussions 中发起讨论,或通过邮件列表进行交流。
\\n","description":"Apache Kafka 是由 Apache 管理的开源流处理平台,由 Scala 和 Java 编写,为处理实时数据提供了统一、高吞吐、低延迟的功能特性。 其持久化层本质上是一个“按照分布式事务日志架构的大规模发布/订阅消息队列”,这使它作为企业级基础设施来处理流式数据非常有价值。目前已被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型应用程序等领域。\\n\\n实现方式:kafka-logger\\n\\nApache APISIX 早在 1.2 版本开始就已经提供了 kafka-logger 插件的支持,其后又经过多次功能强化,目前已具备非常成熟且完善的功能…","guid":"https://www.apiseven.com/blog/integrate-kafka-with-apache-apisix","author":"白泽平","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-09T16:00:00.466Z","media":[{"url":"https://static.apiseven.com/202108/1642390784736-562187ed-ade9-4a2f-96e1-c79556f9dd7d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1642390828394-721eccfa-ab02-4f8f-a0d8-8039e0eaabc1.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1642390874028-89683dfb-ab16-48cd-92de-496cc60df3b5.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1642390899127-d1eb560a-499e-4a9f-9227-4063ba711e2d.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"如何在 Apache APISIX 中集成 Keycloak 实现身份认证","url":"https://www.apiseven.com/blog/integrate-keycloak-auth-in-apisix","content":"Keycloak 是一个针对现代应用程序和服务的开源身份和访问管理解决方案。Keycloak 支持单点登录(Single-Sign On),因此服务可以通过 OpenID Connect、OAuth 2.0 等协议对接 Keycloak。同时 Keycloak 也支持集成不同的身份认证服务,例如 Github、Google 和 Facebook 等。
\\n另外 Keycloak 也支持用户联邦功能,可以通过 LDAP 或 Kerberos 来导入用户。更多 Keycloak 内容可以参考官方文档介绍。
\\n在进行如下步骤前,请确保环境中已启动 Apache APISIX。
\\n这里我们使用 docker-compose
将 Keycloak 与其所依赖的的 PostgreSQL 一并启动。
version: \'3.7\'\\n\\nservices:\\n postgres:\\n image: postgres:12.2\\n container_name: postgres\\n environment:\\n POSTGRES_DB: keycloak\\n POSTGRES_USER: keycloak\\n POSTGRES_PASSWORD: password\\n\\n keycloak:\\n image: jboss/keycloak:9.0.2\\n container_name: keycloak\\n environment:\\n DB_VENDOR: POSTGRES\\n DB_ADDR: postgres\\n DB_DATABASE: keycloak\\n DB_USER: keycloak\\n DB_PASSWORD: password\\n KEYCLOAK_USER: admin\\n KEYCLOAK_PASSWORD: password\\n PROXY_ADDRESS_FORWARDING: \\"true\\"\\n ports:\\n - 8080:8080\\n depends_on:\\n - postgres\\n
\\ndocker-compose up\\n
\\n执行完毕后需要确认 Keycloak 和 PostgreSQL 是否已成功启动。
\\ndocker-compose ps\\n
\\nKeycloak 启动完成之后,使用浏览器访问 \\"http://127.0.0.1:8080/auth/admin/\\",并键入 admin/password
账号密码进行登录管理员控制台。
首先,创建一个名称为 apisix_test_realm
的 realm
。在 Keycloak 中,realm
是一个专门用来管理项目的工作区,不同 realm
之间的资源是相互隔离的。
Keycloak 中 realm
分为两类:一类是 master realm
,由 Keycloak 刚启动时创建,用于管理 admin 账号以及创建其他的 realm
。第二类是 other realm
,由 master realm
中的 admin 创建,可以在该 realm
中进行用户和应用的创建并进行管理和使用。更多细节可参考 Keycloak 中 realm 和 users 相关内容。
接下来需要创建 OpenID Connect Client
。在 Keycloak 中,Client 表示允许向 Keycloak 发起身份认证的客户端。
在本示例场景中,Apache APISIX
相当于一个客户端,负责向 Keycloak 发起身份认证请求,因此我们创建一个名称为 apisix
的 Client。关于 Client 更多细节可参考 Keycloak OIDC Clients。
Client 创建完成后,需要为 Client 配置 Apache APISIX 的访问类型。
\\n在 Keycloak 中 Access Type
分为三类:
client secret
来获取 access token
, 多运用于服务端渲染的 web 系统。bearer token
访问,多运用于 RESTful API 的使用场景。更多关于 Client 设置细节可参考 Keycloak OIDC Clients 高级设置。
\\n因为我们使用了 Apache APISIX 作为服务端的 Client, 因此可以选择类型一或类型三(这里以类型一为例进行演示)。
\\nKeycloak 支持对接其他第三方的用户系统,例如 Google 和 Facebook。或者使用 LDAP 的方式进行导入或手动创建用户,这里我们使用「手动创建用户」来进行演示。
\\n在 Credentials 页面设置用户的密码。
\\nKeycloak 配置完成后,需要在 Apache APISIX 中创建路由并开启 Openid-Connect
插件,具体关于该插件的配置文档可以参考 Apache APISIX OpenID-Connect 插件。
上图配置中:
\\nclient_id
为之前创建 Client 时使用的名称,即 apisix
;client_secret
则需要进入 Clients-apisix-Credentials 中获取,例如:d5c42c50-3e71-4bbe-aa9e-31083ab29da4
。进入 Realm Settings-General-Endpoints 中,选择 OpenID Endpoint Configuration
链接,复制该链接指向的地址。例如:http://127.0.0.1:8080/auth/realms/apisix_test_realm/.well-known/openid-configuration
。
使用如下命令访问 Apache APISIX Admin 接口来创建一条路由,设置上游为 httpbin.org
,并开启插件 OpenID Connect 用于身份认证。
\\n\\n注意:如果创建 Client 时,选择
\\nbearer-only
作为Access Type
,在配置路由是需要将bearer_only
设置为 true,此时访问 Apache APISIX 将不会跳转到 Keycloak 登录界面。
curl -XPOST 127.0.0.1:9080/apisix/admin/routes -H \\"X-Api-Key: edd1c9f034335f136f87ad84b625c8f1\\" -d \'{\\n \\"uri\\":\\"/*\\",\\n \\"plugins\\":{\\n \\"openid-connect\\":{\\n \\"client_id\\":\\"apisix\\",\\n \\"client_secret\\":\\"d5c42c50-3e71-4bbe-aa9e-31083ab29da4\\",\\n \\"discovery\\":\\"http://127.0.0.1:8080/auth/realms/apisix_test_realm/.well-known/openid-configuration\\",\\n \\"scope\\":\\"openid profile\\",\\n \\"bearer_only\\":false,\\n \\"realm\\":\\"apisix_test_realm\\",\\n \\"introspection_endpoint_auth_method\\":\\"client_secret_post\\",\\n \\"redirect_uri\\":\\"http://127.0.0.1:9080/\\"\\n }\\n },\\n \\"upstream\\":{\\n \\"type\\":\\"roundrobin\\",\\n \\"nodes\\":{\\n \\"httpbin.org:80\\":1\\n }\\n }\\n}\'\\n
\\n上述配置完成后,我们就可以在 Apache APISIX 中进行相关的测试访问了。
\\n使用浏览器访问 http://127.0.0.1:9080/image/png
。
由于开启了 OpenID-Connect 插件,并且设置了 bearer-only
为 false
。因此第一次访问该路径时, Apache APISIX 将重定向到 Keycloak 中 apisix_test_realm
中配置的登录界面,进行用户登录请求。
输入之前配置 Keycloak 时创建的 User peter,即可完成用户登录。
\\n登录成功后,浏览器又会将链接重定向到 \\"http://127.0.0.1:9080/image/png\\"。并成功访问到该图片内容,该内容与上游 \\"http://httpbin.org/image/png\\" 一致。
\\n测试完毕后,使用浏览器访问 \\"http:/127.0.0.1:9080/logout\\" 进行账号登出。
\\n\\n\\n注意:登出路径可通过 OpenID-Connect 插件配置中的
\\nlogout_path
指定,默认为logout
。
本文通过详细的步骤为大家展示了如何在 Apache APISIX 使用 OpenID-Connect 协议和 Keycloak 进行身份认证。通过对接 Keycloak,Apache APISIX 仅需通过配置即可实现对使用者和应用服务进行认证与鉴权,从而大大减少了相关开发工作。
\\n更多关于 Apache APISIX 中的身份认证功能实现也可参考文章《使用 Apache APISIX 和 Okta 来实现集中式身份认证》。
\\n","description":"什么是 Keycloak Keycloak 是一个针对现代应用程序和服务的开源身份和访问管理解决方案。Keycloak 支持单点登录(Single-Sign On),因此服务可以通过 OpenID Connect、OAuth 2.0 等协议对接 Keycloak。同时 Keycloak 也支持集成不同的身份认证服务,例如 Github、Google 和 Facebook 等。\\n\\n另外 Keycloak 也支持用户联邦功能,可以通过 LDAP 或 Kerberos 来导入用户。更多 Keycloak 内容可以参考官方文档介绍。\\n\\n如何使用\\n环境准备\\n\\n在进行如下…","guid":"https://www.apiseven.com/blog/integrate-keycloak-auth-in-apisix","author":"朱欣欣","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-09T16:00:00.425Z","media":[{"url":"https://static.apiseven.com/202108/1639101202459-72803240-b358-4c69-a9ca-4b6751a8547d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101243617-0498379f-392e-4837-8f37-eee558c21e3d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101288379-9a46b92a-294e-4b40-ac7e-408284a3d0ad.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101327347-c8ab463a-1cb0-4eb0-a26f-17d7c0c54846.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101355171-e368730b-2a72-4c4d-9397-cf4a1c8f2806.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101385277-b2f578c0-e68a-4945-83ac-7a77145bb056.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101406281-724bbb50-96fc-4aa8-aec1-9414f83c199d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101430209-d289459a-5014-4a2d-864f-7917b84b1c0c.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101454807-ff8c8b77-bdac-4ac6-966e-a2f5e2418b7a.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101585273-7eb31728-fe4c-4af3-84d1-76c1a97e7e35.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101623370-cc668e0f-0c2c-469c-9a3e-3118c271d63f.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639101644015-6d541202-dfff-4de3-ad47-f49dd65911a6.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"强强联合!APISIX 集成 SkyWalking 打造全方位日志处理","url":"https://www.apiseven.com/blog/apisix-integrate-skywalking-plugin","content":"在可观测性领域,通常采用 Metrics、Logger 与 Tracing 三大方向的数据收集与分析,以达到洞察应用运行状态的目的,Apache SkyWalking 的日志处理正好具备了以上三方面。
\\nApache APISIX 早在 1.4 版本就已经集成 Apache SkyWaling Tracing 能力,并在后续版本中加入了错误日志和访问日志收集等功能。如今随着 Apache SkyWalking 对 Metrics 的支持,能够帮助 Apache APISIX 在集成模式下实现一站式可观测方案,同时覆盖到日志、度量和调用追踪。
\\n熟悉 Apache APISIX 的小伙伴应该知道,Apache APISIX 在运行中会产出两种日志,即访问日志和错误日志。
\\n访问日志记录着每个请求的详细信息,属于请求范围内产生的日志,因此可以直接与 Tracing 关联。而错误日志则是 Apache APISIX 运行时产出日志信息,是整个应用级别日志,但无法确保能百分百关联到请求上。
\\n目前 Apache APISIX 提供了非常丰富的日志处理插件,包括 TCP/HTTP/Kafka 等收集上报插件,但它们与 Tracing 关联都比较弱。以 Apache SkyWalking 为例,提取 Apache APISIX 端日志记录中的 SkyWalking Tracing Conetxt Header 并输出到文件系统,之后利用日志处理框架(fluentbit)将日志转成 SkyWalking 可接受的日志格式。后续从中解析提取 Tracing Context,从而获得 Tracing ID 进而与 Trace 建立联系。
\\n显然,上述方式处理流程比较繁琐复杂,还需要额外转换日志格式。为此,在 PR#5500 中我们实现了将 Apache SkyWalking 访问日志接入 Apache APISIX 插件生态,方便用户在使用 Apache APISIX 中更方便地利用 Apache SkyWalking 进行收集和处理相关日志。
\\nSkyWalking Logger 插件能够解析 SkyWalking Tracing Context Header,并将相关 Tracing Context 信息打印到日志中,从而实现日志与调用链建立关联。
\\n通过使用此插件,可以实现在下游已经集成 Apache SkyWalking 的情况下,Apache APISIX 即便没有打开 SkyWalking Tracing 插件也能获取到 SkyWalking Tracing Context 并实现与 Tracing 关联。
\\n\\n\\n上图 Content 为日志内容,这里使用了 Apache APISIX metadata 配置来收集 Request 相关信息。后续可通过 Plugin Metadata 修改 Log Format 定制日志内容,具体可以参考官方文档。
\\n
在使用该插件时,由于 SkyWalking 插件默认为「不开启」,所以需要手动修改 conf/default-apisix.yaml
文件中 plugins
章节来解开SkyWalking 注释从而启用插件。
plugins:\\n ...\\n - skywalking\\n ...\\n
\\n之后便可使用 SkyWalking Tracing 插件直接得到 Tracing 数据,以便接下来验证 Logging 插件相关功能是否能够正常开启与工作。
\\n接下来创建一个路由,并绑定 SkyWalking Tracing 插件和 SkyWalking Logging 插件。关于插件具体配置细节可以参考 Apache APISIX 官方文档,这里不再赘述。
\\ncurl -X PUT \'http://192.168.0.108:9080/apisix/admin/routes/1001\' \\\\\\n-H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' \\\\\\n-H \'Content-Type: application/json\' \\\\\\n-d \'{\\n \\"uri\\": \\"/get\\",\\n \\"plugins\\": {\\n \\"skywalking\\": {\\n \\"sample_ratio\\": 1\\n },\\n \\"skywalking-logger\\": {\\n \\"endpoint_addr\\": \\"http://127.0.0.1:12800\\"\\n }\\n },\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"httpbin.org:80\\": 1\\n }\\n }\\n}\'\\n
\\n在 Apache SkyWalking 侧,可以使用 LAL(Logger Analysis Language)脚本进行日志处理,比如 Tag 提取、SkyWalking 元数据修正等。
\\n这里进行 Tag 提取主要是为了后续检索方便,以及在 Metrics 统计时添加相关依赖。可使用如下代码进行 SkyWalking LAL 脚本配置来完成 Tag 提取,更多关于 SkyWalking LAL 脚本使用方法可以参考 Apache SkyWalking 官方文档。
\\n# The default LAL script to save all logs, behaving like the versions before 8.5.0.\\nrules:\\n - name: default\\n dsl: |\\n filter {\\n json {\\n abortOnFailure false\\n }\\n\\n extractor {\\n tag routeId: parsed.route_id\\n tag upstream: parsed.upstream\\n tag clientIp: parsed.client_ip\\n tag latency: parsed.latency\\n }\\n\\n sink {\\n }\\n }\\n
\\n在 SkyWalking OAP Server 配置上述 LAL 脚本后将显示如下日志:
\\n展开日志详情如下:
\\n通过上述操作可以看到,将 routeId
,upstream
和 clientIp
以键值对形式展示,比在日志正文中直接查找要方便许多,还能用于 MAL 统计生成相关的度量指标。
目前 error-log-logger 插件已支持 SkyWalking 日志格式,现在可以使用 error-log-logger 插件将 Apache APISIX 错误日志快捷接入到 Apache SkyWalking 中。目前,错误日志还无法获取 SkyWalking Tracing Context 信息,因此无法直接与 SkyWalking Tracing 产生关联。
\\n关于 Error Log 接入 SkyWalking 主要是为了能集中管理 Apache APISIX 的日志数据,同时也方便在 SkyWalking 内查看所有可观测性数据。
\\n由于 error-log-logger 插件默认「不开启」,所以仍需要上文中提到的方法进行插件开启。
\\nplugins:\\n ...\\n - error-log-logger\\n ...\\n
\\n启用之后,需要将插件绑定到路由或者 global rules
上,这里我们以「绑定路由」为例。
curl -X PUT \'http://192.168.0.108:9080/apisix/admin/plugin_metadata/error-log-logger\' \\\\\\n-H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' \\\\\\n-H \'Content-Type: application/json\' \\\\\\n-d \'{\\n \\"inactive_timeout\\": 10,\\n \\"level\\": \\"ERROR\\",\\n \\"skywalking\\": {\\n \\"endpoint_addr\\": \\"http://127.0.0.1:12800/v3/logs\\"\\n }\\n}\'\\n
\\n\\n\\n注意这里
\\nendpoint_addr
是 SkyWalking OAP Server 地址,需要带上 URI(即/v3/logs
)。
与 Access Log 处理方式基本一样,日志在送达 SkyWalking OAP Server 时,同样会经过 LAL 处理。因此,我们依然可以使用 SkyWalking LAL 脚本来分析处理日志信息。
\\n需要注意的是,Error Log 日志消息体使用文本格式。如果进行 Tags 提取,则需要使用正则表达式来完成。与 Access Log 处理消息正文的方式略有不同,Acces Log 使用 JSON 格式,可以直接使用 JSON 解析后引用 JSON 对象的字段,其他处理流程则大体一致。
\\n同时也可以利用 Tags 来优化显示效果与检索,方便后续使用 SkyWalking MAL 进行 Metrics 计算。
\\nrules:\\n - name: apisix-errlog\\n dsl: |\\n filter {\\n text {\\n regexp \\"(?<datetime>\\\\\\\\d{4}/\\\\\\\\d{2}/\\\\\\\\d{2} \\\\\\\\d{2}:\\\\\\\\d{2}:\\\\\\\\d{2}) \\\\\\\\[(?<level>\\\\\\\\w+)\\\\\\\\] \\\\\\\\d+\\\\\\\\#\\\\\\\\d+:( \\\\\\\\*\\\\\\\\d+ \\\\\\\\[(?<module>\\\\\\\\w+)\\\\\\\\] (?<position>.*\\\\\\\\.lua:\\\\\\\\d+): (?<function>\\\\\\\\w+\\\\\\\\(\\\\\\\\)):)* (?<msg>.+)\\"\\n }\\n extractor {\\n tag level: parsed.level\\n if (parsed?.module) {\\n tag module: parsed.module\\n tag position: parsed.position\\n tag function: parsed.function\\n }\\n }\\n sink {\\n }\\n }\\n
\\n在 SkyWalking OAP Server 使用的 LAL 脚本之后,将会在日志中提取部分 Tags,效果如下图。
\\n本文主要介绍了两款 Apache APISIX 集成 SkyWalking 的日志插件,为之后大家在 Apache APISIX 中进行日志处理提供更方便的操作与环境。希望通过本篇内容,大家可以对新功能有了更充分的理解,后续可以更方便地利用 Apache APISIX 进行可观测数据的集中管理。
\\n","description":"在可观测性领域,通常采用 Metrics、Logger 与 Tracing 三大方向的数据收集与分析,以达到洞察应用运行状态的目的,Apache SkyWalking 的日志处理正好具备了以上三方面。 Apache APISIX 早在 1.4 版本就已经集成 Apache SkyWaling Tracing 能力,并在后续版本中加入了错误日志和访问日志收集等功能。如今随着 Apache SkyWalking 对 Metrics 的支持,能够帮助 Apache APISIX 在集成模式下实现一站式可观测方案,同时覆盖到日志、度量和调用追踪。\\n\\n功能开发背景…","guid":"https://www.apiseven.com/blog/apisix-integrate-skywalking-plugin","author":"庄浩潮","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-07T16:00:00.293Z","media":[{"url":"https://static.apiseven.com/202108/1638781626018-da50a39d-da16-4914-b4f5-8ac9b4312e19.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638781696137-6ba3a486-08c0-49e1-bc57-e144f95918a2.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638781751540-d597ace7-1de1-4baf-b361-1c136dfe5e05.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638781827612-f7d88e0e-0159-44ba-bc1e-b718695bc3b8.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638781886771-b98c80de-4ea2-4cf3-ad1c-26250da231f7.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Apache APISIX 携手 RocketMQ 为实时 API 日志监控功能再下一城","url":"https://www.apiseven.com/blog/integrate-rocketmq-in-apisix","content":"Apache RocketMQ 自 2016 年走入全球开发者视野以来,目前已发展成为电商、金融、教育、科技等多领域技术中台的核心数据底座。
\\n据不完全统计,国内用户(包括金融、保险、财富和券商等各领域百强企业)超过 70% 的企业都在核心应用链路上规模化部署了 Apache RocketMQ,包括全球 5 大云厂商也纷纷上线了有关 Apache RocketMQ 的云产品服务。
\\n除了常规应用于核心业务消息的处理,也有非常多的公司开始使用 Apache RocketMQ 进行日志处理与分析。
\\n为了满足广大企业用户对于日志处理的需求,Apache APISIX 发布了基于 Apache RocketMQ 的日志插件 rocketmq-logger
,支持将 API 接口请求日志以 JSON 形式推送给 RocketMQ 集群。
该插件使用 RocketMQ 原生支持的 TCP 协议,通过 OpenResty 提供的无阻塞 TCP Socket API,实现了高并发、高性能访问等功能特性。
\\n同时,使用 rocketmq-logger
插件发送的 API 日志格式与其他日志插件相同,同样支持批量发送日志、自定义日志格式、支持重试等功能。
此外,该插件还支持 TLS 加密传输,以及配置 AK、SK 认证方式访问 Apache RocketMQ,满足用户对于数据安全的需求。
\\n首先在本地利用下述命令来启动 RocketMQ,具体详细步骤可参考官方文档。
\\nwget https://dlcdn.apache.org/rocketmq/4.9.2/rocketmq-all-4.9.2-bin-release.zip\\n\\nunzip rocketmq-all-4.9.2-bin-release.zip\\n\\ncd rocketmq-4.9.2/\\n\\nnohup sh bin/mqnamesrv &\\n\\nnohup sh bin/mqbroker -n 127.0.0.1:9876 -c conf/broker.conf &\\n
\\n在生产环境中只需执行一条命令,就可以为指定路由启用 rocketmq-logger
插件。
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"plugins\\": {\\n \\"rocketmq-logger\\": {\\n \\"nameserver_list\\" : [ \\"127.0.0.1:9876\\" ],\\n \\"topic\\" : \\"test\\",\\n }\\n },\\n \\"upstream\\": {\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n },\\n \\"type\\": \\"roundrobin\\"\\n },\\n \\"uri\\": \\"/hello\\"\\n}\'\\n
\\n启用 rocketmq-logger
插件后,任何对端点 URI/hello
的请求都会将日志推送到 Apache RocketMQ 中。
具体支持的参数详情可参考下方表格:
\\n名称 | \\n类型 | \\n描述 | \\n
---|---|---|
nameserver_list | \\nobject | \\n要推送的 rocketmq 的 nameserver 列表。 | \\n
topic | \\nstring | \\n要推送的 topic。 | \\n
key | \\nstring | \\n发送消息的keys。 | \\n
tag | \\nstring | \\n发送消息的tags。 | \\n
timeout | \\ninteger | \\n发送数据的超时时间。 | \\n
use_tls | \\nboolean | \\n是否开启TLS加密。 | \\n
access_key | \\nstring | \\nACL认证的access key,空字符串表示不开启ACL。 | \\n
secret_key | \\nstring | \\nACL认证的secret key。 | \\n
当然,如果在使用过程中不想使用默认的日志格式,也可以对插件进行元数据设置。
\\n首先可以通过模板形式来调整相关日志格式。
\\n名称 | \\n默认值 | \\n描述 | \\n
---|---|---|
log_format | \\n{\\"host\\": \\"$host\\", \\"@timestamp\\": \\"$time_iso8601\\", \\"client_ip\\": \\"$remote_addr\\"} | \\n以 JSON 格式的键值对来声明日志格式。对于值部分,仅支持字符串。如果是以 $ 开头,则表明是要获取 APISIX 变量或 Nginx 内置变量。特别的,该设置是全局生效的,意味着指定 log_format 后,将对所有绑定 http-logger 的 Route 或 Service 生效。 | \\n
日志格式调整完成后,需要向 /apisix/admin/plugin_metadata
端点发出请求来更新元数据,具体可参考下方代码。
curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/rocketmq-logger -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"log_format\\": {\\n \\"host\\": \\"$host\\",\\n \\"@timestamp\\": \\"$time_iso8601\\",\\n \\"client_ip\\": \\"$remote_addr\\"\\n }\\n}\'\\n
\\n如果您不再使用该插件,可通过在插件配置中删除相应的 JSON 配置来禁用 rocketmq-logger
插件。该过程无需重新启动服务,输入下方代码即可立即生效。
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"methods\\": [\\"GET\\"],\\n \\"uri\\": \\"/hello\\",\\n \\"plugins\\": {},\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n }\\n }\\n}\'\\n
\\n","description":"Apache RocketMQ 自 2016 年走入全球开发者视野以来,目前已发展成为电商、金融、教育、科技等多领域技术中台的核心数据底座。 据不完全统计,国内用户(包括金融、保险、财富和券商等各领域百强企业)超过 70% 的企业都在核心应用链路上规模化部署了 Apache RocketMQ,包括全球 5 大云厂商也纷纷上线了有关 Apache RocketMQ 的云产品服务。\\n\\n除了常规应用于核心业务消息的处理,也有非常多的公司开始使用 Apache RocketMQ 进行日志处理与分析。\\n\\n插件介绍\\n\\n为了满足广大企业用户对于日志处理的需求…","guid":"https://www.apiseven.com/blog/integrate-rocketmq-in-apisix","author":"余洲","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-12-07T16:00:00.269Z","media":null,"categories":null,"attachments":null,"extra":null,"language":null},{"title":"在 KubeSphere 中使用 Apache APISIX Ingress 网关接入自定义监控","url":"https://www.apiseven.com/blog/use-apisix-ingress-in-kubesphere","content":"11 月初,KubeSphere 发布了 3.2.0 版本,新版本为项目网关增配了整套监控及管理页面,同时引入了集群网关来提供集群层面全局的 Ingress 网关能力。
\\n为了让用户更了解如何在新版 KubeSphere 中部署使用第三方 Ingress Controller,本文将以 Apache APISIX Ingress Controller 为例,为大家展示通过 KubeSphere 快速为 Kubernetes 集群使用不同类型的网关并进行状态监控。
\\n安装 KubeSphere 有两种方法:
\\nKubeSphere 最小化安装版本已经包含了监控模块,因此不需要额外启用,可以通过「系统组件」页面中的「监控」标签页确认安装状态。
\\n由于需要演示网关的访问控制能力,我们必须要先有一个可以访问的应用作为网关的后台服务。这里我们使用 httpbin.org 提供的 kennethreitz/httpbin 容器应用作为演示应用。
\\n在 KubeSphere 中,我们可以先创建新的项目或使用已有的项目,进入项目页面后,选择「应用负载」下的「服务」直接创建无状态工作负载并生成配套服务。
\\n使用 kennethreitz/httpbin 容器默认的 80
端口作为服务端口,创建完成后确保在「工作负载」和「服务」页面下都可以看到 httpbin
的对应条目,如下图所示。
项目网关是 KubeSphere 3.0 之后上线的功能。KubeSphere 项目中的网关是一个 NGINX Ingress 控制器。KubeSphere 内置用于 HTTP 负载均衡的机制称为应用路由,它定义了从外部到集群服务的连接规则。如需允许从外部访问服务,用户可创建路由资源来定义 URI 路径、后端服务名称等信息。
\\n承接上文中已部署的 httpbin
服务项目,在「项目设置」中打开「网关设置」页面,然后执行「开启网关」操作。方便起见,直接选择 NodePort
作为「访问方式」即可。
确定后回到网关页面,稍等片刻后刷新页面,可以得到如下图显示的部署完成状态,在这里可以看到 NodePort 默认被赋予了两个节点端口。接招我们通过右上角的「管理」按钮「查看详情」。
\\n此时我们看到的便是 3.2.0 版本关于项目/集群网关的新监控页面。下面我们就需要为 httpbin 服务创建应用路由。
\\n从「应用负载」进入「应用路由」页面,开始「创建」路由。为路由取名为 httpbin
后,我们指定一个方便测试的域名,并设置「路径」为 /
, 选择「服务」httpbin
和「端口」80
。
直接下一步跳过高级设置后完成路由创建,可以得到如下图所示的 httpbin 应用路由项。
\\n接下来我们就可以通过项目网关的 NodePort 地址及指定域名(如这里是 http://httpbin.ui:32516) 来访问 httpbin 应用服务,随意刷新或操作一下页面的请求生成功能,再进入网关的详情页面,便可以看到在「监控」面板上已经出现了网关的一些内置的监控指标展示。
\\n对于公有云环境,如果使用 NodePort 方式向外暴露访问能力,开放端口通常是有限且受控的,因此对于网关所使用的 NodePort 我们需要对它进行修改。
\\n由于网关是被 KubeSphere 统一管理的,要修改网关服务的 NodePort 需要具备访问 kubesphere-controls-system
的项目权限。进入该项目后,通过「应用负载」的「服务」页面即可找到命名为 kubesphere-router-<project-namespace>
形式且外部访问已开放 NodePort 的网关服务。NodePort 服务端口需要通过「编辑 YAML」来直接修改。
\\n\\nKubeSphere 3.2.0 开始支持集群级别的全局网关,所有项目可共用同一个网关,之前已创建的项目网关也不会受到集群网关的影响。也可以统一纳管所有项目的网关,对其进行集中管理和配置,管理员用户再也不需要切换到不同的企业空间中去配置网关了。
\\n
如果您使用的是是 KubeSphere 3.2.0 版本,我们更推荐大家使用集群网关的功能来统一整个集群的应用路由。要启用集群网关也非常简单:使用具备集群管理权限的账号,进入其可管理的某个集群(如我们这里以 default
集群为例),在「集群设置」的「网关设置」中即可「开启网关」,同时查看「项目网关」。
集群网关开启的方式以及对齐 NodePort 访问端口的修改和之前项目网关的操作基本完全一致,这里就不多赘述了。
\\n但有一点需要特别注意:集群网关开启后,已经开启的项目网关还会保留;但尚未创建网关的项目是无法再创建单独的网关的,会直接使用集群网关。
\\n下图展示了已创建网关的项目,在同时拥有项目及集群网关后,在「网关设置」页面所呈现的所有网关概览。
\\nApache APISIX 是一款开源的高性能、动态云原生网关,由深圳支流科技有限公司于 2019 年捐赠给 Apache 基金会,目前已成为 Apache 基金会的顶级开源项目,也是 GitHub 上最活跃的网关项目。Apache APISIX 目前已覆盖 API 网关、LB、Kubernetes Ingress、Service Mesh 等多种场景。
\\n首先添加 Apache APISIX Helm Chart 仓库。之后选定一个企业空间,通过「应用管理」下的「应用仓库」来添加如下一个 Apache APISIX 的仓库。
\\n接下来创建一个名为 apisix-system
的项目。进入项目页面后,选择在「应用负载」中创建「应用」的方式来部署 Apache APISIX,并选择 apisix
应用模版开始进行部署。
\\n\\n为何是直接部署 Apache APISIX 应用的 Helm Chart,而不是直接部署 Apache APISIX Ingress Controller?
\\n
这是因为 Apache APISIX Ingress Controller 目前和 Apache APISIX 网关是强关联的(如下图所示),且目前通过 Apache APISIX Helm Charts 同时部署 Apache APISIX Gateway + Dashboard + Ingress Controller 是最方便的,因此本文推荐直接使用 Apache APISIX 的 Helm Chart 进行整套组件的部署。
\\n将应用命名为 apisix
以避免多个组件(Gateway, Dashboard, Ingress Controller)的工作负载及服务名称产生不匹配的情况;在安装步骤中编辑的「应用设置」的部分,请参照以下配置进行填写(请特别注意带有【注意】标记的注释部分的说明,其余可以按需自行编辑修改)。
global:\\n imagePullSecrets: []\\n\\napisix:\\n enabled: true\\n customLuaSharedDicts: []\\n image:\\n repository: apache/apisix\\n pullPolicy: IfNotPresent\\n tag: 2.10.1-alpine\\n replicaCount: 1\\n podAnnotations: {}\\n podSecurityContext: {}\\n securityContext: {}\\n resources: {}\\n nodeSelector: {}\\n tolerations: []\\n affinity: {}\\n podAntiAffinity:\\n enabled: false\\n\\nnameOverride: \'\'\\nfullnameOverride: \'\'\\n\\ngateway:\\n type: NodePort\\n externalTrafficPolicy: Cluster\\n http:\\n enabled: true\\n servicePort: 80\\n containerPort: 9080\\n tls:\\n enabled: false\\n servicePort: 443\\n containerPort: 9443\\n existingCASecret: \'\'\\n certCAFilename: \'\'\\n http2:\\n enabled: true\\n stream:\\n enabled: false\\n only: false\\n tcp: []\\n udp: []\\n ingress:\\n enabled: false\\n annotations: {}\\n hosts:\\n - host: apisix.local\\n paths: []\\n tls: []\\n\\nadmin:\\n enabled: true\\n type: ClusterIP\\n externalIPs: []\\n port: 9180\\n servicePort: 9180\\n cors: true\\n credentials:\\n admin: edd1c9f034335f136f87ad84b625c8f1\\n viewer: 4054f7cf07e344346cd3f287985e76a2\\n allow:\\n ipList:\\n - 0.0.0.0/0\\n\\nplugins:\\n - api-breaker\\n - authz-keycloak\\n - basic-auth\\n - batch-requests\\n - consumer-restriction\\n - cors\\n - echo\\n - fault-injection\\n - grpc-transcode\\n - hmac-auth\\n - http-logger\\n - ip-restriction\\n - ua-restriction\\n - jwt-auth\\n - kafka-logger\\n - key-auth\\n - limit-conn\\n - limit-count\\n - limit-req\\n - node-status\\n - openid-connect\\n - authz-casbin\\n - prometheus\\n - proxy-cache\\n - proxy-mirror\\n - proxy-rewrite\\n - redirect\\n - referer-restriction\\n - request-id\\n - request-validation\\n - response-rewrite\\n - serverless-post-function\\n - serverless-pre-function\\n - sls-logger\\n - syslog\\n - tcp-logger\\n - udp-logger\\n - uri-blocker\\n - wolf-rbac\\n - zipkin\\n - traffic-split\\n - gzip\\n - real-ip\\n #【注意】添加此插件以配合 Dashboard 展示服务信息\\n - server-info\\n\\nstream_plugins:\\n - mqtt-proxy\\n - ip-restriction\\n - limit-conn\\n\\ncustomPlugins:\\n enabled: true\\n luaPath: /opts/custom_plugins/?.lua\\n #【注意】如下配置保障 Prometheus 插件可对外暴露指标\\n plugins:\\n - name: prometheus\\n attrs:\\n export_addr:\\n ip: 0.0.0.0\\n port: 9091\\n configMap:\\n name: prometheus\\n mounts: []\\n\\ndns:\\n resolvers:\\n - 127.0.0.1\\n - 172.20.0.10\\n - 114.114.114.114\\n - 223.5.5.5\\n - 1.1.1.1\\n - 8.8.8.8\\n validity: 30\\n timeout: 5\\n\\nautoscaling:\\n enabled: false\\n minReplicas: 1\\n maxReplicas: 100\\n targetCPUUtilizationPercentage: 80\\n targetMemoryUtilizationPercentage: 80\\n\\nconfigurationSnippet:\\n main: \'\'\\n httpStart: \'\'\\n httpEnd: \'\'\\n httpSrv: \'\'\\n httpAdmin: \'\'\\n stream: \'\'\\n\\netcd:\\n enabled: true\\n host:\\n - \'http://etcd.host:2379\'\\n prefix: /apisix\\n timeout: 30\\n auth:\\n rbac:\\n enabled: false\\n user: \'\'\\n password: \'\'\\n tls:\\n enabled: false\\n existingSecret: \'\'\\n certFilename: \'\'\\n certKeyFilename: \'\'\\n verify: true\\n service:\\n port: 2379\\n replicaCount: 3\\n\\ndashboard:\\n enabled: true\\n #【注意】为 Dashboard 开启 NodePort 方便后续使用\\n service:\\n type: NodePort\\n\\ningress-controller:\\n enabled: true\\n config:\\n apisix:\\n #【注意】一定要设置 gateway 所在的 namespace\\n serviceNamespace: apisix-system\\n serviceMonitor:\\n enabled: true\\n namespace: \'apisix-system\'\\n interval: 15s\\n
\\n部署成功后,点击应用名称进入详情页面,可以在「资源状态」标签页下看到如下的服务部署和工作状态运行状态展示。
\\n\\n\\nApache APISIX 项目另有的两个 Helm Chart 对应的默认配置参数可以分别参考:Dashboard 和 Ingress Controller 的 values.yaml。
\\n
Apache APISIX 应用部署完成后,可通过 Apache APISIX Dashboard 来检验一下 Apache APISIX 网关的当前状态。
\\n从应用负载-服务页面可以找到 apisix-dashboard
服务,由于我们在应用配置中已为 Dashboard 开启了 NodePort,所以这里可以直接通过 NodePort 端口来访问 Dashboard。
使用默认用户名及密码 admin
登录 Apache APISIX Dashboard,可以进入「系统信息」页面查看到当前连接管理的「Apache APISIX 节点」信息。
接下来让我们回到「应用路由」页面,再新建一个路由(如 apisix-httpbin
),设置路径为 /*
httpbin
80
并为其添加 kubernetes.io/ingress.class
: apisix
的键值。
回到 Apache APISIX Dashboard 进入「路由」页面,可以看到新建的应用路由已被 Apache APISIX Ingress Controller 识别后自动添加到了 Apache APISIX 网关中,在「上游」页面也可以看到自动创建的一个上游条目。
\\n接下来回到 apisix-system
项目「服务」页面,找到 apisix-gateway
服务对应的端口,由此访问 <apisix-httpbin 应用路由指定的域名>:<apisix-gateway 外部访问端口>
(例如此处为 httpbin.ui:30408
)即可访问到 apisix-httpbin
应用路由所关联的后台服务。
使用 Apache APISIX 网关时可通过 Prometheus 插件以及 KubeSphere 自带的自定义监控能力来进行监控能力的加持。
\\n由于我们在前边部署 Apache APISIX 应用时已经开启了 Prometheus 插件,所以接下来只需要把 Prometheus 监控指标的接口暴露出来即可。
\\n进入 apisix-system
项目,在「工作负载」页面找到 apisix 并进入部署详情页面,随后在左侧操作面板的「更多操作」中选择「编辑设置」。
在弹出的面板中,进入到 apisix
容器编辑界面,找到「端口设置」,添加一个新的名为 prom
的端口映射到容器的 9091
端口,保存后 apisix
工作负载会重启。
接下来我们需要将已暴露的指标接口接入到 KubeSphere 自带的 Prometheus 中使之可被访问(被抓取指标数据)。
\\n由于 KubeSphere 是通过 Prometheus Operator 来维护内部 Prometheus 系统,所以最快捷的方式自然是直接创建 ServiceMonitor 资源来实现指标接口的接入。
\\napiVersion: monitoring.coreos.com/v1\\nkind: ServiceMonitor\\nmetadata:\\n name: apisix\\n namespace: apisix-system\\nspec:\\n endpoints:\\n - scheme: http\\n #【注意】使用上一步中工作负载暴露的容器端口名称\\n targetPort: prom\\n #【注意】需要正确绑定 apisix 对应的指标接口路径\\n path: /apisix/prometheus/metrics\\n interval: 15s\\n namespaceSelector:\\n matchNames:\\n - apisix-system\\n selector:\\n matchLabels:\\n app.kubernetes.io/name: apisix\\n app.kubernetes.io/version: 2.10.0\\n helm.sh/chart: apisix-0.7.2\\n
\\n使用 kubectl apply -f your_service_monitor.yaml
创建 ServiceMonitor 资源。创建成功后,如果有集群管理权限,也可以在集群的 CRD 管理页面中搜索查看 ServiceMonitor 资源并找到名为 apisix
的自定义资源,也可以在这里做后续的 YAML 修改。
在项目左侧菜单列表中找到「监控告警」中的「自定义监控」,开始「创建」自定义监控面板。
\\n在弹出窗口中填入「名称」,选择「自定义」监控模版,并进入「下一步」的监控面板创建。
\\n进入编辑页面后现在左侧点击 +
区域,在右侧的「数据」区域进行 Prometheus 监控指标的配置。例如这里我们可以用 sum(apisix_nginx_http_current_connections)
来统计 Apache APISIX 网关实时的连接总数。
保存后在页面右下角找到「+ 添加监控项」,并选择「折线图」创建 Nginx connection state
指标:使用 sum(apisix_nginx_http_current_connections) by (state)
作为指标、{{state}}
用作图例名称、「图例类型」为堆叠图,即可得到类似下图的结果。保存模版后即可得到第一个自定义监控面板!
\\n\\nApache APISIX 网关目前提供的 Prometheus 指标可以参见官方文档的可有的指标部分。
\\n
由于指标配置过程比较麻烦,推荐在集群层面的「自定义监控」中直接导入 Apache APISIX Grafana 模版(下载 JSON 并通过「本地上传」进行导入)。
\\n创建完成后可直接呈现出非常丰富的 Apache APISIX 网关监控面板。KubeSphere 也同时在积极推进将 Grafana 模版导入的功能引入到项目的自定义监控能力中去,敬请期待!
\\n通过本文非常详细的步骤介绍,大家可充分了解并跟随上手体验到如何「将 Apache APISIX Ingress 网关介入 KubeSphere 并进行自定义监控」。希望通过阅读本文,可以加深各位对 Apache APISIX Ingress Controller 与 Apache APISIX 应用理解。
\\n作者张海立,驭势科技云平台研发总监。开源爱好者,云原生社区上海站 PMC 成员,KubeSphere Ambassador。
\\n","description":"11 月初,KubeSphere 发布了 3.2.0 版本,新版本为项目网关增配了整套监控及管理页面,同时引入了集群网关来提供集群层面全局的 Ingress 网关能力。 为了让用户更了解如何在新版 KubeSphere 中部署使用第三方 Ingress Controller,本文将以 Apache APISIX Ingress Controller 为例,为大家展示通过 KubeSphere 快速为 Kubernetes 集群使用不同类型的网关并进行状态监控。\\n\\n准备工作\\n安装 KubeSphere\\n\\n安装 KubeSphere 有两种方法:\\n\\n在…","guid":"https://www.apiseven.com/blog/use-apisix-ingress-in-kubesphere","author":"张海立","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-11-30T16:00:00.658Z","media":[{"url":"https://static.apiseven.com/202108/1638255471644-e1327ffc-dbed-4890-a15c-819f28731fc9.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638255616585-b0f5a674-f06a-4b18-baf9-8d6006abeead.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638255786442-924bf704-9b9d-413f-9fc0-be6650a6ff4a.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638255792974-7f354950-e34a-427a-9ff7-aa3af0a56dd6.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638256005754-d1e8bf9a-0ecc-4c6e-8ceb-0c25b04fef20.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638256011357-960f6852-31b3-4702-8911-17d07ec19d7b.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241684770-ce94fe24-58a6-4b9b-9507-d802713b4c38.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241689985-149fc2f7-456b-423c-8cfc-00800dc24917.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638256382273-109728eb-4d19-4c2b-ab92-9a2909c3eff8.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638256419345-48476f01-b293-401b-9e4f-8bf64a9fab90.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638256523468-408ee36f-aac7-4bb4-9cd3-2473a95a52f4.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638256574546-920473f3-e8ac-4cf9-932b-4202888e7a54.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638256658706-ac5107fe-2fd7-4521-b830-9ae1fdf762e1.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638256788584-dca2d21b-3ffc-4bb4-bd73-56dedb6d005a.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241691528-80090ab6-85de-401f-96d7-58118b3cbd88.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241693072-9b3146f5-bcc6-4441-b002-f1a07603a8c4.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241694605-7d88f095-fef5-43f4-9752-8dc5a2f9abc4.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241699353-8d54dfe9-8439-4085-8e7d-02583a1d0d9e.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241703083-0915a427-9aab-41e6-8c76-be60d70fc135.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241705123-6fe3ba11-bc08-4fb2-a8b1-73066ce73679.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241706790-3989c06d-c803-4c16-869a-6fa000b5744b.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241712811-db1f93dd-2963-4034-b461-26733d173bae.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241716159-134e6bd8-9e08-46de-8d46-39142c439b8f.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241718162-86d110b6-2c40-461c-9cf4-a13b73cf5768.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241721050-c3e9409c-4ec8-4ff1-bcf8-045ea57ec179.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241723331-64cb363e-b6af-4af4-93f3-29a79c9a5e77.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241724906-d9531809-4682-49b3-b90b-d7f3a03e70e3.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241727938-cd3843f9-0e22-4316-91d2-84b56cd66f21.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241729416-3d2024f1-9586-44ac-ad6c-7472c8924fc8.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241730747-298fe17e-fb34-4da6-ac9d-8b1efde4521c.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241733535-168ce86b-6654-4278-941d-23fb44003c90.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1638241735167-4c6d3a9a-8190-41b5-9e89-7f09384c7113.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"azure-functions 插件发布,Apache APISIX 支持 Azure Functions 集成","url":"https://www.apiseven.com/blog/apache-apisix-azure-functions-integration","content":"Apache APISIX 为 Microsoft Azure Functions 提供了对 serverless 框架的支持。Apache APISIX 建议定义一个启用了无服务器插件的路由,而不是在应用程序中采用硬编码函数 URL。它使开发者能够灵活地热更新函数 URI。此外,因为 Apache APISIX 有非常强大的认证支持,这种方法还可以减轻应用逻辑中的授权和认证问题,可以用来识别和授权客户消费者访问带有 FAAS 的特定路由。本文介绍了 Apache APISIX 最近新增的插件 azure-functions
,并详细说明了如何将 Azure Functions(一种广泛使用的 serverless 解决方案)集成到 Apache APISIX 中。
azure-functions
插件让用户为网关 URI 定义一个上游的 azure HTTP Trigger
serverless 功能。如果启用,该插件将终止正在进行的对该 URI 的请求,并代表客户向 azure FAAS(新的上游)发起一个新的请求,其中包括用户设置的合适的授权细节、请求头、请求体、参数(这三个部分都是从原始请求中传递的),并将响应体、状态码和头返回给向 Apache APISIX 代理发出请求的原始客户。
该插件支持通过 API 密钥和 azure active directory 对 azure FAAS 服务进行授权。
\\n该插件的主要目标是将路由配置中指定的网关路由代理到 azure function URI 上。本节为您介绍如何在 azure 云上配置和创建 serverless HTTP Trigger。
\\n首先进入 Azure 并设置一个试用计划,最多可免费调用 100 万次。要了解更多关于定价的情况,请访问这里。
\\n访问Azure Portal。
\\n在 VSCode 编辑器中安装 Azure Functions 插件。安装后,通过插件认证,并安装 azure function core tool,用于本地开发。
\\nnpm install -g azure-functions-core-tools@3 --unsafe-perm true\\n
\\n将下面的代码段部署到我们刚才通过 VSCode 中的 Azure Functions 扩展面板创建的同一个function 应用中。
\\nmodule.exports = async function (context, req) {\\ncontext.log(\'HTTP trigger invoked on Test-APISIX.\')\\n\\nconst name = req.query.name || (req.body && req.body.name)\\nconst responseMessage = name\\n ? \'Hello, \' + name\\n : \'This HTTP triggered function executed successfully. Pass a name in the query string or in the request body to generate a personalized response.\'\\n\\ncontext.res = {\\n // status: 200, /* Defaults to 200 */\\n body: responseMessage,\\n}\\n}\\n
\\n\\n\\n这个代码段从查询参数中获取用户名字(如果不存在,则从请求体中获取)并向用户问好。
\\n
下面我们将通过一个示例为大家说明如何为一个特定的路由启用 azure-functions
插件。我们假设你的 HTTP Trigger 已经部署并准备好提供服务。
# enable plugin for a specific route\\ncurl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"plugins\\": {\\n \\"azure-functions\\": {\\n \\"function_uri\\": \\"http://test-apisix.azurewebsites.net/api/HttpTrigger\\",\\n \\"authorization\\": {\\n \\"apikey\\": \\"<Generated API key to access the Azure-Function>\\"\\n }\\n }\\n },\\n \\"uri\\": \\"/azure\\"\\n}\'\\n
\\n现在,任何对 Apache APISIX 网关上的 URI /azure
的请求(HTTP/1.1、HTTPS、HTTP2)都将触发对上述函数 URI 的 HTTP 调用,响应体与响应头和响应代码将被代理回给客户端。例如:
curl -i -XGET http://localhost:9080/azure\\\\?name=Bisakh\\nHTTP/1.1 200 OK\\nContent-Type: text/plain; charset=utf-8\\nTransfer-Encoding: chunked\\nConnection: keep-alive\\nRequest-Context: appId=cid-v1:38aae829-293b-43c2-82c6-fa94aec0a071\\nDate: Wed, 19 Nov 2021 18:46:55 GMT\\nServer: APISIX/2.10.2\\n\\nHello, Bisakh\\n
\\n考虑到,Apache APISIX 也是在config-default.yaml上以 enable_http2: true
运行,端口为 9081,客户端和 Apache APISIX 代理之间的任何 HTTP/2
通信将被代理到 azure faas,类似于 HTTP/1.1,响应将被代理回给客户端,并有适当的标题,例如:
curl -i -XGET --http2 --http2-prior-knowledge http://localhost:9081/azure\\\\?name=Bisakh\\nHTTP/2 200\\ncontent-type: text/plain; charset=utf-8\\nrequest-context: appId=cid-v1:38aae829-293b-43c2-82c6-fa94aec0a071\\nDate: Wed, 19 Nov 2021 18:46:56 GMT\\nserver: APISIX/2.10.2\\n\\nHello, Bisakh\\n
\\n如果需要停用 azure-functions 该插件,只需在插件配置中删除相应的 JSON 配置,禁用azure-functions
插件,并添加合适的上游配置。Apache APISIX 插件是热加载的,因此不需要重新启动 Apache APISIX。
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\": \\"/azure\\",\\n \\"plugins\\": {},\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n }\\n }\\n}\'\\n
\\n在启用 azure-functions
插件创建新路由时,在最小的配置中,function_uri
是插件配置的强制性属性,指向函数的 URL。有很多额外的选项,可以通过插件参数和元数据参数进行调整。
名称 | \\n类型 | \\n必填 | \\n默认值 | \\n有效值 | \\n描述 | \\n
---|---|---|---|---|---|
function_uri | \\nstring | \\n是 | \\nn/a | \\nn/a | \\n触发 serverless functions 代码的 azure functions Endpoint(例如:http://test-apisix.azurewebsites.net/api/HttpTrigger)。 | \\n
authorization | \\nobject | \\n否 | \\nn/a | \\nn/a | \\n访问云 functions 的授权凭证。 | \\n
authorization.apikey | \\nstring | \\n否 | \\nn/a | \\nn/a | \\n授权内的字段。生成API密钥来授权对该端点的请求。 | \\n
authorization.clientid | \\nstring | \\n否 | \\nn/a | \\nn/a | \\n授权内的字段。客户端ID(azure active directory),用于授权对该端点的请求。 | \\n
timeout | \\ninteger | \\n否 | \\n3000 | \\n[100,...] | \\n代理请求超时,以毫秒为单位。 | \\n
ssl_verify | \\nboolean | \\n否 | \\ntrue | \\ntrue/false | \\n是否启用执行服务器的SSL验证。 | \\n
keepalive | \\nboolean | \\n否 | \\ntrue | \\ntrue/false | \\n是否重复使用同一个代理连接。设置为false则禁用keepalives并立即关闭连接。 | \\n
keepalive_pool | \\ninteger | \\n否 | \\n5 | \\n[1,...] | \\n池中的最大连接数。 | \\n
keepalive_timeout | \\ninteger | \\n否 | \\n60000 | \\n[1000,...] | \\n最大的空闲超时,以毫秒为单位。 | \\n
这为严格约束 azure FAAS 的行为提供了很大的灵活性--从配置超时到 keepalive 池以及验证无服务器FAAS 的 SSL 证书。说实话,当涉及到无服务器时,这实际上意味着很多,因为服务是事件驱动的,而且资源是由云提供商即时分配的。
\\n同样,有一些属性可以通过使用元数据进行调整。
\\n名称 | \\n类型 | \\n必填 | \\n默认值 | \\n有效值 | \\n描述 | \\n
---|---|---|---|---|---|
master_apikey | \\nstring | \\n否 | \\n\\"\\" | \\nn/a | \\n可用于访问 azure functions URI 的 API KEY。 | \\n
master_clientid | \\nstring | \\n否 | \\n\\"\\" | \\nn/a | \\n可用于授权 function URI的客户ID(active directory)。 | \\n
azure-functions
插件的元数据提供了授权回退的功能。它定义了 master_apikey
和 master_clientid
(azure active directory client id),用户可以为关键任务的应用部署定义主 API 密钥或客户端 ID。因此,如果在插件属性中没有找到授权细节,元数据中的授权细节就会启动。
优先级排序如下
\\n首先,该插件在 Apache APISIX 代理的请求头中寻找 x-functions-key
或 x-functions-clientid
键。
如果没有找到,azure-functions 插件会检查插件属性中的授权细节。如果存在,它会将相应的标头添加到发送到 Azure cloud function 的请求中。
\\n如果在插件属性中没有找到授权细节,Apache APISIX 将为该插件获取元数据配置并使用主密钥。
\\n要添加一个新的主 APIKEY,请用更新的元数据向 /apisix/admin/plugin_metadata
端点提出请求,如下所示:
curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/azure-functions \\\\\\n-H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"master_apikey\\" : \\"<Your azure master access key>\\"\\n}\'\\n
\\nazure-functions
插件是 Apache APISIX 为 serverless 设计的第二个插件。我们正在开发其他 serverless 插件,并会在即将发布的 Apache APISIX 版本中介绍这些插件。如果大家感兴趣,请提交 Issue来分享你的意见,也可以在我们的邮件列表中分享开发新插件的建议!
在 GoLand 中通过 Nocalhost 部署 Apache APISIX Ingress Controller,操作如下:
\\n在 GoLand 中打开 Nocalhost 插件
\\n选择将要部署 APISIX Ingress Controller 的命名空间
\\n右键点击选定的命名空间,选择 Deploy Application
,然后选择 Helm Repo
作为安装方法
在下面的对话框中:
\\nName
中输入:apisix-ingress-controller
Chart URL
中输入:https://charts.apiseven.com
部署完成后,我们通过在 IDE 内启用端口转发来测试 apisix-ingress-controller
:
apisix-ingress-controller
,右键点击并选择 Port Forward
8080:8080
http://127.0.0.1:8080/healthz
并检查结果apisix-ingress-controller
工作负载,选择 Start DevMode
现在通过在远程终端中输入以下命令来启动 apisix-ingress-controller
进程:
go run main.go ingress --config-path conf/config-default.yaml\\n
\\napisix-ingress-controller
启动后,可通过 http://127.0.0.1:8080/healthz
访问服务,并检查结果。
现在我们来修改一下代码并看看效果:
\\napisix-ingress-controller
进程healthz
并找到 router.go
文件。将 healthzResponse
的状态代码从 ok
更改为 Hello Nocalhost
现在关闭开发窗口并退出开发模式:
\\napisix-ingress-controller
End DevMode
Nocalhost 将使 apisix-ingress-controller
结束开发模式, 并重置 apisix-ingress-controller
到其原始版本。启用端口转发来看看退出开发模式后的结果。
注意:在开发模式下修改代码时,所有代码更改都只在开发容器中生效。
\\n退出开发模式后,Nocalhost 将会将远程容器重置为原始状态(进入开发模式之前的版本)。这样,在退出开发模式后,对代码进行修改不会对原始环境造成任何更改或影响。
\\n调试应用程序是一件麻烦的事,在 Kubernetes 集群中调试应用程序则更加麻烦。但 Nocalhost 可以帮助我们在调试 Kubernetes 集群中的程序时获得和在 IDE 中直接调试本地程序同样的体验。
\\n我们可以通过以下方式开启远程调试
\\napisix-ingress-controller
并选择 Remote Debug
apisix-ingress-controller
进入开发模式,并运行在 dev config
定义的调试命令在 healthz
函数上设置一个断点。悬停在行号左侧,然后点击红点。设置好断点后,在浏览器中访问 http://127.0.0.1:8080/healthz
,会触发断点,GoLand 会跳到前台。点击调试相关按钮可对程序进行调试。
此外,因为我们启用了 dev.hotReload
,所以每次更改代码时,Nocalhost 将自动重新运行调试命令。这可以让我们频繁更改和调试代码时变得方便很多。
Nocalhost 不仅仅可以远程调试,还为我们在 Kubernetes 集群中运行服务以及热加载提供了一种更简单的方式。
\\n我们可以通过以下步骤使用 Remote Run 功能:
\\napisix-ingress-controller
,并选择 Remote Run
apisix-ingress-controller
进入开发模式,并运行在 dev config
定义的运行命令每次更改代码完代码后,Nocalhost 都会自动触发运行命令,将程序运行起来。
\\n通过本文,我们为大家展示了如何使用 Nocalhost 来开发和调试 Kubernetes 集群中的 Apache APISIX Ingress Controller。借助 Nocalhost 的能力,我们不再需要等待缓慢的本地开发过程,而是可以通过即时反馈和高效的云本地开发环境进行快速部署与迭代。
\\n","description":"环境准备 准备一个可用的 Kubernetes 集群。可使用任意拥有命名空间管理权限的 Kubernetes 集群\\n本地已安装好 Helm v3.0+\\n集群中已安装好 Apache APISIX\\nGoLand IDE 2020.03+ (本文应用的是 2021.2 版本)\\n安装 Nocalhost JetBrains plugin 插件\\n安装 Go 1.13 或更高版本\\n部署 Apache APISIX Ingress Controller\\n\\n在 GoLand 中通过 Nocalhost 部署 Apache APISIX Ingress…","guid":"https://www.apiseven.com/blog/develop-apisix-ingress-with-nocalhost-in-kubernetes","author":"Garry Chen","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-11-21T16:00:00.910Z","media":[{"url":"https://static.apiseven.com/202108/1637131316244-f1a58c88-8628-4918-a4c4-1ad287742fd0.gif","type":"photo"},{"url":"https://static.apiseven.com/202108/1637131450462-842c3baf-b7a4-4598-be0b-27486bf1cf28.gif","type":"photo"},{"url":"https://static.apiseven.com/202108/1637131513751-b9184c10-4da3-4ab2-b403-56ae2360704a.gif","type":"photo"},{"url":"https://static.apiseven.com/202108/1637131699629-a0766f66-0faa-4bf8-9013-284e5f2bdd57.gif","type":"photo"},{"url":"https://static.apiseven.com/202108/1637131766524-dba7b756-ae0b-42d1-8ff0-6ac14059ce11.gif","type":"photo"},{"url":"https://static.apiseven.com/202108/1637132327260-7bba1d81-cf70-4982-9a07-51cc379e6bea.gif","type":"photo"},{"url":"https://static.apiseven.com/202108/1637132455552-86f44c0c-94d1-4ad9-a79d-0e2c6957d60b.gif","type":"photo"},{"url":"https://static.apiseven.com/202108/1637133046432-84810667-c3ee-4d71-8a33-eb1833fd9ce2.gif","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"重磅功能!Apache APISIX 拥抱 WASM 生态","url":"https://www.apiseven.com/blog/apisix-support-wasm","content":"在即将发布的 Apache APISIX 版本(2.11.0)中,我们新增了对于 WASM 的支持!现在开发者除了可以使用 Lua、Java、Go、Python、JavaScript 等多种编程语言开发 APISIX 的插件之外,也可以用 WASM 来开发插件。
\\nWASM 全称 WebAssembly,与上述具体编程语言运行时的不同之处在于,它是一套字节码标准,专门设计成可以在宿主环境中嵌套使用。
\\n如果某种编程语言提供编译成 WASM 字节码的功能,就可以把该语言的应用编译成 WASM 字节码,运行在某个支持 WASM 的宿主环境中。
\\n听起来,是不是只要某个宿主环境支持 WASM,就能像操作系统一样运行任意应用呢?
\\n但其实这里有个限制,就像操作系统需要实现特定标准的 syscall 一样,要想运行特定的应用,也需要实现该应用所需的 API。
\\n以 JavaScript 为例,虽然同样是 JavaScript 代码,但是针对浏览器写的 JS 模块不能直接用在 npm 包里面,因为两个的 API 不一样。
\\n所以仅仅把 WASM 放到 Apache APISIX 里面并行不通,要想让开发者在 Apache APISIX 上运行 WASM,我们还需要提供一套专门的 API。
\\n对于如何提供这套 API,我们曾经权衡过两套方案:
\\nProxy WASM 是 Envoy 的 WASM API 标准。所以上述问题其实等价于,我们是自己搞一套 API 标准还是复用 Envoy 已有标准呢?
\\nWASM API 标准可以拆成两个方面来看:
\\n如果我们遵循 Envoy 的标准,优势在于可以复用 Envoy 现有的 WASM SDK(Proxy WASM SDK),而不足之处在于这套标准是 Envoy 结合自己情况制定的,如果我们跟着实现,没有自己量身定制那么轻松。
\\n经过社区的讨论后,我们最终决定采用 Proxy WASM 标准。「做难且正确的事」,实现 Proxy WASM 自然是难的事,但我们相信这是正确的事,通过社区的合作和共建,可以构建更加繁荣的生态。
\\nApache APISIX 目前已初步支持 WASM,可以使用 WASM 来编写 fault-injection 插件的部分功能。感兴趣的读者可以在本月底的 Apache APISIX 2.11.0 版本中尝尝鲜,敬请期待!
\\n下面我们将结合 proxy-wasm-go-sdk 来讲讲怎么用 WASM 实现注入自定义响应的功能。
\\n实现代码(包含 go.mod
和其他)具体细节可点击此处查阅。
这里需要解释下,虽然 proxy-wasm-go-sdk 这个项目带了 Go 的名字,但它其实用的是 tinygo 而不是原生的 Go。因为原生的 Go 在支持 WASI (你可以认为它是非浏览器的 WASM 运行时接口)时会有一些问题,详情可点击此处查阅。
\\ntinygo build -o ./fault-injection/main.go.wasm -scheduler=none -target=wasi ./fault-injection/main.go\\n
\\napisix:\\n ...\\nwasm:\\n plugins:\\n - name: wasm_fault_injection\\n priority: 7997\\n file: t/wasm/fault-injection/main.go.wasm\\n
\\n通过以上操作,你可以像用 Lua 插件一样用这个 WASM 插件,比如:
\\nuri: \\"/wasm\\"\\nplugins:\\n wasm_fault_injection:\\n conf: \'{\\"body\\":\\"hello world\\", \\"http_status\\":200}\'\\nupstream:\\n type: roundrobin\\n nodes:\\n 127.0.0.1:1980: 1\\n
\\n注意 WASM 插件的配置都是 conf 字段下面的一条字符串,由对应的插件自己去做解析。
\\nApache APISIX 发展到现在,已经有三种编写插件的方式:
\\n这三种方式在诸如生态、成熟度等各个方面都差异很大。正巧我们都可以用它们来实现 fault-injection,所以可以比比看。
\\nLua way 的 fault-injection,自然是使用内置的 fault-injection 插件。Runner way 的 fault-injection 实现具体可点击此处查阅。
\\n接下来让我们分别给它们配置不同的路由:
\\n---\\nuri: \\"/wasm\\"\\nplugins:\\n wasm_fault_injection:\\n conf: \'{\\"body\\":\\"hello world\\", \\"http_status\\":200}\'\\nupstream:\\n type: roundrobin\\n nodes:\\n 127.0.0.1:1980: 1\\n---\\nplugins:\\n ext-plugin-pre-req:\\n conf:\\n - name: fault-injection\\n value: \'{\\"body\\":\\"hello world\\", \\"http_status\\":200}\'\\nupstream:\\n nodes:\\n 127.0.0.1:1980: 1\\n type: roundrobin\\nuri: /ext-plugin\\n---\\nplugins:\\n fault-injection:\\n abort:\\n body: hello world\\n http_status: 200\\nupstream:\\n nodes:\\n 127.0.0.1:1980: 1\\n type: roundrobin\\nuri: /fault-injection\\n
\\n接下来试着用 wrk 进行压测,具体数据对比如下:
\\n从上述结果可以看到,WASM 版本的性能介于外部插件和原生 Lua 之间。
\\nWASM 版本的性能之所以比外部插件好那么多,是因为 fault-injection 功能简单,所以外部插件 RPC 带来的性能损耗过于明显。考虑到我们还没有对 WASM 实现做任何优化,这种情况已经让我们感到满意了。
\\n而 WASM 的另一个好处,就是让我们一下子拥有多语言的支持(这也托了 Proxy WASM SDK 的福)。具体细节可参考下方文档:
\\n\\n说了这么多 WASM 的好处,是不是有点心动呢?但它目前并非是一个完美的解决方案, WASM/Proxy WASM 还是有一些不够成熟的地方。比如:
\\n虽然上面列举了几点不足之处,但是我们相信这个技术栈的前景是光明的:
\\nApache APISIX 是个紧跟技术潮流的项目,“好风凭借力,送我上青天”,Apache APISIX 支持 WASM 是个长期的过程。
\\n“千里之行,始于足下”,Apache APISIX 为了支持 WASM,已经发起了 wasm-nginx-module 这个开源项目。感兴趣的读者可以关注该项目的进展,“独行者速,众行者远”,期待你的加入,一起创造世界顶级项目。
\\n","description":"在即将发布的 Apache APISIX 版本(2.11.0)中,我们新增了对于 WASM 的支持!现在开发者除了可以使用 Lua、Java、Go、Python、JavaScript 等多种编程语言开发 APISIX 的插件之外,也可以用 WASM 来开发插件。 WASM 全称 WebAssembly,与上述具体编程语言运行时的不同之处在于,它是一套字节码标准,专门设计成可以在宿主环境中嵌套使用。\\n\\n如果某种编程语言提供编译成 WASM 字节码的功能,就可以把该语言的应用编译成 WASM 字节码,运行在某个支持 WASM 的宿主环境中。\\n\\n听起来…","guid":"https://www.apiseven.com/blog/apisix-support-wasm","author":"罗泽轩","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-11-18T16:00:00.974Z","media":[{"url":"https://static.apiseven.com/202108/1637289637179-ab74d38f-acd4-4401-908f-e1d310a33583.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637289637159-f2fd1f09-4be6-4cd4-88a0-9c3a23c4f405.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637289637162-6d2ef1d6-9de8-410c-8ca6-e264205c1be1.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"如何与 Dapr 集成打造 Apache APISIX 网关控制器","url":"https://www.apiseven.com/blog/dapr-with-apisix","content":"本质上,Apache APISIX 控制器将配置相同标准 Dapr annotations 以注入 daprd sidecar。通过公开这个 sidecar,将允许外部应用程序与集群中启用 Dapr 的应用程序进行通信。
\\n下图为实际项目中的架构流程:
\\n在 K8s 生态中,Ingress 作为表示 K8s 流量入口的一种资源,想要让其生效,就需要有一个 Ingress Controller 去监听 K8s 中的 Ingress 资源,并对这些资源进行相应规则的解析和实际承载流量。在当下趋势中,像 Kubernetes Ingress Nginx 就是使用最广泛的 Ingress Controller 实现。
\\n而 APISIX Ingress 则是另一种 Ingress Controller 的实现。跟 Kubernetes Ingress Nginx 的区别主要在于 APISIX Ingress 是以 Apache APISIX 作为实际承载业务流量的数据面。如下图所示,当用户请求到具体的某一个服务/API/网页时,通过外部代理将整个业务流量/用户请求传输到 K8s 集群,然后经过 APISIX Ingress 进行后续处理。
\\n从上图可以看到,APISIX Ingress 分成了两部分。一部分是 APISIX Ingress Controller,作为控制面它将完成配置管理与分发。另一部分 APISIX Proxy Pod 负责承载业务流量,它是通过 CRD(Custom Resource Definitions) 的方式实现的。Apache APISIX Ingress 除了支持自定义资源外,还支持原生的 K8s Ingress 资源。
\\n点击查看更多详情。
\\nDapr 是一个可移植、事件驱动的运行时。它使开发人员简单地去构建运行在云和 edge 上弹性、无状态和有状态的应用,并且包含多种语言和开发人员框架。
\\n今天,我们正经历一波云应用浪潮。开发人员熟悉 web+ 数据库应用程序架构(例如经典的 3 层设计),但不熟悉本质上是分布式的微服务应用程序架构。开发人员希望专注于业务逻辑,同时依靠平台为他们的应用程序注入伸缩性、弹性、可维护性、弹性和其他本地云架构的属性。
\\n这就是 Dapr 的用武之地。
\\nDapr 可以将构建微服务应用程序的最佳实践编入开放、独立的构建块中,使用户能够使用自己选择的语言和框架构建可移植的应用程序。每个构建块都是完全独立,并可在应用程序中使用其中的一个或多个。
\\n此外,Dapr 与平台无关,这意味着用户可以在任何 Kubernetes 集群和其他与 Dapr 集成的托管环境本地运行应用程序。
\\n点击查看更多详情。
\\n通过运行以下命令为 Apache APISIX 控制器添加最新的 helm chart repo:
\\nhelm repo add apisix https://charts.apiseven.com\\nhelm repo update\\n
\\n确保当前 kubectl 上下文指向正确的 Kubernetes 集群,然后运行以下命令:
\\nkubectl create namespace ingress-apisix\\n
\\n使用以下内容创建一个名为 dapr-annotations.yaml 的文件,以在 Apache APISIX Proxy Pod 上设置注释。
\\napisix:\\n podAnnotations:\\n dapr.io/enabled: \\"true\\"\\n dapr.io/app-id: \\" apisix-gateway\\"\\ndapr.io/app-port: \\"9080\\"\\ndapr.io/enable-metrics: \\"true\\"\\ndapr.io/metrics-port: \\"9099\\"\\ndapr.io/sidecar-listen-addresses: 0.0.0.0\\ndapr.io/config: ingress-apisix-config\\n
\\n\\n\\n注意:上面的 app-port 是告诉 daprd sidecar Proxy 在监听哪个端口。有关受支持的注释完整列表,可参考 Dapr Kubernetes pod 注释规范。
\\n
下面以我个人在 AKS 上安装的示例 dapr-annotations.yaml 进行展示。
\\n apisix:\\n podAnnotations:\\n dapr.io/app-id: apisix-gateway\\n dapr.io/app-port: \'9080\'\\n dapr.io/enable-metrics: \'true\'\\n dapr.io/enabled: \'true\'\\n dapr.io/metrics-port: \'9099\'\\ndapr.io/sidecar-listen-addresses: 0.0.0.0\\ndapr.io/config: ingress-apisix-config\\n\\ngateway:\\n type: LoadBalancer\\n\\ningress-controller:\\n enabled: true\\n\\ndashboard:\\n enabled: true\\n
\\n接下来运行以下命令(引用上述文件):
\\nhelm install apisix apisix/apisix -f dapr-annotations.yaml -n ingress-apisix\\n
\\n首先,配置 Apache APISIX upstream-apisix-dapr。
\\n在这里主机名填写:apisix-gateway-dapr,端口号填写 3500。
\\n{\\n \\"nodes\\": [\\n {\\n \\"host\\": \\"apisix-gateway-dapr\\",\\n \\"port\\": 3500,\\n \\"weight\\": 1\\n }\\n ],\\n \\"retries\\": 1,\\n \\"timeout\\": {\\n \\"connect\\": 6,\\n \\"read\\": 6,\\n \\"send\\": 6\\n },\\n \\"type\\": \\"roundrobin\\",\\n \\"scheme\\": \\"http\\",\\n \\"pass_host\\": \\"pass\\",\\n \\"name\\": \\"apisix-dapr\\"\\n}\\n
\\n然后配置 Apache APISIX 服务 apisix-gateway-dapr,上游服务选择 apisix-dapr。
\\n{\\n \\"name\\": \\"apisix-gateway-dapr\\",\\n \\"upstream_id\\": \\"376187148778341098\\"\\n}\\n
\\nHTTPBin 是以 Python+Flask 写的一款工具,这款工具涵盖了各类 HTTP 场景,且每个接口都有返回。接下来,我们使用 kennethreitz/httpbin 作为示例项目进行演示。
\\nkubectl apply -f 01.namespace.yaml\\nkubectl apply -f 02.deployment.yaml\\nkubectl apply -f 03.svc.yaml\\n
\\n上图为假设有一个使用 Dapr app-id kennethreitz-httpbin 运行的微服务。
\\n这里补充一下关于路径匹配的相关设置。比如请求网关是 /httpbin/,后端接收路径应该是 /,中间的 httpbin 只充当服务名的标识。
\\n在支持命名空间的托管平台上,Dapr 应用 ID 是符合有效的 FQDN 格式,其中包括目标名称空间。例如,以下字符串包含应用 ID (svc-kennethreitz-httpbin) 以及应用运行在命名空间(kind-test)。
\\n最后可以通过访问:http://20.195.90.43/httpbin/get 来查看代理是否成功。
\\n当然,在进行部署的过程中,也可以在 Kubernetes 中使用 Apache APISIX 官方 Helm 仓库直接部署 Apache APISIX 和 APISIX Ingress Controller。这样可以直接将 Apache APISIX 作为网关,进行 APISIX Ingress Controller 的数据面来承载业务流量。
\\n最后将 Dapr 通过 Sidecar annotations 注入到 Apache APISIX Proxy Pod,通过服务调用模块来调用集群中的微服务,实现完整流程部署。
\\n如项目结束,想要删除 Apache APISIX 控制器,可按下方命令操作(记得不要忘记删除之前创建的命名空间 ingress-apisix)。
\\nhelm delete apisix -n ingress-apisix\\n
\\n","description":"本质上,Apache APISIX 控制器将配置相同标准 Dapr annotations 以注入 daprd sidecar。通过公开这个 sidecar,将允许外部应用程序与集群中启用 Dapr 的应用程序进行通信。 下图为实际项目中的架构流程:\\n\\n基本项目概览\\nApache APISIX Ingress\\n\\n在 K8s 生态中,Ingress 作为表示 K8s 流量入口的一种资源,想要让其生效,就需要有一个 Ingress Controller 去监听 K8s 中的 Ingress 资源,并对这些资源进行相应规则的解析和实际承载流量。在当下趋势中,像…","guid":"https://www.apiseven.com/blog/dapr-with-apisix","author":"张善友","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-11-17T16:00:00.399Z","media":[{"url":"https://static.apiseven.com/202108/1637119221118-75dab9f1-4092-4684-ad23-34932d8a7eac.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637119221119-71bbe219-dd19-46be-90fb-20cd667d9805.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637119221120-15a5be20-17a2-4c18-a82e-91e1ff3709f0.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637119221106-e57ae8b8-38ed-46ea-b219-401619fadbe3.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637119221115-ae7c847a-99a3-4ee6-b36f-4269fd067198.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637119221110-9b901451-6ca6-4d15-b591-69f7c5d57ce1.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637119221114-90c1ef58-6743-419c-be87-9cdc8503aa30.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1637119221100-13997340-dfb6-45fb-abba-4215e0318238.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"APISIX-Datadog 插件发布,助力用户提高系统的可观测性","url":"https://www.apiseven.com/blog/apache-apisix-datadog-integration","content":"随着应用开发的复杂度增加,监控成为了应用的一个重要组成部分。及时、准确的监控既能满足快速迭代的周期性需求,又能够确保应用的稳定性和流畅性。如何选择一个适合的监控,以提升应用的可观测性,成为了每个开发者都必须面临的一道难题。
\\nApache APISIX 将监控和可观测性从应用中解耦了出来,给开发人员带来了一个优势:在构建应用的时候,只需要关注业务逻辑,而 Apache APISIX 可以和开发人员选定的监控平台对接,处理可观测性的问题。
\\nApache APISIX 最近发布了一个新的插件:APISIX-Datadog,以提供与 Datadog 监控平台的集成。这篇文章介绍了 APISIX-Datadog 插件的实现原理及功能。
\\nAPISIX-Datadog 插件将其自定义指标推送到 DogStatsD server。而 DogStatsD server 通过 UDP 连接与 Datadog agent 捆绑在一起。DogStatsD 是 StatsD 协议的一个实现。它为 Apache APISIX agent 收集自定义指标,将其聚合成一个数据点,并将其发送到配置的 Datadog server。要了解更多关于 DogStatsD 的信息,请访问 DogStatsD 文档。
\\n当你启用 APISIX-Datadog 插件时,Apache APISIX agent 会在每个请求响应周期向 DogStatsD server 输出以下指标:
\\n参数名称 | \\nStatsD 类型 | \\n描述 | \\n
---|---|---|
Request Counter | \\nCounter | \\n收到的请求数量。 | \\n
Request Latency | \\nHistogram | \\n处理该请求所需的时间,以毫秒为单位。 | \\n
Upstream latency | \\nHistogram | \\n上游 server agent 请求到收到响应所需的时间,以毫秒为单位。 | \\n
APISIX Latency | \\nHistogram | \\nAPISIX agent 处理该请求的时间,以毫秒为单位。 | \\n
Ingress Size | \\nTimer | \\n请求体大小,以字节为单位。 | \\n
Egress Size | \\nTimer | \\n响应体大小,以字节为单位。 | \\n
这些指标将被发送到 DogStatsD agent,并带有以下标签。如果任何特定的标签没有合适的值,该标签将被直接省略。
\\n参数名称 | \\n描述 | \\n
---|---|
route_name | \\n路由的名称,如果不存在,将显示路由 ID。 | \\n
service_id | \\n如果一个路由是用服务的抽象概念创建的,那么特定的服务 ID 将被使用。 | \\n
consumer | \\n如果路由有一个链接的消费者,消费者的用户名将被添加为一个标签。 | \\n
balancer_ip | \\n处理了当前请求的上游复制均衡器的的 IP。 | \\n
response_status | \\nHTTP 响应状态代码。 | \\n
scheme | \\n已用于提出请求的协议,如 HTTP、gRPC、gRPCs 等。 | \\n
APISIX-Datadog 插件维护了一个带有 timer 的 buffer。当 timer 失效时,APISIX-Datadog 插件会将 buffer 的指标作为一个批量处理程序传送给本地运行的 DogStatsD server。这种方法通过重复使用相同的 UDP 套接字,对资源的占用较少,而且由于可以配置 timer,所以不会一直让网络过载。
\\n如果你已经在使用 Datadog,你必须在系统中安装一个 Datadog agent。它可以是一个 docker 容器,一个 pod 或二进制的包管理器。你只需要确保Apache APISIX agent 可以到达 Datadog agent 的 8125 端口。
\\n\\n\\n如果需要了解更多关于如何安装一个完整的 Datadog agent,请访问这里。
\\n
如果你从没使用过 Datadog
\\nAPISIX-Datadog 插件只需要依赖 datadog/agent
的 dogstatsd 组件即可实现,因为该插件按照 statsd 协议通过标准的 UDP 套接字向 DogStatsD server 异步发送参数。我们推荐使用独立的 datadog/dogstatsd
镜像,而不是使用完整的datadog/agent
,因为 datadog/dogstatsd
的组件大小只有大约 11 MB,更加轻量化。而完整的 datadog/agent
镜像的大小为 2.8 GB。
运行以下命令,将它作为一个容器来运行:
\\n# pull the latest image\\ndocker pull datadog/dogstatsd:latest\\n# run a detached container\\ndocker run -d --name dogstatsd-agent -e DD_API_KEY=<Your API Key from step 2> -p 8125:8125/udp datadog/dogstatsd\\n
\\n如果你在生产环境中使用 Kubernetes,你可以将 dogstatsd
作为一个 Daemonset
或 Multi-Container Pod
与 Apache APISIX agent 一起部署。
如果你已经启动了 dogstatsd
agent,只需执行一条命令,就可以为指定路由启用 APISIX-Datadog 插件。
# enable plugin for a specific route\\ncurl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"plugins\\": {\\n \\"datadog\\": {}\\n },\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n }\\n },\\n \\"uri\\": \\"/hello\\"\\n}\'\\n
\\n启用 APISIX-Datadog 插件后,任何对端点 URI /hello
的请求都会产生上述指标,并推送到 Datadog agent的本地 DogStatsD server。
如果启用 APISIX-Datadog 插件时,使用的是默认配置,dogstatsd 服务在 127.0.0.1:8125
可用。如果你想更新配置,请更新插件的元数据。
参数名称 | \\n类型 | \\n是否必须修改 | \\n默认值 | \\n描述 | \\n
---|---|---|---|---|
hosts | \\nstring | \\n否 | \\n\\"127.0.0.1\\" | \\nDogStatsD server 的主机地址 | \\n
port | \\ninteger | \\n否 | \\n8125 | \\nDogStatsD server的主机端口 | \\n
namespace | \\nstring | \\n否 | \\n\\"apisix\\" | \\n由 APISIX agent发送的所有自定义参数的前缀。对寻找指标图的实体很有帮助,例如:(apisix.request.counter)。 | \\n
constant_tags | \\narray | \\n否 | \\n[\\"source:apisix\\"] | \\n静态标签嵌入到生成的指标中。对某些信号的 metrics 进行分组很有用。 | \\n
要了解更多关于如何有效地编写标签,请访问这里。
\\n向 /apisix/admin/plugin_metadata 端点发出请求,更新元数据,如下所示。
\\ncurl http://127.0.0.1:9080/apisix/admin/plugin_metadata/datadog -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"host\\": \\"127.0.0.1\\",\\n \\"port\\": 8125,\\n \\"constant_tags\\": [\\n \\"source:apisix\\",\\n \\"service:custom\\"\\n ],\\n \\"namespace\\": \\"apisix\\"\\n}\'\\n
\\n与元数据类似,在启用 APISIX-Datadog 插件时,你也可以调整其他参数。
\\n|参数名称|类型|是否必须修改|默认值|取值范围||描述|\\n|----|----|--------|-------|-----|-----------|\\n|batch_max_size|integer|否|5000|[1,...]|每个批次的 buffer 最大值|\\n|inactive_timeout|integer|否|5|[1,...]|如果不活跃,buffer 将被刷新的最长时间(秒)。|\\n|buffer_duration|integer|否|60|[1,...]|在必须处理一个批次之前,该批次中最老的条目的最长存活时间(秒)。|\\n|max_retry_count|integer|否|1|[1,...]|如果一个条目未能到达 dogstatsd server,重试的次数。|
\\n由于所有的字段都是可选的,如果你没有手动设置任何参数,APISIX-Datadog 插件将使用默认值设置这些参数。如果你需要更新任何参数,只需用更新的参数值更新所需的路由、服务或消费者。例如,下面的代码将 batch_max_size
修改为 10。
\'{\\n...\\n\\"plugins\\": {\\n \\"datadog\\": {\\n \\"batch_max_size\\": 10\\n }\\n}\\n... }\'\\n
\\n你只需在插件配置中删除相应的 json 配置即可停用 APISIX-Datadog 插件。得益于 Apache APISIX 插件的热加载机制,删除 json 配置后,会立即停用APISIX-Datadog 插件,不需要重新加载。
\\n# disable plugin for a route\\ncurl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\": \\"/hello\\",\\n \\"plugins\\": {},\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n }\\n }\\n}\'\\n
\\n","description":"随着应用开发的复杂度增加,监控成为了应用的一个重要组成部分。及时、准确的监控既能满足快速迭代的周期性需求,又能够确保应用的稳定性和流畅性。如何选择一个适合的监控,以提升应用的可观测性,成为了每个开发者都必须面临的一道难题。 Apache APISIX 将监控和可观测性从应用中解耦了出来,给开发人员带来了一个优势:在构建应用的时候,只需要关注业务逻辑,而 Apache APISIX 可以和开发人员选定的监控平台对接,处理可观测性的问题。\\n\\nApache APISIX 最近发布了一个新的插件:APISIX-Datadog,以提供与 Datadog…","guid":"https://www.apiseven.com/blog/apache-apisix-datadog-integration","author":"Bisakh Mondal","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-11-11T16:00:00.856Z","media":[{"url":"https://static.apiseven.com/202108/1636955062917-28911d71-0d56-48ec-85e5-a7908195da2f.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1636685752757-d02d8305-2a68-4b3e-b2cc-9e5410c8bf11.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1636685007445-05f134fd-e80a-4173-b1d7-f0a118087998.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"浅谈 Apache APISIX 的可观测性","url":"https://www.apiseven.com/blog/the-observability-of-apache-apisix","content":"可观测性是从系统外部去观察系统内部程序的的运行时状态和资源使用情况。衡量可观测性的主要手段包括:Metrics、Logging 和 Tracing,下图是 Metrics、Logging 和 Tracing 之间的关系。
\\n举个例子,Tracing 和 Logging 重合的部分代表的是 Tracing 在 request 级别产生的日志,并通过 Tracing ID 将 Tracing 和 Logging 关联起来。对这份日志进行一定的聚合运算之后,能够得到一些 Metrics。Tracing 自身也会产生一些 Metrics,例如调用量之间的关系。
\\nApache APISIX 拥有完善的可观测性能力:支持 Tracing 和 Metrics、拥有丰富的 Logging 插件生态、支持查询节点状态。
\\nApache APISIX 支持多种 Tracing 插件,包括:Zipkin、OpenTracing 和 SkyWalking。需要注意是: Tracing 插件默认处于关闭状态,使用前需要手动开启 Tracing 插件;Tracing 插件需要与路由或全局规则绑定,如果没有采样率的要求,建议与全局规则绑定,这样可以避免遗漏。
\\n在 Apache APISIX 中, Metrics 的相关信息通过 Prometheus Exporter上报,兼容 Prometheus 的数据格式。在 Apache APISIX 中使用 Prometheus Plugin 有两件事情需要注意。
\\n第一,请尽量提高路由、服务和上游这三者名称的可读性。
\\nPrometheus Plugin 中有一个名为 prefer_name
的参数,将这个参数的值设置为 true
时,即:prefer_name: true
,如果路由、服务和上游这三者的名称可读性比较强,这会带来一些好处:后续通过 Grafana 监控大屏展示参数的时候,不仅能够清楚地展示出所有的数据,还能够清晰地知晓这些数据的来源。如果 prefer_name
参数的值为 false
,则只会展示资源的 ID 作为数据来源,例如 路由 ID、上游 ID,进而造成监控大屏的可读性较低的问题。
第二,Prometheus Plugin 必须与路由或者全局规则绑定,然后才可以查看到指定资源的 Metrics。
\\n完成上述设置以后,Metrics 的数据会存储在 Prometheus 里面。由于 Prometheus 的存储性能很好,但展示性能欠佳,所以我们需要借助 Grafana Dashboard 展示数据。我们可以看到 Nginx 实例的 Metrics、网络带宽的 Metrics、路由和上游的 Metrics 等,详情如下图所示:
\\nApache APISIX 支持多种日志插件,可以与其他外部的平台直接分享日志数据。Error Log 插件支持 HTTP 与 TCP 协议,并且兼容 SkyWalking 的日志格式。也可以通过 FluentBit 等日志收集组件,将日志同步到日志平台进行处理。
\\nAccess Log 插件目前还不支持在日志格式里面进行嵌套。因为 Access Log 插件是路由级别的,所以需要跟路由进行绑定,才可以收集到路由的访问日志。但是日志的格式是全局的,而全局只能有一份日志格式。
\\nApache APISIX 的支持查询节点状态,启用之后,可以通过 /apisix/status
收集到节点的信息,包括节点数、等待链接数、处理连接数等。
上文讲到,Apache APISIX 的可观测性能力非常完善,能够收集 Metrics、Logging 和 Tracing 等信息。虽然借助 Apache APISIX 的内置插件配合 Grafana Dashboard,能够解决监控数据收集和指标可视化问题,但是各种数据分散在各个平台。期望有一个可观测性分析平台能集成 Metrics、Logging、Tracing 信息,能够将所有数据联动起来。
\\nApache SkyWalking 是一个针对分布式系统的应用性能监控(APM)和可观测性分析平台。它提供了多维度应用性能分析手段,从分布式拓扑图到应用性能指标、Trace、日志的关联分析与告警。
\\nApache SkyWalking 支持对接 Metrics、Logging、Tracing 等多种监控数据,兼容 Prometheus 数据模型,还可以通过 Log Analysis Language 进行二次聚合,产生新的 Metrics。
\\nApache SkyWalking 的 Dashboard 分为上下两个区域。上部是功能选择区域,下部是面板内容。Dashboard 提供全局、服务、示例、Endpoint 等多个实体维度的 Metrics 相关信息,支持以不同的视图展示可观测性。以全局视图为例,展示的 Metrics 包括:服务负载、慢服务数量、不健康的服务数量等,如下图所示。
\\n另外值得一说的是 SkyWalking Dashboard 的 Trace 视图。SkyWalking 提供了 3 种展现形式:列表、树状图和表格。Trace 视图是分布式追踪的典型视图,这些视图允许用户从不同角度查看追踪数据,特别是 Span 间的耗时关系。
\\nSkyWalking Dashboard 也支持拓扑图。拓扑图是根据探针上行数据分析出的整体拓扑结构。拓扑图支持点击展现和下钻单个服务的性能统计、Tracing、告警,也可以点击拓扑图中的关系线,展示服务之间、服务示例间的性能 Metrics。
\\nKubernetes 是一个开源的云原生容器化集群管理平台,目标是让部署容器化的应用简单且高效。Apache SkyWalking 后台可以部署在 Kubernetes 之中,而且得益于 Kubernetes 的高效率管理,可以保证 UI 组件的高可用性。
\\n如果在集群上部署了 Apache APISIX,Apache SkyWalking 支持以 sidecar 或服务发现的形式部署 SkyWalking Satellite,监控集群中的 Apache APISIX。
\\nApache APISIX 在未来仍会继续加强可观测性相关的功能支持,例如:
\\n解决 SkyWalking Nginx-Lua 插件的 peer 缺失问题
\\n支持在日志中打印 trace id
\\n接入访问日志
\\n支持网关元数据
\\n本文介绍了 Apache APISIX 的可观测性能力以及如何通过 Apache SkyWalking 提升Apache APISIX 的可观测性能力。未来两个社区还会继续深度合作,进一步增强 Apache APISIX 的可观测性能力。希望大家能够多多地参与到 Apache APISIX 和 Apache SkyWalking 项目中来。如果你对这两个开源项目很感兴趣,却不熟悉代码,写文章、做视频、对外分享、积极参与社区和邮件列表讨论都是很不错方式。
\\n","description":"可观测性是从系统外部去观察系统内部程序的的运行时状态和资源使用情况。衡量可观测性的主要手段包括:Metrics、Logging 和 Tracing,下图是 Metrics、Logging 和 Tracing 之间的关系。 举个例子,Tracing 和 Logging 重合的部分代表的是 Tracing 在 request 级别产生的日志,并通过 Tracing ID 将 Tracing 和 Logging 关联起来。对这份日志进行一定的聚合运算之后,能够得到一些 Metrics。Tracing 自身也会产生一些 Metrics,例如调用量之间的关系。…","guid":"https://www.apiseven.com/blog/the-observability-of-apache-apisix","author":"Haochao Zhuang","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-11-03T16:00:00.526Z","media":[{"url":"https://static.apiseven.com/202108/1635993536337-f8ee034d-ef3b-40b6-9886-ebde62d8edc6.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635993660940-9c9bbb0b-d5f1-4add-b93d-1f076de9aebd.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635993774170-ca3bf15d-9f55-42ac-9a2f-2d8955f74c5c.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635993914263-b7511acd-9bcf-49ca-aa32-911fc85acfac.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635993968588-403c9219-ae66-4b97-9eee-dcb97067b789.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Apache APISIX 扩展指南","url":"https://www.apiseven.com/blog/extension-guide","content":"Apache APISIX 提供了 50 多个插件、常用的几个负载均衡选择器,以及对主流服务发现(如 Nacos 和 DNS)的支持。API 网关和企业内部的业务紧密相关,为了满足企业的业务需求,用户通常需要在 Apache APISIX 的基础上添加一些代码,以实现业务所需的功能。如何拓展 Apache APISIX 成了许多用户的共同痛点:在保证 Apache APISIX 平稳运行的前提下,如何添加业务代码,满足实际需求?
\\n本文提供了 Apache APISIX 的拓展指南,旨在为用户提供拓展 Apache APISIX 的一些思路。由于 Apache APISIX 处于高速发展阶段,版本迭代的频率比较高,所以本文会以 Apache APISIX 的首个 LTS 版本 v2.10.0 为基础进行说明。如果你使用的 Apache APISIX 版本低于 2.10.0,可能需要结合实际情况做一些变通。另外,虽然本文只讲解了 HTTP 相关的逻辑,但是 TCP 相关的部分,大体上也较为相似。
\\n我们从请求的生命周期说起:当一个请求进入到 Apache APISIX 时,首先会由 http_access_phase
这个方法进行处理。熟悉 OpenResty phases 概念的读者可能会有些疑惑:OpenResty 一共有 6 个 phases,按照执行的先后顺序排列,分别是: rewrite
、 access
、 before_proxy
、 header_filter
、 body_filter
和 log
,为什么一上来就是 access
,rewrite
怎么不见了?
Apache APISIX 插件的 phases 概念和 OpenResty 的 phases 概念略有不同。为了提升 Apache APISIX 的性能,APISIX 插件的 rewrite 方法会在 OpenResty 的 access 阶段中运行。用户依然能够在插件层面自定义 rewrite
的逻辑,但是在代码层面,rewrite
实际上也是在 access
里面执行。
虽然说 rewrite
的逻辑和 access
的逻辑都在 access phase 里面运行,但是 rewrite
的逻辑还是会比 access
的逻辑先执行。为了避免后续插件执行 rewrite
失败后,没有继续执行 access
,导致 trace 遗漏的问题,必须在rewrite
里面添加 trace 的逻辑。
除了执行的先后顺序外,rewrite
和 access
之间还有一个差别,就是它们之间有一个处理 consumer
的逻辑:
plugin.run_plugin(\\"rewrite\\", plugins, api_ctx)\\n if api_ctx.consumer then\\n ...\\n end\\n plugin.run_plugin(\\"access\\", plugins, api_ctx)\\n
\\nconsumer
代表一种身份。你可以针对不同的 consumer
进行权限控制,比如使用 consumer-restriction
这个插件实现基于角色的权限控制,也就是大家所说的 RBAC。另外,你也可以给不同的 consumer
设置对应的限流策略。
Apache APISIX 里面的鉴权插件(在插件定义里面有 type = \\"auth\\"
),需要在 rewrite
阶段选好 consumer
。这里我们用 key-auth
插件举个例子:
local _M = {\\n version = 0.1,\\n priority = 2500,\\n type = \'auth\',\\n name = plugin_name,\\n schema = schema,\\n consumer_schema = consumer_schema,\\n}\\n\\n...\\nfunction _M.rewrite(conf, ctx)\\n ...\\n local consumer_conf = consumer_mod.plugin(plugin_name)\\n if not consumer_conf then\\n return 401, {message = \\"Missing related consumer\\"}\\n end\\n\\n local consumers = lrucache(\\"consumers_key\\", consumer_conf.conf_version,\\n create_consume_cache, consumer_conf)\\n\\n local consumer = consumers[key]\\n if not consumer then\\n return 401, {message = \\"Invalid API key in request\\"}\\n end\\n\\n consumer_mod.attach_consumer(ctx, consumer, consumer_conf)\\nend\\n
\\n鉴权插件的执行逻辑都是相似的:首先从用户输入中获取某组参数,然后根据参数查找对应的 consumer
,最后连同该插件对应的 consumer_conf
附加到 ctx
中。
综上,对于无需在请求早期阶段执行,且不需要查找 consumer
的插件,建议把逻辑写到 access
里面。
在执行完 access
之后,我们就要跟上游(Upstream)打交道了。通常情况下,上游节点是写死在 Upstream 配置上的。不过也可以从服务发现上获取节点来实现 discovery。
接下来我们会以 Nacos 为例,讲讲怎么实现。
\\n一个动态获取 Nacos 管理的节点的 Upstream 配置如下:
\\n{\\n \\"service_name\\": \\"APISIX-NACOS\\",\\n \\"type\\": \\"roundrobin\\",\\n \\"discovery_type\\": \\"nacos\\",\\n \\"discovery_args\\": {\\n \\"namespace_id\\": \\"test_ns\\",\\n \\"group_name\\": \\"test_group\\"\\n }\\n}\\n
\\n我们可以看到其中三个重要的变量:
\\ndiscovery_type
: 服务发现的类型,\\"discovery_type\\": \\"nacos\\"
表示使用 Nacos 实现服务发现。service_name
: 服务名称。discovery_args
: 不同的 discovery 特定的参数,Nacos 的特定参数包括:namespace_id
和 group_name
。Nacos discovery 对应的 Lua 代码位于 discovery/nacos.lua
。打开 nacos.lua
这个文件,我们可以看到它里面实现了几个所需的方法。
一个 discovery 需要实现至少两个方法:nodes
和 init_worker
。
function _M.nodes(service_name, discovery_args)\\n local namespace_id = discovery_args and\\n discovery_args.namespace_id or default_namespace_id\\n local group_name = discovery_args\\n and discovery_args.group_name or default_group_name\\n\\n ...\\nend\\n\\nfunction _M.init_worker()\\n ...\\nend\\n
\\n其中nodes
的函数签名已经明了地展示获取新节点所用的查询参数:service_name
和 discovery_args
。每次请求时,Apache APISIX 都会用这一组查询最新的节点。该方法返回的是一个数组:
{\\n {host = \\"xxx\\", port = 12100, weight = 100, priority = 0, metadata = ...},\\n # priority 和 metadata 是可选的\\n ...\\n}\\n
\\n而 init_worker
负责在后台启动一个 timer,确保本地的节点数据能跟服务发现的数据保持一致。
获取到一组节点后,我们要按照负载均衡的规则来决定接下来要先尝试哪个节点。如果常用的几种负载均衡算法满足不了需求,你也可以自己实现一个负载均衡。
\\n让我们以最少连接数负载均衡为例。对应的 Lua 代码位于 balancer/least_conn.lua
。打开 least_conn.lua
这个文件,我们可以看到它里面实现了几个所需的方法:new
、get
、after_balance
和 before_retry_next_priority
。
new
负责做一些初始化工作。
get
负责执行选中节点的逻辑。
after_balance
在下面两种情况下会运行:
before_retry_next_priority
则是在每次尝试完当前一组同 priority 的节点,准备尝试下一组之前运行。
function _M.new(up_nodes, upstream)\\n ...\\n\\n return {\\n upstream = upstream,\\n get = function (ctx)\\n ...\\n end,\\n after_balance = function (ctx, before_retry)\\n ...\\n if not before_retry then\\n if ctx.balancer_tried_servers then\\n core.tablepool.release(\\"balancer_tried_servers\\", ctx.balancer_tried_servers)\\n ctx.balancer_tried_servers = nil\\n end\\n\\n return nil\\n end\\n\\n if not ctx.balancer_tried_servers then\\n ctx.balancer_tried_servers = core.tablepool.fetch(\\"balancer_tried_servers\\", 0, 2)\\n end\\n\\n ctx.balancer_tried_servers[server] = true\\n end,\\n before_retry_next_priority = function (ctx)\\n if ctx.balancer_tried_servers then\\n core.tablepool.release(\\"balancer_tried_servers\\", ctx.balancer_tried_servers)\\n ctx.balancer_tried_servers = nil\\n end\\n end,\\n }\\nend\\n
\\n如果没有内部状态需要维护,可以直接借用固定的模板代码(上述代码中,位于省略号以外的内容)来填充 after_balance
和 before_retry_next_priority
这两个方法。
选中节点之后,我们也可以通过插件的形式添加额外的逻辑。插件可以实现 before_proxy
方法。该方法会在选中节点之后调用,我们可以在该方法里面记录当前选中的节点信息,这在 trace 里面会有用。
我们可以通过 response-rewrite
插件,在header_filter
和 body_filter
处理上游返回的响应。前一个方法是修改响应头,后一个方法修改响应体。注意 Apache APISIX 的响应处理是流式的,如果header_filter
里面没有修改响应头,响应头就会被先发送出去,到了body_filter
就没办法修改响应体了。
这意味着如果你后续想要修改body,但是 header 里面又有 Content-Length 之类跟 body 相关的响应头,那么就要提前在 header_filter
里面把这些头改掉。我们提供了一个辅助方法:core.response.clear_header_as_body_modified
,只需要在 header_filter
调用它就行。
body_filter
也是流式的,而且还会被多次调用。所以如果你想要获取完整的响应体,你需要把每次 body_filter
提供的部分响应体给拼起来。在 Apache APISIX master 分支上,我们提供了一个叫做 core.response.hold_body_chunk
的方法来简化操作,感兴趣的读者可以看看代码。
在请求结束之后,我们还可以通过 log
方法来做一些清场工作。这一类工作可以分成两类:
prometheus
插件。http-logger
插件。如果你感兴趣的话,可以看看这两个插件的 log
方法是怎么实现的:
prometheus
插件文档http-logger
插件文档在 K8s 生态中,Ingress 作为表示 K8s 流量入口的一种资源,想要让其生效,就需要有一个 Ingress Controller 去监听 K8s 中的 Ingress 资源,并对这些资源进行相应规则的解析和实际承载流量。
\\nAPISIX Ingress 则是基于 Apache APISIX 的 Ingress Controller 实现,实现了对 Kubernetes 的扩展,同时也支持 Ingress resource 的原生资源定义。
\\n\\n通过上图可以看到,APISIX Ingress 是在 Kubernetes 集群中部署,并代理 Kubernetes 外部集群的请求。然后将这些请求反向代理到 Kubernetes 集群 Service,同时也支持直接将服务推送到 Service Pod。
前边我们提到了 APISIX Ingress 是采用 Apache APISIX 作为实际承载业务流量的数据面,那么 Apache APISIX 项目又是做什么的呢?
\\nApache APISIX 是 Apache 基金会旗下的顶级开源项目,也是当前最活跃的开源网关项目,目前也通过中国信通院的可信开源项目认证。作为一个动态、实时、高性能的开源 API 网关,Apache APISIX 提供了负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。
\\n从上图框架可以看到,Apache APISIX 分为两部分,左侧数据面用来处理流量的反向代理,右侧控制面负责配置的分发。
\\nApache APISIX Ingress Controller 采用声明式的配置,经过内部处理后,最终会通过控制面的 Admin API 将数据同步到 etcd 中并传输给 Apache APISIX,实现 Apache APISIX 集群的配置同步。
\\n更多关于 Apache APISIX Ingress Controller 特性讲解点此查阅。
\\n关于 Apache APISIX Ingress 的使用场景或者产品对比优势等,在往期的分享中大都提及了很多。这次我们换个角度,从 Apache APISIX Ingress 的诞生及发展角度进行解析。
\\n2019 年我给 APISIX Ingress Controller 项目提供了第一行代码,2020 年 12 月份该项目被正式加入到 Apache 社区。在产品更新上,今年 6 月份我们发布了第一个 GA 版本,同时在刚刚过去的 10 月份中也发布了 1.3 版本,预计在今年 11 月份将会发布 1.4 版本,保证项目的正常更新迭代。
\\n上图是 Apache APISIX Ingress Controller 的贡献者增长曲线图。结合时间轴可以看到,从 2020 年 12 月加入 Apache 社区后,贡献者的人数增加速度呈现出高速稳定增长的态势。侧面反映出 Apache APISIX Ingress 得到了越来越多小伙伴的关注,并开始逐步应用到企业生产环境中。
\\n从个人项目或企业内部孵化出的项目开始到加入社区,前后环境的转换必然会导致项目工作方式的变化。加入社区后,Apache APISIX Ingress 在功能和项目整体度上得到了更多的支持与帮助。
\\n成为 Apache 软件基金会项目后,Apache APISIX Ingress Controller 项目变得更加开放。比如关于产品每一个特性的新增或者修改都必须经过一些公开的讨论,讨论的方式一般分为邮件列表讨论和 GitHub Issue 讨论。
\\n\\n
目前是上述两种讨论同时发起,尽可能多地让大家站在各自的使用场景以及使用角度去评判特性的合理性。因为这已不再是一个个人项目,而是一个社区项目,是多人参与的合作产出。
\\n同时,通过邮件列表和 GitHub Issue 的异步式讨论,可以更全面地收集到社区的反馈(不管是提问还是回答),在公开化的基础上为后续问题的搜索和整理提供了便利。
\\n在互动方面,Apache APISIX Ingress 吸取了一些其他社区的经验,开放了一个每两周进行的社区例会活动。
\\n这是一个新的渠道,我们希望让项目透明化的同时,也可以为社区小伙伴提供一个更生活化的渠道来一起讨论问题。
\\n通过这个双周例会,我们会给大家详细介绍最近两周项目发生了哪些变化,有哪些新的 issue 被提出以及哪些 PR 正在等待合并。当然也会跟大家一起讨论当前项目的一些问题或建议。
\\n我们希望这不仅是一个即时讨论的过程,更是一个分享和交流多角度事物观察的互动。
\\n具体关于双周例会的会议内容点此查阅,也可以点此查看往期例会回放。
\\n进入 Apache 社区后,另一个比较大的变化是项目规划上变得更加规范,不管是代码、测试还是版本发布。
\\n在代码层面,目前社区采用的是 Golang 代码规范,通过 Action CI 进行一些自动化检查。
\\n为了保证项目特性能够快速合并,并且不会引入新的 bug,在测试规范上我们也进行了相关要求。比如在特性开发过程中,一定要包含单元测试或者 e2e 测试,其中 e2e 测试集成了 gruntwork-io/terratest 以及 kubernetes-sigs/kind,用来构建 Kubernetes 测试环境。
\\n同时测试框架采用的是社区中广为接纳的 Ginkgo,测试用例的完善极大地保证了项目稳定性,同时也降低了项目的维护成本。
\\n在版本发布方面,目前也是严格遵循了 Apache 社区的发版规范。同时由于 APISIX Ingress Controller 也是属于 Kubernetes 的一个扩展,所以在涉及 CRD 的迭代部分也是按照 Kubernetes 的发版规则进行。
\\n除了上述提到的关于项目制度上的一些规范,走向社区的过程中,我们也收获了很多小伙伴们的「技术回馈」。
\\n这些贡献大都来源于社区小伙伴们平时在使用 APISIX Ingress 当中遇到的一些问题,或者场景上的一些完善,比如:
\\n更多特性点此查看。
\\n同时借助社区的反馈,我们也顺应大家的需求支持了多平台集成功能。
\\n在社区里得到功能加持的同时,也收获了关于 Apache APISIX Ingress 的使用场景上的丰富。
\\n最典型的一种方式是在 Kubernetes 集群内部进行部署,如下图就是一个典型的使用场景示意图。
\\n客户端经过外部 LB 后,经过 Apache APISIX 进行承接处理。Apache APISIX 作为网关也是一个反向代理,同时还可以部署在 Kubernetes 集群内外。
\\n上图的部署场景就是在 Kubernetes 内部集成 APISIX Ingress Controller,通过 APISIX Ingress Controller 将 Kubernetes 的声明式配置同步到 Apache APISIX。这样外部的请求就可以通过 Apache APISIX 集群数据面去直接代理后续 Upstream 的业务服务。
\\n苏州思必驰公司的用户为我们提供了关于跨集群使用场景,大体流程如下所示。
\\n在上图架构中有两个集群,即云主机正式集群和物理机集群。Apache APISIX Ingress Controller 在每一个集群内都有部署,在与 Kubernetes API server 交互的同时,通过 Apache APISIX Admin API 将配置同步到 Apache APISIX 集群。
\\n在跨集群场景时,主要是通过 Apache APISIX 来打通集群之间的互相访问。通常集群之间的访问分为专线和公网,借助 Apache APISIX 的健康检查功能,可以做到当专线或公网传输失败时自动将流量切换到其他正常通道上,保证了业务的稳定与高可用。
\\n该使用场景是将 APISIX Ingress Controller 部署在 Kubernetes 集群内部,与场景一不同的是这里有多个 Kubernetes 集群。但相应的 Apache APISIX 实际上是部署在所有 Kubernetes 集群外部,然后通过 Apache APISIX Ingress Controller 将各自集群的配置同步到总的 Apache APISIX 集群中。
\\n这样做的优势是可以通过一套 SLB Cluster 去完全控制各个 Kubernetes 集群,满足一些企业架构为多集群或跨机房的使用场景,减少业务流量上的转发次数。
\\n得益于以上收获成果,Apache APISIX Ingress 也得到了越来越多的关注,越来越多的企业也开始将 APISIX Ingress Controller 应用到自家产品中,比如中国移动、又拍云、有赞、观为智慧等多家企业。未来期待更多企业选择 Apache APISIX Ingress。
\\nApache APISIX Ingress 在不断迭代的过程中,也收到了很多社区小伙伴的一些建议,比如对未来产品的一些功能规划:
\\n目前 Kubernetes 社区里也有很多企业在做自己的 Ingress 项目支持,Kubernetes 社区为了能统一 Ingress 的设计,给出了 gateway API 的实现标准。一旦实现了这种标准,后续用户再使用 APISIX Ingress 时,就可以做到同一份配置在不同的 Ingress 里去使用,完美适配多方部署。
\\n目前社区里有一些声音会认为 Apache APISIX 所依赖的 etcd 实际上是一个有状态的服务,一旦涉及到有状态的服务,就需要额外去关注存储和迁移相关的工作。
\\n大家希望在容器化的云原生场景下,让 Apache APISIX 可以无缝扩容,所以后续也会去进行 Ingress Controller 单体架构的部署规划。在这种场景下,Apache APISIX 可以脱离 etcd 单独部署,声明式配置可以被 Apache APISIX Ingress Controller 监听并同步到 Apache APISIX。
\\n更多未来规划以及特性相关内容点此查阅。
\\n社区的发展是永无止境的,很感谢一路以来各位用户对 Apache APISIX Ingress Controller 的支持。希望大家在后续使用过程中,可以积极地参与和反馈关于 Apache APISIX Ingress Controller 项目的任何问题,让产品变得更优秀。
\\n","description":"概念篇 APISIX Ingress 概述\\n\\n在 K8s 生态中,Ingress 作为表示 K8s 流量入口的一种资源,想要让其生效,就需要有一个 Ingress Controller 去监听 K8s 中的 Ingress 资源,并对这些资源进行相应规则的解析和实际承载流量。\\n\\nAPISIX Ingress 则是基于 Apache APISIX 的 Ingress Controller 实现,实现了对 Kubernetes 的扩展,同时也支持 Ingress resource 的原生资源定义。\\n\\n通过上图可以看到,APISIX Ingress 是在…","guid":"https://www.apiseven.com/blog/progress-of-apisix-ingress","author":"金卫","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-10-26T16:00:00.237Z","media":[{"url":"https://static.apiseven.com/202108/1635304156040-50b7a2ae-ed0c-42ac-8517-edd0715e0082.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156053-68751f2e-40e7-4932-99a4-5b9cc8f60628.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156115-9d5e41d0-a8e9-4a6e-8a1a-757f3107a49a.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156111-d0b82a61-b304-42ce-8d3a-2b959d3cb271.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156102-8877f3da-a43d-4b94-9a84-a95743546112.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156096-c0eeb189-54f8-4ebe-b019-f41001869186.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156088-035cb0b0-8138-4e93-af5c-8e6ee8371f81.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156077-ced688eb-9dbf-4895-b7a2-acb2f4a288b2.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156072-ae9a3943-e686-4629-a5b7-0b5c38301139.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1635304156063-c7d879c6-8dfb-4ead-a88d-b5bdc9e453d6.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"教程篇:如何在 Apache APISIX Ingress Controller 中使用 Cert Manager 管理证书","url":"https://www.apiseven.com/blog/cert-manager-ingress","content":"Apache APISIX Ingress Controller 是一款以 Apache APISIX 作为数据面的 Kubernetes Ingress Controller 开源工具,目前已经更新到 v1.3 版本,实现了如证书管理、负载均衡、金丝雀发布等功能。
\\n长久以来,证书管理都不是一件简单的事情,虽然 Apache APISIX Ingress Controller 支持从 Kubernetes Secrets 资源中提取证书和私钥,并转换为 Apache APISIX 可识别的 SSL 对象,但这只是整个证书管理链中的一部分,证书的颁发、轮转、吊销逻辑依然需要管理员执行,尤其当证书数量比较多时,工作量往往并不小,因而会占用管理员不少的时间。
\\nCert Manager 是一款致力于在 Kubernetes 平台上简化证书管理的软件,它支持对接许多不同的证书源,如 Let’s Encrypt 和 HashiCorp Vault。
\\n如果你在使用 Apache APISIX Ingress Controller 时,遇到了证书管理的麻烦,那么使用 Cert Manager 将会是一个不错的选择,本文将介绍如何通过 Cert Manager 来创建证书并对接到 Apache APISIX Ingress Controller。
\\n如果你希望按照本文的指导进行实际的操作,请确保以下环境和工具已准备就绪:
\\n\\n\\n\\n请注意,下文所有的操作都将在 ingress-apisix 命名空间中执行,因此需要先创建该命名空间:
\\nkubectl create namespace ingress-apisix
我们可以通过 Helm 来安装 Apache APISIX Ingress Controller,包括数据面的 Apache APISIX 和 etcd 集群。
\\nhelm repo add apisix https://charts.apiseven.com\\nhelm repo update\\nhelm install apisix apisix/apisix --set gateway.tls.enabled=true --set ingress-controller.enabled=true --namespace ingress-apisix\\n
\\n点击查看详细安装介绍。
\\n通过 Helm 来安装 Cert Manager,点击可查看详细安装介绍。
\\nhelm install cert-manager jetstack/cert-manager --namespace ingress-apisix --set prometheus.enabled=false --set installCRDs=true\\n
\\n安装完毕后请等待一会后查看组件的运行状态,确保所有组件都已正常运行,你可以通过如下命令进行查看。
\\nkubectl get all -n ingress-apisix\\n
\\n返回结果如下所示,表示所有组件都已正常运行。
\\nNAME READY STATUS RESTARTS AGE\\npod/apisix-5d99956d88-j68sj 1/1 Running 0 63s\\npod/apisix-69459554d4-btnwn 0/1 Terminating 0 57m\\npod/apisix-etcd-0 1/1 Running 0 57m\\npod/apisix-etcd-1 1/1 Running 0 57m\\npod/apisix-etcd-2 0/1 Running 0 50s\\npod/apisix-ingress-controller-7b5c767cc7-j62hb 1/1 Running 0 55m\\npod/cert-manager-5ffd4f6c89-q9f7m 1/1 Running 0 45m\\npod/cert-manager-cainjector-748dc889c5-nrvkh 1/1 Running 0 45m\\npod/cert-manager-startupapicheck-kmgxf 0/1 Completed 0 45m\\npod/cert-manager-webhook-bc964d98b-mkjj7 1/1 Running 0 45m\\n\\nNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\\nservice/apisix-admin ClusterIP 10.96.16.25 <none> 9180/TCP 57m\\nservice/apisix-etcd ClusterIP 10.96.232.251 <none> 2379/TCP,2380/TCP 57m\\nservice/apisix-etcd-headless ClusterIP None <none> 2379/TCP,2380/TCP 57m\\nservice/apisix-gateway NodePort 10.96.118.75 <none> 80:32039/TCP,443:30107/TCP 57m\\nservice/apisix-ingress-controller ClusterIP 10.96.13.76 <none> 80/TCP 57m\\nservice/cert-manager-webhook ClusterIP 10.96.182.188 <none> 443/TCP 45m\\n\\nNAME READY UP-TO-DATE AVAILABLE AGE\\ndeployment.apps/apisix 1/1 1 1 57m\\ndeployment.apps/apisix-ingress-controller 1/1 1 1 57m\\ndeployment.apps/cert-manager 1/1 1 1 45m\\ndeployment.apps/cert-manager-cainjector 1/1 1 1 45m\\ndeployment.apps/cert-manager-webhook 1/1 1 1 45m\\n\\nNAME DESIRED CURRENT READY AGE\\nreplicaset.apps/apisix-5d99956d88 1 1 1 63s\\nreplicaset.apps/apisix-69459554d4 0 0 0 57m\\nreplicaset.apps/apisix-ingress-controller-74c6b5fbdd 0 0 0 57m\\nreplicaset.apps/apisix-ingress-controller-7b5c767cc7 1 1 1 55m\\nreplicaset.apps/apisix-ingress-controller-7d58db957c 0 0 0 55m\\nreplicaset.apps/cert-manager-5ffd4f6c89 1 1 1 45m\\nreplicaset.apps/cert-manager-cainjector-748dc889c5 1 1 1 45m\\nreplicaset.apps/cert-manager-webhook-bc964d98b 1 1 1 45m\\n\\nNAME READY AGE\\nstatefulset.apps/apisix-etcd 2/3 57m\\n\\nNAME COMPLETIONS DURATION AGE\\njob.batch/cert-manager-startupapicheck 1/1 6m24s 45m\\n
\\n\\n\\nKubernetes Controller Manager 的机制决定了 Pod 名称会有所不同。
\\n
首先我们需要配置证书颁发对象。
\\n# issuer.yaml\\napiVersion: cert-manager.io/v1\\nkind: Issuer\\nmetadata:\\n name: issuer\\n namespace: ingress-apisix\\nspec:\\n selfSigned: {}\\n
\\n并创建自签名证书颁发者。
\\nkubectl apply -f issuer.yaml\\n
\\n\\n\\n请注意,自签名颁发对象不推荐使用在生产环境中!更多证书颁发对象的配置请参考这里。
\\n
然后为域名 httpbin.org
创建一张证书。
# httpbin-cert.yaml\\napiVersion: cert-manager.io/v1\\nkind: Certificate\\nmetadata:\\n name: httpbin\\n namespace: ingress-apisix\\nspec:\\n secretName: httpbin\\n duration: 2160h # 90d\\n renewBefore: 360h # 15d\\n subject:\\n organizations:\\n - foo\\n commonName: httpbin.org\\n isCA: false\\n privateKey:\\n algorithm: RSA\\n encoding: PKCS1\\n size: 2048\\n usages:\\n - server auth\\n dnsNames:\\n - \\"httpbin.org\\"\\n - \\"*.httpbin.org\\"\\n issuerRef:\\n name: issuer\\n kind: Issuer\\n group: cert-manager.io\\n
\\nkubectl apply -f httpbin-cert.yaml\\n
\\n此时需要查看对应 Secrets 是否已经被创建。
\\nkubectl get secrets -n ingress-apisix httpbin\\nNAME TYPE DATA AGE\\nhttpbin kubernetes.io/tls 3 2m5s\\n
\\n通过上述验证,该 Secrets 对象的创建事件已经被 Apache APISIX Ingress Controller 捕获到,我们尝试访问 Apache APISIX Ingress Controller 来验证证书是否生效,首先我们需要创建额外的路由对象。
\\n# 创建后端\\nkubectl run httpbin --image kennethreitz/httpbin --namespace ingress-apisix\\nkubectl expose pod httpbin -n ingress-apisix --port 80\\n
\\n# 定义 ApisixTls 对象\\napiVersion: apisix.apache.org/v1\\nkind: ApisixTls\\nmetadata:\\n name: httpbin\\n namespace: ingress-apisix\\nspec:\\n hosts:\\n - httpbin.org\\n secret:\\n name: httpbin\\n namespace: ingress-apisix\\n---\\n# 定义访问后端的路由\\napiVersion: apisix.apache.org/v2beta1\\nkind: ApisixRoute\\nmetadata:\\n name: httpbin\\n namespace: ingress-apisix\\nspec:\\n http:\\n - name: httpbin\\n match:\\n paths:\\n - /*\\n hosts:\\n - httpbin.org\\n backends:\\n - serviceName: httpbin\\n servicePort: 80\\n
\\n接下来访问服务 apisix-gateway
。注意,默认情况下该服务的类型为 NodePort
,你可以根据需要修改其类型,比如你的 Kubernetes 集群是云厂商托管的,则可以考虑将其修改为 LoadBalancer
类型,以获取一个外部可达的 IP。
这里我们通过端口转发的方式将服务映射到本地。
\\nkubectl port-forward -n ingress-apisix svc/apisix-gateway 8443:443\\n
\\n然后开始配置访问。
\\ncurl https://httpbin.org:8443/json --resolve \'httpbin.org:8443:127.0.0.1\' -sk\\n{\\n \\"slideshow\\": {\\n \\"author\\": \\"Yours Truly\\",\\n \\"date\\": \\"date of publication\\",\\n \\"slides\\": [\\n {\\n \\"title\\": \\"Wake up to WonderWidgets!\\",\\n \\"type\\": \\"all\\"\\n },\\n {\\n \\"items\\": [\\n \\"Why <em>WonderWidgets</em> are great\\",\\n \\"Who <em>buys</em> WonderWidgets\\"\\n ],\\n \\"title\\": \\"Overview\\",\\n \\"type\\": \\"all\\"\\n }\\n ],\\n \\"title\\": \\"Sample Slide Show\\"\\n }\\n}\\n
\\n经过上述操作,可以看到访问成功,说明证书已经生效。注意,由于证书是自签名的,这里需要加上 -k
选项来忽略证书的校验。
此外,如果你想要轮转证书,删除 httpbin
这一 Secret 对象即可,Cert Manager 会立刻创建一个新的 httpbin Secret 对象,并且包含新的证书。
本文主要讲解了如何利用 Cert Manager 在 Apache APISIX Ingress Controller 中进行证书的创建和管理。想了解更多关于 Apache APISIX Ingress 的介绍与内容,可参考本篇文章。
\\n或者参与 Apache APISIX Ingress 项目每两周举行的线上讨论,分享当下项目进度、最佳实践及设计思路等多个话题,可查看具体 issue 了解更多。
\\n","description":"Apache APISIX Ingress Controller 是一款以 Apache APISIX 作为数据面的 Kubernetes Ingress Controller 开源工具,目前已经更新到 v1.3 版本,实现了如证书管理、负载均衡、金丝雀发布等功能。 长久以来,证书管理都不是一件简单的事情,虽然 Apache APISIX Ingress Controller 支持从 Kubernetes Secrets 资源中提取证书和私钥,并转换为 Apache APISIX 可识别的 SSL 对象,但这只是整个证书管理链中的一部分,证书的颁发、轮转…","guid":"https://www.apiseven.com/blog/cert-manager-ingress","author":"张超","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-10-21T16:00:00.532Z","media":null,"categories":null,"attachments":null,"extra":null,"language":null},{"title":"保姆级教程,从概念到实践帮你快速上手 Apache APISIX Ingress","url":"https://www.apiseven.com/blog/apisix-ingress-details","content":"在 K8s 生态中,Ingress 作为表示 K8s 流量入口的一种资源,想要让其生效,就需要有一个 Ingress Controller 去监听 K8s 中的 Ingress 资源,并对这些资源进行相应规则的解析和实际承载流量。在当下趋势中,像 Kubernetes Ingress Nginx 就是使用最广泛的 Ingress Controller 实现。
\\n而 APISIX Ingress 则是另一种 Ingress Controller 的实现。跟 Kubernetes Ingress Nginx 的区别主要在于 APISIX Ingress 是以 Apache APISIX 作为实际承载业务流量的数据面。如下图所示,当用户请求到具体的某一个服务/API/网页时,通过外部代理将整个业务流量/用户请求传输到 K8s 集群,然后经过 APISIX Ingress 进行后续处理。
\\n从上图可以看到,APISIX Ingress 分成了两部分。一部分是 APISIX Ingress Controller,作为控制面它将完成配置管理与分发。另一部分 APISIX Proxy Pod 负责承载业务流量,它是通过 CRD(Custom Resource Definitions) 的方式实现的。Apache APISIX Ingress 除了支持自定义资源外,还支持原生的 K8s Ingress 资源。
\\n前边我们提到了 APISIX Ingress 是采用 Apache APISIX 作为实际承载业务流量的数据面,那么 Apache APISIX 项目又是做什么的呢?
\\nApache APISIX 是 Apache 基金会旗下的顶级开源项目,也是当前最活跃的开源网关项目。作为一个动态、实时、高性能的开源 API 网关,Apache APISIX 提供了负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。
\\nApache APISIX 可以帮助企业快速、安全地处理 API 和微服务流量,比如限流认证、日志安全功能,以及支持丰富的自定义插件。目前也与很多开源项目如 Apache SkyWalking、Prometheus 等之类的组件进行了相关集成。
\\n因为本人同时参与到了 APISIX Ingress 与 K8s Ingress Nginx 两个项目的开发和维护,所以很多人也会问我,这两个项目做比较的话,到底该如何选择?或者说为什么有了 K8s Ingress Nginx 还要再做 APISIX Ingress。
\\n在 APISIX Ingress 中,我们增加了一些丰富且灵活的配置,比如通过单个配置文件去实现灰度部署。但在 K8s Ingress Nginx 中去实现如上效果的话,最少也需要有两个 Ingress 资源文件才可以完成。
\\n在丰富度上,由于 Apache APISIX 本身的自带功能丰富且允许多种插件扩展使用,所以使用 APISIX Ingress 就可以省去自己额外配置功能的繁琐步骤,可以将更多的时间投入到实际开发中。
\\nAPISIX Ingress 采用了数据面与控制面的分离架构,所以用户可以选择将数据面部署在 K8s 集群内部/外部。但 K8s Ingress Nginx 是将控制面和数据面放在了同一个 Pod 中,如果 Pod 或控制面出现一点闪失,整个 Pod 就会挂掉,进而影响到业务流量。
\\n这种架构分离,给用户提供了比较方便的部署选择,同时在业务架构调整场景下,也方便进行相关数据的迁移与使用。
\\n由于 Apache APISIX 是一个全动态的高性能网关,所以在 APISIX Ingress 自身就支持了全动态,包括路由、SSL 证书、上游以及插件等等。
\\n同时 APISIX Ingress 还具有以下特性:
\\n以下我们将从 CRD 与自定义资源层面进行详细的介绍。
\\n在前面的介绍中我们提到了 CRD,那么 APISIX Ingress 是如何使用 CRD 扩展的?
\\n从用户层面来看,当 Client 发起请求,到达 Apache APISIX 后,会直接把相应的业务流量传输到后端(如 Service Pod),从而完成转发过程。此过程不需要经过 Ingress Controller,这样做可以保证一旦有问题出现,或者是进行变更、扩缩容或者迁移处理等,都不会影响到用户和业务流量。
\\n同时在配置端,用户通过 kubectl apply,可将自定义 CRD 配置应用到 K8s 集群。Ingress Controller 会持续 watch 这些资源变更,来将相应配置应用到 Apache APISIX。
\\nAPISIX Ingress 目前已经支持的自定义资源主要是以下 5 类,涉及到路由、上游、消费者、证书相关和集群公共配置的相关类别。
\\n自定义资源 APISIX Route 中 spec
属性的顶级配置是 http
。但其实 spec
是同时支持两种配置的,一种是下图示例的 spec.http
,主要用于 7 层代理;另一种是 spec.stream
,用于 4 层代理。在配置文件中,我们首先为其自定义了一项规则,即 match 下的相关参数。
如上图后端配置示例使用了同一个 Service,实际使用中大家根据场景进行调整即可。需要注意的是,weight
属性是用来配置相关 Service 权重。通过以上配置,从而实现一套完整的路由自定义资源。
在配置 APISIX Upstream 时,需要注意 name
的内容要与 K8s 集群的 Service 保持一致,这样可以保证后续 APISIX Ingress Controller 准确匹配其相应流量。
在配置文件中,spec.loadbalancer
主要负责负载均衡策略的设置,有多种策略模式可供选择。spec.schem
e 则是协议类型的配置,目前只支持 HTTP 和 gRPC 协议。spec.healthCheck
主要是对健康检查功能进行设置,比如设置其活跃状态、生效协议与路径和最终反馈等参数配置。
在 APISIX Consumer 配置中,主要是增加了认证相关的功能,比如 spec.authParameter
,目前该配置参数支持 BasicAuth
与 KeyAuth
这两种比较常见的认证类型。
通过 value
可直接去配置相关的 username
和 password
,或者直接使用 secret
进行配置,相比前者的明文配置会更安全一些。
APISIX TLS 主要是为了进行证书的管理。如示例所示,用户可以通过 hosts
来配置多个域名,secret
下的参数就是对应的配置证书。
同时 APISIX TLS 还配有 spec.client
,用于进行 mTLS 双向认证的配置。
关于自定义资源支持的 Config 类型我们会从两个方面进行描述。
\\n一种是 APISIX Cluster Config,它主要用于一些通用配置。目前支持在 K8s 或者 Apache APISIX 中全局使用 Prometheus 插件/全局配置 SkyWalking,后续开发中也会去增加一些其他的通用配置。
\\n另一种就是我们现在正在 PR 中的 APISIX Plugin Config。大家如果感兴趣的话,也可以点击链接来一起参与讨论。Plugin Config 主要是将通用的插件配置统一集合在一起,比如一些同样的配置,用户就可以通过 APISIX Plugin Config 同时应用在多个路由当中,省去了额外多项独立配置的繁琐步骤。
\\n目前大家可以通过 Helm Charts 的方式来进行 APISIX Ingress 的部署。通过一条命令,就可以同时把 Apache APISIX 以及 APISIX Ingress,包括 Apache APISIX 所需要用到的 etcd 全部部署好,步骤非常简单。
\\n通过使用 APISIX Ingress 可以实现按比例进行流量切分的效果,具体操作如下:
\\n通过在 backends
中去配置 subset
和 weight
,来实现用户请求流量进入时的分流。如下图示例就是 90% 的流量会进入到 v1 中,10% 的流量进入到 v2 中。
通过以上两步,就可以十分方便地按比例进行流量切分,实现类似灰度发布等场景需求。\\n更多具体操作细节也可参考:Apache APISIX Ingress Controller 中的流量切分。
\\n如果想在 APISIX Ingress 中为某些路由配置 Basic Auth,可以参考如下操作:
\\n如前文所提到的,可以在 APISIX Consumer 配置中增加 basicAuth
,并为其指定用户名和密码。
在自定义资源 APISIX Route 中,通过在后端添加 authenticatio
n,将其开启并指定认证类型即可。
通过以上步骤,就可以实现使用 Consumer 去完成相关配置认证。
\\n正如我们在开头提到过的,APISIX Ingress 不仅支持自定义资源,还同时支持 K8s 原生的 Ingress 资源。
\\n如上图是 K8s Ingress 资源。通常情况下如果想要在资源上做 rewrite,可以通过增加 annotation 配置属性。这样当用户携带 httpbin.org
请求时,就可以通过路径 /sample 将它重定向到 /ip。
当上述需求使用 APISIX Ingress 时,只需在 Ingress 增加一个 kubernetes.io/ingress.class: apisix
,去指定 APISIX Ingress Controller 去监听这个资源,同时通过配置 k8s.apisix.apache.org/rewrite-target: \\"/ip\\"
,就可以完成重定向到 /ip 路径。
以上示例只是目前 APISIX Ingress 对于原生 K8s Ingress 支持的一种方式,更多示例大家可以查看具体文档进行参考使用。
\\n之后 APISIX Ingress 将会继续在功能与生态上进行更新,目前阶段已经完成了 APISIX Ingress 与 Cert-manager 集成,后续将逐步实现以下目标:
\\n最后也希望大家能够多多地参与到项目中来,比如每两周的周三下午 2 点都会有一次 APISIX Ingress 社区会议,会跟大家同步一下当前的项目进展或者遇到的问题。大家可以持续关注 Apache APISIX 视频号,届时可以直接参与社区会议直播。
\\n点此查看更多关于 APISIX Ingress 社区会议细节。
\\n","description":"Apache APISIX Ingress 概览 Apache APISIX Ingress 定义\\n\\n在 K8s 生态中,Ingress 作为表示 K8s 流量入口的一种资源,想要让其生效,就需要有一个 Ingress Controller 去监听 K8s 中的 Ingress 资源,并对这些资源进行相应规则的解析和实际承载流量。在当下趋势中,像 Kubernetes Ingress Nginx 就是使用最广泛的 Ingress Controller 实现。\\n\\n而 APISIX Ingress 则是另一种 Ingress Controller 的实现。跟…","guid":"https://www.apiseven.com/blog/apisix-ingress-details","author":"张晋涛","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-10-08T16:00:00.902Z","media":[{"url":"https://static.apiseven.com/202108/1633765366863-8964a75c-0c16-4683-ad9b-c8c83ac64ec6.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765402660-6b20dd1c-bef6-4dcb-974e-fa80334e0623.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765449155-0e25f1d0-e62a-4c4f-ab9a-019f609ed5fb.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765501091-e64ff6e5-5e3e-4b0f-adcc-7ff418edb52c.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765534667-3ce978ae-2d85-4de7-8a57-3c5be5f57604.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765580844-9d17d699-fa45-4b43-9ed9-f8ea9c9cab48.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765614989-88b363c2-3805-4159-abfc-bac1b055559b.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765647605-6ad1ba44-06fd-475d-a6ae-925b3cc9c1ce.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765686788-156b0641-aa78-4de8-833d-a187772470a5.png","type":"photo"},{"url":"https://static.apiseven.com/2022/09/19/632828d22987f.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765771090-1e51e66c-0979-43b4-852b-28f2284a5d4e.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765803898-7a30c663-7ba8-4064-8772-a19c56cef191.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765828596-9a0f0142-f201-4004-b85d-a34de4ee13dc.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765859904-bc48dcc5-cd7a-4875-b248-5c4c64a2d7c5.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1633765888876-d2d252ee-706c-49f3-b630-03a7e72a0620.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Python 助你快速上手 Apache APISIX 插件开发","url":"https://www.apiseven.com/blog/python-helps-you-quickly-with-apache-apisix-plugin-development","content":"在 Apache APISIX Python Runner
之前社区中已经支持了 Java\\n和 Go 语言的 Runner
,今天 Python Runner
\\n也来了,社区中的小伙伴们在开发 Apache APISIX
的插件时又多了一种新选择。
Apache APISIX
是一个高性能的云原生开源 API 网关,它可以对请求进行统一的拦截和治理(如:鉴权、认证、缓存、版本、熔断、审计 等等)帮助开发人员轻松的对外提供安全可靠的服务,而开发人员通过 Apache APISIX
\\n的加持只需要关注业务实现即可,省去了大量花费在通用能力上的开发与维护上的时间并且也降低了整体业务架构的复杂度。
Python
语言作为一个解释型的高级编程语言,它 语法简洁易上手
、代码可读性好
,在 跨平台
、可移植性
、开发效率
\\n上都有很好的表现,同时作为一个高级编程语言它的封装抽象程度比较高屏蔽了很多底层细节(例如:GC
\\n)让我们在开发的过程中可以更专注应用逻辑的开发。Python
作为一个有 30 年历史的老牌开发语言,它的生态以及各种模块已经非常完善,我们大部分的开发和应用场景都可以从社区中找到很成熟的模块或解决方案。Python
\\n其他的优点就不再一一赘述。Python
的缺点也比较明显:Python
作为一门解释性语言,相较于 C++
和 Go
这样的编译型语言,在性能上的差距还是比较大的。
apache-apisix-python-runner 这个项目可以理解为 Apache APISIX
\\n和 Python
\\n之间的一道桥梁,通过 Python Runner
可以把 Python
直接应用到 APISIX
的插件开发中,最重要的还是希望让更多对 Apache APISIX
和 API 网关
感兴趣的 Python开发者
\\n通过这个项目更多的了解使用 Apache APISIX
,以下为 Apache APISIX
多语言支持的架构图。
上图左边是 Apache APISIX
的工作流程,右边的 Plugin Runner
是各语言的插件运行器,本文介绍的 apisix-python-plugin-runner
就是支持 Python
\\n语言的 Plugin Runner
。
当你在 Apache APISIX
中配置一个 Plugin Runner
时,Apache APISIX
会启动一个子进程运行 Plugin Runner
,该子进程与 Apache APISIX
\\n进程属于同一个用户,当我们重启或重新加载 Apache APISIX
时,Plugin Runner
也将被重启。
如果你为一个给定的路由配置了 ext-plugin-*
插件,请求命中该路由时将触发 Apache APISIX
通过 Unix Socket
向 Plugin Runner
发起 RPC
调用。调用分为两个阶段:
Apache APISIX
内置插件(Lua 语言插件)之前Apache APISIX
内置插件(Lua 语言插件)之后大家可以根据需要选择并配置 Plugin Runner
的执行时机。
Plugin Runner
会处理 RPC
调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
多语言插件的执行顺序是在 ext-plugin-*
插件配置项中定义的,像其他插件一样,它们可以被启用并在运行中重新定义。
Apache APISIX
\\n的安装部署本文不在过多赘述,详情请参考 Apache APISIX 官方文档:如何构建 Apache APISIX\\n进行部署。
$ git clone https://github.com/apache/apisix-python-plugin-runner.git\\n$ cd apisix-python-plugin-runner\\n$ make install\\n
\\n$ cd /path/to/apisix-python-plugin-runner\\n$ APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock python3 apisix/main.py start\\n
\\n$ vim /path/to/apisix/conf/config.yaml\\napisix:\\n admin_key:\\n - name: \\"admin\\"\\n key: edd1c9f034335f136f87ad84b625c8f1\\n role: admin\\next-plugin:\\n path_for_test: /tmp/runner.sock\\n
\\n$ vim /path/to/apisix/conf/config.yaml\\napisix:\\n admin_key:\\n - name: \\"admin\\"\\n key: edd1c9f034335f136f87ad84b625c8f1\\n role: admin\\next-plugin:\\n cmd: [ \\"python3\\", \\"/path/to/apisix-python-plugin-runner/apisix/main.py\\", \\"start\\" ]\\n
\\n如果需要对 Log Level
或 Unix Domain Socket
环境变量调整可以修改 Runner
的配置文件
$ vim /path/to/apisix-python-plugin-runner/apisix/config.yaml\\nsocket:\\n file: $env.APISIX_LISTEN_ADDRESS # Environment variable or absolute path\\nlogging:\\n level: debug # error warn info debug\\n
\\n$ cd /path/to/apisix\\n# Start or Restart\\n$ ./bin/apisix [ start | restart ]\\n
\\n启动或重启 APISIX
即可,此时 APISIX
和 Python Runner
已经完成配置并启动。
# 使用默认demo插件进行测试\\n$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\": \\"/get\\",\\n \\"plugins\\": {\\n \\"ext-plugin-pre-req\\": {\\n \\"conf\\": [\\n { \\"name\\": \\"stop\\", \\"value\\":\\"{\\\\\\"body\\\\\\":\\\\\\"hello\\\\\\"}\\"}\\n ]\\n }\\n },\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n }\\n }\\n}\'\\n
\\nplugins.ext-plugin-pre-req.conf
为 Runner
插件配置,conf
为数组格式可以同时设置多个插件。name
为插件名称,该名称需要与插件代码文件和对象名称一直。value
为插件配置,可以为 JSON
字符串。$ curl http://127.0.0.1:9080/get -i\\nHTTP/1.1 200 OK\\nDate: Fri, 13 Aug 2021 13:39:18 GMT\\nContent-Type: text/plain; charset=utf-8\\nTransfer-Encoding: chunked\\nConnection: keep-alive\\nhost: 127.0.0.1:9080\\naccept: */*\\nuser-agent: curl/7.64.1\\nX-Resp-A6-Runner: Python\\nServer: APISIX/2.7\\nHello, Python Runner of APISIX\\n
\\n/path/to/apisix-python-plugin-runner/apisix/plugins\\n
\\n此目录中的 .py
文件将会被自动加载。
/path/to/apisix-python-plugin-runner/apisix/plugins/stop.py\\n/path/to/apisix-python-plugin-runner/apisix/plugins/rewrite.py\\n
\\nfrom apisix.runner.plugin.base import Base\\nfrom apisix.runner.http.request import Request\\nfrom apisix.runner.http.response import Response\\nclass Stop(Base):\\n def __init__(self):\\n \\"\\"\\"\\n Example of `stop` type plugin, features:\\n This type of plugin can customize response `body`, `header`, `http_code`\\n This type of plugin will interrupt the request\\n \\"\\"\\"\\n super(Stop, self).__init__(self.__class__.__name__)\\n def filter(self, request: Request, response: Response):\\n \\"\\"\\"\\n The plugin executes the main function\\n :param request:\\n request parameters and information\\n :param response:\\n response parameters and information\\n :return:\\n \\"\\"\\"\\n # 在插件中可以通过 `self.config` 获取配置信息,如果插件配置为JSON将自动转换为字典结构\\n # print(self.config)\\n # 设置响应头信息\\n headers = request.headers\\n headers[\\"X-Resp-A6-Runner\\"] = \\"Python\\"\\n response.headers = headers\\n # 设置响应体信息\\n response.body = \\"Hello, Python Runner of APISIX\\"\\n # 设置响应状态码\\n response.status_code = 201\\n # 通过调用 `self.stop()` 中断请求流程,此时将立即响应请求给客户端\\n # 如果未显示调用 `self.stop()` 或 显示调用 `self.rewrite()`将继续将请求\\n # 默认为 `self.rewrite()`\\n self.stop()\\n
\\nBase
类filter
函数filter
函数参数只能包含 Request
和 Response
类对象作为参数Request
对象参数可以获取请求信息Response
对象参数可以设置响应信息self.config
可以获取插件配置信息filter
函数中调用 self.stop()
时将马上中断请求,响应数据。filter
函数中调用 self.rewrite()
时,将会继续请求。目前 Apache APISIX
各语言的 Runner
还处于早期开发阶段,我们会陆续完善其功能。成功的开源项目离不开大家的参与和贡献,欢迎各位参与 Apache APISIX Runner
\\n的开发,让我们一起共建 Apache APISIX
与各语言的桥梁。
身份认证在日常生活当中是非常常见的一项功能,大家平时基本都会接触到。比如用支付宝消费时的人脸识别确认、公司上班下班时的指纹/面部打卡以及网站上进行账号密码登录操作等,其实都是身份认证的场景体现。
\\n如上图,Jack 通过账号密码请求服务端应用,服务端应用中需要有一个专门用做身份认证的模块来处理这部分的逻辑。请求处理完毕子后,如果使用 JWT Token 认证方式,服务器会反馈一个 Token 去标识这个用户为 Jack。如果登录过程中账号密码输入错误,就会导致身份认证失败。这个场景大家肯定都非常熟悉,这里就不做展开举例了。
\\n身份认证确保了后端服务的安全性,避免了未经授权的访问,从而确保数据的安全性。比如防止某些黑客攻击,以及一些恶意调用,这些都可以通过身份认证进行阻拦。
\\n从实用性的角度考虑,它可以更方便地记录操作者或调用方。比如上班打卡其实就是通过记录「谁进行了这项操作」来统计员工上班信息。
\\n其次它可以记录访问频率及访问频次。例如记录某用户在最近几分钟中发起请求的频率和频次,可以判断这个用户活跃程度,也可以判断是否为恶意攻击等。
\\n在功能层面,它通过识别身份可以对不同的身份进行不同权限的操作处理。比如在公司里,你的身份权限无法使用某些页面或服务。再细致一点,对不同身份或者不同的 API 接口调用方做一些相关技术上的限制策略,如限流限速等,以此来达到根据不同的用户(调用方)采取不同的功能限制。
\\n如下图所示,左侧的图为我们展示了一种比较常见的传统身份认证方法。每一个应用服务模块去开发一个单独的身份认证模块,用来支持身份认证的一套流程处理。但当服务量多了之后,就会发现这些模块的开发工作量都是非常巨大且重复的。
\\n这种时候,我们可以通过把这部分的开发逻辑放置到 Apache APISIX 的网关来实现统一,减少开发量。
\\n图右所示,用户或应用方直接去请求 Apache APISIX,然后 Apache APISIX 通过识别并认证通过后,会将鉴别的身份信息传递到上游应用服务。之后上游应用服务就可以从请求头中读到这部分信息,然后进行后续相关工作的处理。
\\n讲完了大概流程,我们来详细罗列下。
\\n如上图是一张 APISIX-Dashboard 的界面截图,可以看到路由、Consumer 等数据信息。这里的 Consumer 可以理解为一个应用方,比如可以为应用专门去创建一个 Consumer 并配置相关的认证插件,例如 JWT、Basic-Auth 等插件。当有新的服务出现时,我们需要再创建一个 Consumer,然后将这部分配置信息给配置到第二个应用服务上。
\\n通过集中式身份认证,可以将客户配置进行收敛并统一管理,达到降低运维成本的效果。
\\nApache APISIX 作为一个 API 网关,目前已开启与各种插件功能的适配合作,插件库也比较丰富。目前已经可与大量身份认证相关的插件进行搭配处理,如下图所示。
\\n基础认证插件比如 Key-Auth、Basic-Auth,他们是通过账号密码的方式进行认证。
\\n复杂一些的认证插件如 Hmac-Auth、JWT-Auth。如 Hmac-Auth 通过对请求信息做一些加密,生成一个签名。当 API 调用方将这个签名携带到 Apache APISIX 的网关 Apache APISIX 会以相同的算法计算签名,只有当签名方和应用调用方认证相同时才予以通过。
\\nAuthz-casbin 插件是目前 Apche APISIX 与 Casbin 社区正在进行合作开发的一个项目,它的应用原理是按照 Casbin 的规则,去处理一些基于角色的权限管控 (RBAC),进行 ACL 相关操作。
\\n其他则是一些通用认证协议和联合第三方组件进行合作的认证协议,例如 OpenID-Connect 身份认证机制,以及 LDAP 认证等。
\\n功能强大该如何理解,就是 Apache APISIX 中可以针对每一个 Consumer (即调用方应用)去做不同级别的插件配置。
\\n如上图,我们创建了两个消费者 Consumer A,Consumer B。我们将 Consumer A 应用到应用1
,则后续应用1
的访问将会开启 Consumer A 的这部分插件,例如 IP 黑白名单,限制并发数量等。将 Consumer B 应用到应用2
,由于开启了 http-log 插件,则应用2
的访问日志将会通过 HTTP 的方式发送到日志系统进行收集。
关于 Apache APISIX 身份认证的玩法,这里为大家提供三个阶段的玩法推荐,大家仅作参考,也可以在这些基础上,进行更深度的使用和应用。
\\n普通玩法推荐大家基于 Key-Auth、Basic-Auth、JWT- Auth 和 Hmac-Auth 进行,这些插件的使用需要与 Consumer 进行关联使用。
\\n创建路由,配置上游为 httpbin.org
,同时开启 basic-auth
插件。
创建消费者 foo。在消费者中,我们需要配置用户的认证信息,例如 username
为 foo,password
为 bar
。
应用携带 username:foo
,password: bar
访问 Apache APISIX。Apache APISIX 通过认证,并将请求 Authorization 请求头携带至上游 httpbin.org
。由于 httpbin.org
中 get 接口会将请求信息返回,因此我们可以在其中观察到请求头 Authorization
。
进阶模式下,是使用 Apache APISIX 与 OpenID-Connect 插件进行对接第三方认证服务。OpenID-Connect 是一种认证机制,可以采用该认证机制对接用户的用户管理系统或者用户管理服务,例如国内的 Authing 和腾讯云,国外的 Okta 和 Auth0 等。
\\n具体操作如下,这里使用 Okta 云服务举例:
\\n在 Okta 控制台页面创建一个支持 OpenID-Connect 的应用。
\\n创建路由,配置访问的上游地址为 httpbin.org,同时开启 openid-connect 插件,将 Okta 应用的配置填写到 openid-connect 插件中。
\\n此时,当用户访问 Apache APISIX 时,会先重定向到 Okta 登录页面。此时需要在该页面填写 Okta 中已经存在的用户的账号密码。登陆完成之后,Apache APISIX 会将本次认证的 Access-Token,ID-Token 携带至上游,同时将本次认证的用户信息以 base64 的方式编码至 Userinfo 请求头,传递至上游。
\\n这里提供的 DIY 玩法是利用了 Serverless 插件,这款插件功能丰富,玩法也非常多。大家如果有自己的使用玩法,也欢迎在社区内进行交流。
\\n具体操作流程就是将自己的代码片段通过 Serverless 插件上传到 Apache APISIX,这个过程中 Serverless 插件支持动态配置和热更新。
\\n通过请求头、参数等相关信息,来进行一些判断。通过这种做法,我们可以去实现自己的一些规则,比如说结合企业内部的一些认证,或者去写一些自己的业务逻辑。
\\n通过 HTTP 库发起一个 HTTP 请求,我们可以利用第三方服务做一些认证、鉴权相关事情,然后解析返回结果。通过这种方式,我们可以做的事情就可以扩展很多。比如对接 Redis 或数据库,只要是通过TCP 或 UDP 这种形式的,都可以通过 Serverless 插件进行尝试。
\\n完成自定义代码片之后,我们创建路由,并将代码片配置到 Serverless 插件。后面再通过访问 Apache APISIX 获取相应的信息反馈,测试插件是否生效。
\\nKubeSphere 是在 Kubernetes 之上构建的面向云原生应用的系统,完全开源,支持多云与多集群管理,提供全栈的 IT 自动化运维能力,简化企业的 DevOps 工作流。它的架构可以非常方便地使第三方应用与云原生生态组件进行即插即用 (plug-and-play) 的集成。
\\n作为全栈的多租户容器平台,KubeSphere 提供了运维友好的向导式操作界面,帮助企业快速构建一个强大和功能丰富的容器云平台。KubeSphere 为用户提供构建企业级 Kubernetes 环境所需的多项功能,例如多云与多集群管理、Kubernetes 资源管理、DevOps、应用生命周期管理、微服务治理(服务网格)、日志查询与收集、服务与网络、多租户管理、监控告警、事件与审计查询、存储管理、访问权限控制、GPU 支持、网络策略、镜像仓库管理以及安全管理等。
\\nApache APISIX 是一款开源的高性能、动态云原生网关,由深圳支流科技有限公司于 2019 年捐赠给 Apache 基金会,当前已经成为 Apache 基金会的顶级开源项目,也是 GitHub 上最活跃的网关项目。Apache APISIX 当前已经覆盖了 API 网关,LB,Kubernetes Ingress,Service Mesh 等多种场景。
\\n将现有 Kubernetes 集群已纳入 KubeSphere 管理。
\\n我们可以参考 KubeSphere 的文档启用 KubeSphere 的 AppStore,或者使用使用 Apache APISIX 的 Helm 仓库来进行部署。这里,我们直接使用 Apache APISIX 的 Helm 仓库进行部署。
\\n执行以下命令即可添加 Apache APISIX 的 Helm repo,并完成部署。
\\n➜ ~ helm repo add apisix https://charts.apiseven.com\\n\\"apisix\\" has been added to your repositories\\n➜ ~ helm repo add bitnami https://charts.bitnami.com/bitnami\\n\\"bitnami\\" has been added to your repositories\\n➜ ~ helm repo update\\n➜ ~ kubectl create ns apisix\\nnamespace/apisix created\\n➜ ~ helm install apisix apisix/apisix --set gateway.type=NodePort --set ingress-controller.enabled=true --namespace apisix\\nW0827 18:19:58.504653 294386 warnings.go:70] apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16+, unavailable in v1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition\\nNAME: apisix\\nLAST DEPLOYED: Fri Aug 27 18:20:00 2021\\nNAMESPACE: apisix\\nSTATUS: deployed\\nREVISION: 1\\nTEST SUITE: None\\nNOTES:\\n1. Get the application URL by running these commands:\\n export NODE_PORT=$(kubectl get --namespace apisix -o jsonpath=\\"{.spec.ports[0].nodePort}\\" services apisix-gateway)\\n export NODE_IP=$(kubectl get nodes --namespace apisix -o jsonpath=\\"{.items[0].status.addresses[0].address}\\")\\n echo http://$NODE_IP:$NODE_PORT\\n
\\n验证是否已经成功部署且运行:
\\n➜ ~ kubectl -n apisix get pods\\nNAME READY STATUS RESTARTS AGE\\napisix-77d7545d4d-cvdhs 1/1 Running 0 4m7s\\napisix-etcd-0 1/1 Running 0 4m7s\\napisix-etcd-1 1/1 Running 0 4m7s\\napisix-etcd-2 1/1 Running 0 4m7s\\napisix-ingress-controller-74c6b5fbdd-94ngk 1/1 Running 0 4m7s\\n
\\n可以看到相关的 Pod 均已正常运行。
\\n我们使用 kennethreitz/httpbin
作为示例项目进行演示。这里也直接在 KubeSphere 中完成部署。
选择服务 -- 无状态服务,创建即可。
\\n在 KubeSphere 的服务和负载界面即可看到部署成功,也可以直接在终端下查看是否已经部署成功。
\\n➜ ~ kubectl get pods,svc -l app=httpbin\\nNAME READY STATUS RESTARTS AGE\\npod/httpbin-v1-7d6dc7d5f-5lcmg 1/1 Running 0 48s\\n\\nNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\\nservice/httpbin ClusterIP 10.96.0.5 <none> 80/TCP 48s\\n
\\n我们先演示如何使用 Apache APISIX 作为网关代理 Kubernetes 集群中的服务。
\\nroot@apisix:~$ kubectl -n apisix exec -it `kubectl -n apisix get pods -l app.kubernetes.io/name=apisix -o name` -- bash\\nbash-5.1# curl httpbin.default/get\\n{\\n \\"args\\": {},\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Host\\": \\"httpbin.default\\",\\n \\"User-Agent\\": \\"curl/7.77.0\\"\\n },\\n \\"origin\\": \\"10.244.2.9\\",\\n \\"url\\": \\"http://httpbin.default/get\\"\\n}\\n
\\n可以看到在 Apache APISIX 的 Pod 内可正常访问示例项目。接下来使用 Apache APISIX 对该示例项目进行代理。
\\n这里我们使用 curl
调用 Apache APISIX 的 admin 接口,创建一条路由。将所有 host 头为 httpbin.org
的请求转发给 httpbin.default:80
这个实际的应用服务上。
bash-5.1# curl \\"http://127.0.0.1:9180/apisix/admin/routes/1\\" -H \\"X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\\" -X PUT -d \'\\n{\\n \\"uri\\": \\"/get\\",\\n \\"host\\": \\"httpbin.org\\",\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"httpbin.default:80\\": 1\\n }\\n }\\n}\'\\n{\\"node\\":{\\"key\\":\\"\\\\/apisix\\\\/routes\\\\/1\\",\\"value\\":{\\"host\\":\\"httpbin.org\\",\\"update_time\\":1630060883,\\"uri\\":\\"\\\\/*\\",\\"create_time\\":1630060883,\\"priority\\":0,\\"upstream\\":{\\"type\\":\\"roundrobin\\",\\"pass_host\\":\\"pass\\",\\"nodes\\":{\\"httpbin.default:80\\":1},\\"hash_on\\":\\"vars\\",\\"scheme\\":\\"http\\"},\\"id\\":\\"1\\",\\"status\\":1}},\\"action\\":\\"set\\"}\\n
\\n你会得到类似上面的输出,接下来验证是否代理成功:
\\nbash-5.1# curl http://127.0.0.1:9080/get -H \\"HOST: httpbin.org\\"\\n{\\n \\"args\\": {},\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Host\\": \\"httpbin.org\\",\\n \\"User-Agent\\": \\"curl/7.77.0\\",\\n \\"X-Forwarded-Host\\": \\"httpbin.org\\"\\n },\\n \\"origin\\": \\"127.0.0.1\\",\\n \\"url\\": \\"http://httpbin.org/get\\"\\n}\\n
\\n得到上面的输出,说明已经通过 Apache APISIX 代理了示例项目的流量。接下来我们试试在集群外通过 Apache APISIX 访问示例项目。
\\nroot@apisix:~$ kubectl -n apisix get svc -l app.kubernetes.io/name=apisix\\nNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\\napisix-admin ClusterIP 10.96.33.97 <none> 9180/TCP 22m\\napisix-gateway NodePort 10.96.126.83 <none> 80:31441/TCP 22m\\n
\\n在使用 Helm chart 部署的时候,默认会将 Apache APISIX 的端口通过 NodePort 的形式暴露出去。我们使用 Node IP + NodePort 的端口进行访问测试。
\\nroot@apisix:~$ curl http://172.18.0.5:31441/get -H \\"HOST: httpbin.org\\"\\n{\\n \\"args\\": {},\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Host\\": \\"httpbin.org\\",\\n \\"User-Agent\\": \\"curl/7.76.1\\",\\n \\"X-Forwarded-Host\\": \\"httpbin.org\\"\\n },\\n \\"origin\\": \\"10.244.2.1\\",\\n \\"url\\": \\"http://httpbin.org/get\\"\\n}\\n
\\n可以看到,在集群外已经可以通过 Apache APISIX 作为网关代理 Kubernetes 集群内的服务了。
\\n我们可以直接在 KubeSphere 中添加应用路由(Ingress) ,Apache APISIX Ingress Controller 会自动将路由规则同步至 Apache APISIX 中,完成服务的代理。
\\n注意我们添加了 kubernetes.io/ingress.class: apisix
的 annotation 配置,用于支持集群内多 ingress-controller 的场景。
保存后,可看到如下界面:
\\n在终端下测试是否代理成功:
\\nroot@apisix:~$ curl http://172.18.0.5:31441/get -H \\"HOST: http-ing.org\\" { \\"args\\": {}, \\"headers\\": { \\"Accept\\": \\"*/*\\", \\"Host\\": \\"http-ing.org\\", \\"User-Agent\\": \\"curl/7.76.1\\", \\"X-Forwarded-Host\\": \\"http-ing.org\\" }, \\"origin\\": \\"10.244.2.1\\", \\"url\\": \\"http://http-ing.org/get\\"}\\n
\\n可以看到也正常代理了。
\\n除了以上方式外,Apache APISIX Ingress Controller 通过 CRD 的方式对 Kubernetes 进行了扩展,你也可以通过发布 ApisixRoute
等这种自定义资源来完成 Kubernetes 中服务的对外暴露。
你可以在 KubeSphere 中使用 Apache APISIX 的官方 Helm 仓库直接部署 Apache APISIX 和 APISIX Ingress Controller 。并且 Apache APISIX 可通过作为网关,或者 APISIX Ingress Controller 的数据面来承载业务流量。
\\nApache APISIX 已经与 KubeSphere 社区达成合作,你可以直接在 KubeSphere 自带的应用仓库中找到 Apache APISIX ,不需要手动添加 Helm 仓库。
\\n","description":"KubeSphere 介绍 KubeSphere 是在 Kubernetes 之上构建的面向云原生应用的系统,完全开源,支持多云与多集群管理,提供全栈的 IT 自动化运维能力,简化企业的 DevOps 工作流。它的架构可以非常方便地使第三方应用与云原生生态组件进行即插即用 (plug-and-play) 的集成。\\n\\n作为全栈的多租户容器平台,KubeSphere 提供了运维友好的向导式操作界面,帮助企业快速构建一个强大和功能丰富的容器云平台。KubeSphere 为用户提供构建企业级 Kubernetes 环境所需的多项功能,例如多云与多集群管理…","guid":"https://www.apiseven.com/blog/apache-apisix-kubesphere-a-better-gateway-and-k8s-ingress-controller","author":"Jintao Zhang","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-08-30T16:00:00.437Z","media":[{"url":"https://static.apiseven.com/202108/1630404138226-5475c163-d372-414e-af74-5c5a86f19629.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630404173444-9bb73e0d-5bee-428e-a257-4685500344ef.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630404265190-585b9b09-72d5-4320-b0fe-9cf8a73c55ea.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630404325747-b92928dc-2c6b-4574-a49d-32b6bcb187f9.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630404366474-dfe8ae08-f16d-417f-8ef3-3495ebda0f7d.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"使用 Apache APISIX 的 OpenID Connect 插件进行集中身份认证","url":"https://www.apiseven.com/blog/using-the-apache-apisix-openid-connect-plugin-for-centralized-authentication","content":"@朱欣欣 是API7.ai的系统工程师,也是 Apache APISIX 项目的 committer。他是一个开源爱好者,也是一个 Golang 开发者。现在他正在为 Apache APISIX 的 control plane 贡献代码并执行 code review。除此之外,他在 Apache APISIX 社区中非常活跃,乐于回答社区内的各种问题。
\\nApache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。Apache APISIX 不仅支持插件动态变更和热插拔,而且拥有众多实用的插件。Apache APISIX 的 OpenID Connect 插件支持 OpenID,用户可以使用该插件将身份认证从传统认证模式替换为集中认证模式。
\\n身份认证是指通过一定的手段,对用户的身份进行验证。应用通过身份认证识别用户身份,并根据用户身份 ID 从身份提供方(Identity Provider)获取详细的用户元数据,并以此判断用户是否拥有访问指定资源的权限。身份认证模式分为两大类:传统认证模式和集中认证模式。
\\n在传统认证模式下,各个应用服务需要单独支持身份认证,例如当用户未登录时访问登录接口,接口返回 301 跳转页面。应用需要开发维护 Session 以及和身份提供商的认证交互等逻辑。传统认证模式的流程如下图所示:首先由用户发起请求(request),然后由网关接收请求并将其转发至对应的应用服务,最后由应用服务与身份提供方对接,完成身份认证(authorization)。
\\n与传统认证模式不同,集中身份认证模式把用户认证从应用服务中抽离了出来,以 Apache APISIX 为例,集中认证的流程如下图所示:首先由用户发起请求(request),然后由前置的网关负责用户认证流程,与身份提供方对接,向身份提供方发送身份认证(authorization)请求。身份提供方返回用户身份信息(user info)。网关完成用户身份识别后,将用户身份信息通过请求头的形式转发至后端应用。
\\n相比较传统认证模式,集中认证模式下有如下优点:
\\nOpenID 是一种集中认证模式,它是一个去中心化的身份认证系统。使用 OpenID 的好处是,用户只需要在一个 OpenID 身份提供方的网站上注册和登录,使用一份账户密码信息即可访问不同应用。Okta 是一个常见的 OpenID 身份提供方,Apache APISIX OpenID Connect 插件支持 OpenID,所以用户可以使用该插件将传统认证模式替换为集中认证模式。
\\nOpenID 认证过程有以下 7 个步骤,如下图所示。
\\n使用 Apache APISIX OpenID Connect 插件配置 Okta 认证的过程非常简单,只需三步即可完成 Okta 配置 ,从传统身份认证模式切换到集中身份认证模式。下文讲述了使用 Apache APISIX 的 OpenID Connect 插件配置 Okta 认证的操作步骤。
\\n已有 Okta 账号。
\\nhttp://127.0.0.1:9080/
。\\nclient_id
和 {YOUR_CLIENT_ID}
对应。client_secret
和 {YOUR_CLIENT_SECRET}
对应。{YOUR_ISSUER}
对应。你可以通过源码包、Docker、Helm Chart 等多种方式来安装 Apache APISIX。
\\nApache APISIX 的运行环境需要依赖 NGINX 和 etcd,所以在安装 Apache APISIX 前,请根据您使用的操作系统安装对应的依赖。我们提供了 CentOS7、Fedora 31 & 32 、Ubuntu 16.04 & 18.04、 Debian 9 & 10 和 MacOS 上的依赖安装操作步骤,详情请参考安装依赖。
\\n通过 Docker 或 Helm Chart 安装 Apache APISIX 时,已经包含了所需的 NGINX 和 etcd,请参照各自对应的文档。
\\n这种安装方式适用于 CentOS 7 操作系统,请运行以下命令安装 Apache APISIX。
\\nsudo yum install -y https://github.com/apache/apisix/releases/download/2.7/apisix-2.7-0.x86_64.rpm\\n
\\n详情请参考:使用 Docker 安装 Apache APISIX。
\\n详情请参考:使用 Helm Chart 安装 Apache APISIX。
\\napisix-2.7
的目录:mkdir apisix-2.7\\n
\\nwget https://downloads.apache.org/apisix/2.7/apache-apisix-2.7-src.tgz\\n
\\n您也可以通过 Apache APISIX 官网下载 Apache APISIX Release 源码包。 Apache APISIX 官网也提供了 Apache APISIX、APISIX Dashboard 和 APISIX Ingress Controller 的源码包,详情请参考 Apache APISIX 官网-下载页。
\\ntar zxvf apache-apisix-2.7-src.tgz -C apisix-2.7\\n
\\n# 切换到 apisix-2.7 目录\\ncd apisix-2.7\\n# 创建依赖\\nmake deps\\n
\\n运行以下命令初始化 NGINX 配置文件和 etcd。
\\n# initialize NGINX config file and etcd\\nmake init\\n
\\n运行以下命令,启动 Apache APISIX。
\\n创建路由并配置 OpenID Connect 插件。
\\nOpenID Connect 配置列表如下:
\\n字段 | \\n默认值 | \\n描述 | \\n
---|---|---|
client_id | \\n\\"\\" | \\nOAuth 客户端 ID | \\n
client_secret | \\n\\"\\" | \\nOAuth 客户端密钥 | \\n
discovery | \\n\\"\\" | \\n身份提供商的服务发现端点 | \\n
scope | \\nopenid | \\n需要访问资源范围 | \\n
relm | \\napisix | \\n指定 WWW-Authenticate 响应头验证信息 | \\n
bearer_only | \\nfalse | \\n是否检查请求头中的 token | \\n
logout_path | \\n/logout | \\n登出的 URI | \\n
redirect_uri | \\nrequest_uri | \\n身份提供商跳转回来的 URI,默认为请求地址 | \\n
timeout | \\n3 | \\n请求超时时间,单位为秒 | \\n
ssl_verify | \\nfalse | \\n是否身份提供商的校验 ssl 证书 | \\n
introspection_endpoint | \\n\\"\\" | \\n身份提供商的令牌验证端点的 URL,不填则将从 discovery 响应中提取 | \\n
introspection_endpoint_auth_method | \\nclient_secret_basic | \\n令牌自省的认证方法名称 | \\n
public_key | \\n\\"\\" | \\n验证令牌的公钥 | \\n
token_signing_alg_values_expected | \\n\\"\\" | \\n验证令牌的算法 | \\n
set_access_token_header | \\ntrue | \\n是否在请求头中携带 access token | \\n
access_token_in_authorization_header | \\nfalse | \\ntrue 时将 access token 放置在 Authorization 头中,false 时将 access token 放置在 X-Access-Token 头中 | \\n
set_id_token_header | \\ntrue | \\n是否将 ID token 携带至 X-ID-Token 请求头 | \\n
set_userinfo_header | \\ntrue | \\n是否将用户信息携带至 X-Userinfo 请求头 | \\n
以下代码示例通过 Apache APISIX Admin API 进行创建路由,设置路由的上游为 httpbin.org。httpbin.org 是一个简单的用于接收请求和响应请求的后端服务,下文将使用 httpbin.org 的 get 页面,参考 http bin get。
\\n具体配置项请参考 Apache APISIX OpenID Connect Plugin。
\\ncurl -XPOST 127.0.0.1:9080/apisix/admin/routes -H \\"X-Api-Key: edd1c9f034335f136f87ad84b625c8f1\\" -d \'{\\n \\"uri\\":\\"/*\\",\\n \\"plugins\\":{\\n \\"openid-connect\\":{\\n \\"client_id\\":\\"{YOUR_CLIENT_ID}\\",\\n \\"client_secret\\":\\"{YOUR_CLIENT_SECRET}\\",\\n \\"discovery\\":\\"https://{YOUR_ISSUER}/.well-known/openid-configuration\\",\\n \\"scope\\":\\"openid profile\\",\\n \\"bearer_only\\":false,\\n \\"realm\\":\\"master\\",\\n \\"introspection_endpoint_auth_method\\":\\"client_secret_post\\",\\n \\"redirect_uri\\":\\"http://127.0.0.1:9080/\\"\\n }\\n },\\n \\"upstream\\":{\\n \\"type\\":\\"roundrobin\\",\\n \\"nodes\\":{\\n \\"httpbin.org:80\\":1\\n }\\n }\\n}\'\\n
\\n输入用户在 Okta 注册的账号密码,单击“Sign in”,登录 Okta 账户。
\\n登录成功之后,能成功访问到 httpbin.org 中的 get 页面。该 httpbin.org/get 页面将返回请求的数据如下:
\\n\\"X-Access-Token\\": \\"******Y0RPcXRtc0FtWWVuX2JQaFo1ZVBvSlBNdlFHejN1dXY5elV3IiwiYWxnIjoiUlMyNTYifQ.***TVER3QUlPbWZYSVRzWHRxRWh2QUtQMWRzVDVGZHZnZzAiLCJpc3MiOiJodHRwczovL3FxdGVzdG1hbi5va3RhLmNvbSIsImF1ZCI6Imh0dHBzOi8vcXF0ZXN0bWFuLm9rdGEuY29tIiwic3ViIjoiMjgzMDE4Nzk5QHFxLmNvbSIsImlhdCI6MTYyODEyNjIyNSwiZXhwIjoxNjI4MTI5ODI1LCJjaWQiOiIwb2ExMWc4ZDg3TzBGQ0dYZzY5NiIsInVpZCI6IjAwdWEwNWVjZEZmV0tMS3VvNjk1Iiwic2NwIjpbIm9wZW5pZCIsInByb2Zpb***.****iBshIcJhy8QNvzAFD0fV4gh7OAdTXFMu5k0hk0JeIU6Tfg_Mh-josfap38nxRN5hSWAvWSk8VNxokWTf1qlaRbypJrKI4ntadl1PrvG-HgUSFD0JpyqSQcv10TzVeSgBfOVD-czprG2Azhck-SvcjCNDV-qc3P9KoPQz0SRFX0wuAHWUbj1FRBq79YnoJfjkJKUHz3uu7qpTK89mxco8iyuIwB8fAxPMoXjIuU6-6Bw8kfZ4S2FFg3GeFtN-vE9bE5vFbP-JFQuwFLZNgqI0XO2S7l7Moa4mWm51r2fmV7p7rdpoNXYNerXOeZIYysQwe2_L****\\",\\n\\"X-Id-Token\\": \\"******aTdDRDJnczF5RnlXMUtPZUtuSUpQdyIsImFtciI6WyJwd2QiXSwic3ViIjoiMDB1YTA1ZWNkRmZXS0xLdW82OTUiLCJpc3MiOiJodHRwczpcL1wvcXF0ZXN0bWFuLm9rdGEuY29tIiwiYXVkIjoiMG9hMTFnOGQ4N08wRkNHWGc2OTYiLCJuYW1lIjoiUGV0ZXIgWmh1IiwianRpIjoiSUQuNGdvZWo4OGUyX2RuWUI1VmFMeUt2djNTdVJTQWhGNS0tM2l3Z0p5TTcxTSIsInZlciI6MSwicHJlZmVycmVkX3VzZXJuYW1lIjoiMjgzMDE4Nzk5QHFxLmNvbSIsImV4cCI6MTYyODEyOTgyNSwiaWRwIjoiMDBvYTA1OTFndHAzMDhFbm02OTUiLCJub25jZSI6ImY3MjhkZDMxMWRjNGY3MTI4YzlmNjViOGYzYjJkMDgyIiwiaWF0IjoxNjI4MTI2MjI1LCJhdXRoX3RpbWUi*****\\",\\n\\"X-Userinfo\\": \\"*****lfbmFtZSI6IlpodSIsImxvY2FsZSI6ImVuLVVTIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiMjgzMDE4Nzk5QHFxLmNvbSIsInVwZGF0ZWRfYXQiOjE2MjgwNzA1ODEsInpvbmVpbmZvIjoiQW1lcmljYVwvTG9zX0FuZ2VsZXMiLCJzdWIiOiIwMHVhMDVlY2RGZldLTEt1bzY5NSIsImdpdmVuX25hbWUiOiJQZXRlciIsIm5hbWUiOiJQZXRl****\\"\\n
\\n其中:
\\nX-Access-Token:Apache APISIX 将从用户提供商获取到的 access token 放入 X-Access-Token 请求头,可以通过插件配置中的 access_token_in_authorization_header 来选择是否放入 Authorization 请求头中。
\\nX-Id-Token:Apache APISIX 将从用户提供商获取到的 ID token 通过 base64 编码之后放入 X-Id-Token 请求头,可以通过插件配置中的 set_id_token_header 来选择是否开启该功能,默认为为开启状态。
\\nX-Userinfo: Apache APISIX 将从用户提供商获取到的用户信息,通过 base64 编码之后放入 X-Userinfo,你可以通过插件配置中的 set_userinfo_header 来选择是否开启该功能,默认为开启状态。
\\n由此可以看到,Apache APISIX 将会携带 X-Access-Token,X-Id-Token,X-Userinfo 三个请求头传递至上游。上游可以通过解析这几个头部,从而获取到用户 ID 信息和用户的元数据。
\\n我们展示了在 Apache APISIX 中直接建立来自 Okta 的集中式身份认证的过程。只要注册一个免费的 Okta 开发者账户就可以轻松开始了。这种集中认证的方法减少了开发者的学习和维护成本,提供了安全和精简的用户体验。
\\nOkta 是一个可定制的、安全的集中身份认证解决方案。Okta 可以为您的应用程序添加认证和授权。不需要自己编写代码,即可在您的应用程序中直接获得可扩展的认证。您可以将应用程序连接到 Okta,并定义用户的登录方式。每次用户尝试认证时,Okta 都会验证他们的身份,并将所需信息发回给您的应用程序。
\\nApache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。你可以使用 Apache APISIX 处理传统的南北向流量,以及服务间的东西向流量,也可以当做 Kubernetes Ingress Controller 来使用。
\\n全球已有数百家企业使用 Apache APISIX 处理关键业务流量,涵盖金融、互联网、制造、零售、运营商等等,比如美国航空航天局(NASA)、欧盟的数字工厂、中国航信、中国移动、腾讯、华为、微博、网易、贝壳找房、360、泰康、奈雪的茶等等。
\\nGithub:https://github.com/apache/apisix
\\n官网:https://apisix.apache.org
\\n","description":"关于作者 @朱欣欣 是API7.ai的系统工程师,也是 Apache APISIX 项目的 committer。他是一个开源爱好者,也是一个 Golang 开发者。现在他正在为 Apache APISIX 的 control plane 贡献代码并执行 code review。除此之外,他在 Apache APISIX 社区中非常活跃,乐于回答社区内的各种问题。\\n\\n什么是 Apache APISIX\\n\\nApache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能…","guid":"https://www.apiseven.com/blog/using-the-apache-apisix-openid-connect-plugin-for-centralized-authentication","author":"朱欣欣","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-08-25T16:00:00.375Z","media":[{"url":"https://static.apiseven.com/202108/1629945145686-2a5d247b-b42e-43e6-b5fe-a1a716f514f1.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629948254470-6eea722c-4567-4489-9a87-04b5673b6796.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945145694-58b0d80d-5ac7-4ff1-83ce-abcf2c5d13f7.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945284704-056f75ef-f726-4c62-8c4e-f491ba9ed35b.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945322972-0a028f73-2cd8-4a84-9849-3e5d4f5c457b.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945355148-237e1fb7-f874-4a61-adeb-0e062f40cb03.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945383145-18cfbe84-4c7f-4f62-8979-fa2679d96ee1.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945708891-d0e9e0bd-dd3a-4ce7-b497-7a31f6da3f49.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945757074-1340330d-1429-4f3f-bc8e-c89153acaec5.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945782309-14f84210-6cf3-4618-9ed0-809701094872.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945819163-8751bf83-57a1-4278-8fbf-5379e6e81c58.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1629945855914-012fbb0a-d65f-428e-8f46-621291ff9deb.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"为什么 Apache APISIX 选择 NGINX + Lua 这个技术栈?","url":"https://www.apiseven.com/blog/why-apache-apisix-chose-nginx-and-lua","content":"笔者在今年的 COSCUP 大会做分享时,曾有观众问这样的问题,为什么 Apache APISIX、Kong 和 3scale 这些网关都采用 Lua 来编写逻辑?
\\n是啊,Lua 并不是一门广为人知的语言,离“主流编程语言”的圈子大概还差个十万八千里吧。甚至有一次,我在跟别人交流的时候,对方在说到 Lua 之前,先停顿了片刻,随后终于打定主意,以\\"L U A\\"逐个字母发音的方式表达了对这一罕见之物的称呼。
\\n所以,为什么 Apache APISIX 和其他知名的网关会选择用 Lua 呢?
\\n事实上,Apache APISIX 采用的技术栈并不是纯粹的 Lua,准确来说,应该是 Nginx + Lua。Apache APISIX 以底下的 Nginx 为根基,以上层的 Lua 代码为枝叶。
\\n严谨认真的读者必然会指出,Apache APISIX 并非基于 Nginx + Lua 的技术栈,而是 Nginx + LuaJIT (又称 OpenResty,以下为了避免混乱,会仅仅采用 Nginx + Lua 这样的称呼)。
\\nLuaJIT 是 Lua 的一个 JIT 实现,性能比 Lua 好很多,而且额外添加了 FFI 的功能,能方便高效地调用 C 代码。\\n由于现行的主流 API 网关,如果不是基于 OpenResty 实现,就是使用 Go 编写,所以时不时会看到各种 Go 和 Lua 谁的性能更好的比较。
\\n就我个人观点看,脱离场景比较语言的性能,是没有意义的。
\\n首先明确一点,Apache APISIX 是基于 Nginx + Lua 的技术栈,只是外层代码用的是 Lua。所以如果要论证哪种网关性能更好,正确的比较对象是 C + LuaJIT 跟 Go 的比较。网关的性能的大头,在于代理 HTTP 请求和响应,这一块的工作主要是 Nginx 在做。
\\n所以倘若要比试比试性能,不妨比较 Nginx 和 Go 标准库的 HTTP 实现。
\\n众所周知,Nginx 是一个 bytes matter 的高性能服务器实现,对内存使用非常抠门。举两个例子:
\\n凭借这种抠门,Nginx 得以屹立在高性能服务器之巅。
\\n相反的,Go 标准库的 HTTP 实现,是一个滥用内存的典型反例。
\\n这可不是我的一面之辞,Fast HTTP,一个重新实现 Go 标准库里面的 HTTP 包的项目,就举了两个例子:
\\nFast HTTP 文档里面还提到一些 bytes matter 的优化技巧,建议大家可以阅读下。
\\n事实上,即使不去比较作为网关核心的代理功能,用 LuaJIT 写的代码不一定比 Go 差多少。原因有二。
\\n其一,拜 Lua 跟 C 良好的亲和力所赐,许多 Lua 的库核心其实是用 C 写的。
\\n比如 lua-cjson 的 json 编解码,lua-resty-core 的 base64 编解码,实际上大头是用 C 实现的。\\n而 Go 的库,当然是大部分用 Go 实现的。虽然有 CGO 这种东西,但是受限于 Go 的协程调度和工具链的限制,它在 Go 的生态圈里面只能处于从属的地位。
\\n关于 LuaJIT 和 Go 对于 C 的亲和力的比较,推荐 Hacker News 上的这篇文章:《Comparing the C FFI overhead in various programming languages》(链接 https://news.ycombinator.com/item?id=17161168 )
\\n于是我们比较 Lua 的某些功能,其实还是会回到 C 和 Go 的比较中。
\\n其二,LuaJIT 的 JIT 优化无出其右。
\\n讨论动态语言的性能,可以把动态语言分成两类,带 JIT 和不带 JIT 的。JIT 优化能够把动态语言的代码在运行时编译成机器码,进而把原来的代码的性能提升一个数量级。
\\n带 JIT 的语言还可以分成两类,能充分 JIT 的和只支持部分 JIT 的。而 LuaJIT 属于前者。
\\n人所皆知,Lua 是一门非常简单的语言。相对鲜为人知的是,LuaJIT 的作者 Mike Pall 是一个非常厉害的程序员。这两者的结合,诞生了 LuaJIT 这种能跟 V8 比肩的作品。
\\n关于 LuaJIT 和 V8 到底谁更快,一直是长盛不衰的争论话题。展开讲 LuaJIT 的 JIT 已经超过了本文想要讨论的范畴。简单来说,JIT 加持的 LuaJIT 跟预先编译好的 Go 性能差别并不大。
\\n至于谁比谁慢,慢多少,那就是个见仁见智的问题了。这里我举个例子:
\\nlocal text = {\\"The\\", \\"quick\\", \\"brown\\", \\"fox\\", \\"jumped\\", \\"over\\", \\"the\\", \\"lazy\\", \\"dog\\", \\"at\\", \\"a\\", \\"restaurant\\", \\"near\\", \\"the\\", \\"lake\\", \\"of\\", \\"a\\", \\"new\\", \\"era\\"}\\nlocal map = {}\\nlocal times = 1e8\\nlocal n = #text\\nfor i = 1, n do\\n map[text[i]] = 0\\n for _ = 1, times do\\n map[text[i]] = map[text[i]] + 1\\n end\\nend\\n\\nfor i = 1, n do\\n io.write(text[i], \\" \\", map[text[i]], \\"\\\\n\\")\\nend\\n
\\npackage main\\nimport \\"fmt\\"\\nfunc main() {\\n text := []string{\\"The\\", \\"quick\\", \\"brown\\", \\"fox\\", \\"jumped\\", \\"over\\", \\"the\\", \\"lazy\\", \\"dog\\", \\"at\\", \\"a\\", \\"restaurant\\", \\"near\\", \\"the\\", \\"lake\\", \\"of\\", \\"a\\", \\"new\\", \\"era\\"}\\n m := map[string]int{}\\n times := int(1e8)\\n for _, t := range text {\\n m[t] = 0\\n for i := 0; i < times; i++ {\\n m[t]++\\n }\\n }\\n for _, t := range text {\\n fmt.Println(t, \\" \\", m[t])\\n }\\n}\\n
\\n上面两段代码是等价的。你猜是第一个 Lua 版本的快,还是第二个 Go 版本的快?
\\n在我的机器上,第一个用时不到 1 秒,第二个花了 23 秒多。
\\n举这个例子并不是想证明 LuaJIT 比 Go 快 20 倍。我只想说明用 micro benchmark 证明某个语言比另一个语言快的意义不大,因为影响性能的因素很多。一个简单的 micro benchmark 很有可能过分强调某一个因素,导致出乎意料的结果。
\\n让我们转回 Apache APISIX 的 Nginx + Lua 的技术栈。Nginx + Lua 的技术栈给我们带来的,不仅仅是高性能。
\\n经常有人问我们,既然你们是基于 Nginx 开源版本,而 Nginx 并不支持动态配置,为什么 Apache APISIX 声称自己可以实现动态配置?你们是不是改了点东西?
\\n是的,我们确实有在维护自己的 Nginx 发行版,不过 Apache APISIX 的大部分功能在官方的 Nginx 上就能使用。我们之所以能做到动态配置,全靠把配置放到 Lua 代码里面来实现。
\\n举路由系统作为一个例子,Nginx 的路由需要在配置文件里面进行配置,每次更改路由,都需要 reload 之后才能生效。这是因为 Nginx 的路由分发只支持静态配置,不能动态增减路由。
\\n为了实现路由动态配置,Apache APISIX 做了两件事:
\\n你可能会问,在 Lua 里面做路由分发,会比 Nginx 的实现慢吗?
\\n就像前面提到过的一样,凡是对性能要求比较高的,我们会把核心代码用 C 改写。我们的路由分发模块就是这么干的。路由分发模块在匹配路由时,会采用一个前缀树来匹配。而这个前缀树是用 C 实现的。感兴趣的读者可以看下代码:lua-resty-radixtree。
\\n完成了 C 层面上的前缀树匹配,接下来就该 Lua 发挥灵活性的时刻了。对于匹配同一前缀的各个路由,我们支持通过许多别的方式来进行下一级的匹配,其中就包含通过一个特定的表达式来匹配。尽管硬着头皮,也能在 C 层面上接入一个表达式引擎,但是纯 C 实现做不了非常灵活地自定义表达式里面的变量。
\\n举个例子,下面是 Apache APISIX 用来匹配 GraphQL 请求的 route 配置:
\\n{\\n \\"methods\\": [\\n \\"POST\\"\\n ],\\n \\"upstream\\": {\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n },\\n \\"type\\": \\"roundrobin\\"\\n },\\n \\"uri\\": \\"/hello\\",\\n \\"vars\\": [\\n [\\n \\"graphql_name\\",\\n \\"==\\",\\n \\"repo\\"\\n ]\\n ]\\n}\\n
\\n它会匹配这样的 GraphQL 请求:
\\nquery repo\\n{\\n owner\\n {\\n name\\n }\\n}\\n
\\n这里的 graphql_name 并非 Nginx 内置变量,而是通过 Lua 代码定义的。Apache APISIX 一共定义了三个 GraphQL 相关的变量,连同解析 GraphQL body 在内不过 62 行 Lua 代码。如果要通过 Nginx C 模块来定义变量,62 行可能只不过是把相关方法的样板代码搭建起来,都还没有到真正的解析 GraphQL 的逻辑呢。
\\n采用 Lua 代码来做路由还有一个好处:它减低了二次开发的门槛。
\\n如果在路由过程中需要有特殊的逻辑,用户可以实现成自定义的变量和运算符,比如通过 IP 库匹配到的地理位置来决定采用哪条路由。用户只需要写一些 Lua 代码,这要比修改 Nginx C module 的难度小多了。
\\n在 Apache APISIX 里面,不仅仅路由是动态的,我们的 TLS 服务端证书和上游节点配置都是动态的,而且无需修改 Nginx —— 上述功能可以跑在官方的 Nginx + Lua 技术栈上。当然通过修改 Nginx,我们还实现了更多的高级功能,比如动态的 gzip 配置和动态的客户端请求大小限制。后续我们将推行自己的 Nginx 发行版,这样开源用户也能轻松用上这些高级功能。
\\n","description":"笔者在今年的 COSCUP 大会做分享时,曾有观众问这样的问题,为什么 Apache APISIX、Kong 和 3scale 这些网关都采用 Lua 来编写逻辑? 是啊,Lua 并不是一门广为人知的语言,离“主流编程语言”的圈子大概还差个十万八千里吧。甚至有一次,我在跟别人交流的时候,对方在说到 Lua 之前,先停顿了片刻,随后终于打定主意,以\\"L U A\\"逐个字母发音的方式表达了对这一罕见之物的称呼。\\n\\n所以,为什么 Apache APISIX 和其他知名的网关会选择用 Lua 呢?\\n\\n事实上,Apache APISIX 采用的技术栈并不是纯粹的 Lua…","guid":"https://www.apiseven.com/blog/why-apache-apisix-chose-nginx-and-lua","author":"spacewander","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-08-24T16:00:00.149Z","media":null,"categories":null,"attachments":null,"extra":null,"language":null},{"title":"基于 Apache APISIX 的服务网格方案","url":"https://www.apiseven.com/blog/service-grid-solution-based-on-apache-apisix","content":"服务网格(Service Mesh)是处理服务间通信的基础设施层。它负责构成现代云原生应用程序的复杂服务拓扑来可靠地交付请求。通常会为每个服务实例提供一个“边车”(sidecar)代理实例。边车会处理服务间的通信、监控和安全相关的问题, 以及任何可以从各服务中抽象出来的逻辑。
\\nApache APISIX 是一个动态、实时、高性能的 API 网关, 提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。
\\n下面列举出 Apache APISIX 的部分功能亮点,更多功能特性请访问 Github 仓库主页。
\\nApache APISIX 是全动态的云原生 API 网关,上游、SSL 证书、路由、插件等所有功能,都支持动态更新,不需要 reload 就能实时生效,不会产生断连的情况。
\\nApache APISIX 支持比较多的负载均衡策略,如:最常用的带权轮询、一致性 hash、EWMA 算法(指数加权移动平均法)。
\\nApahce APISIX 提供服务发现的功能,如:可以和 Consul 和 Nacos 的组件对接,实现服务发现的功能。同时也支持服务治理相关的功能,如:限流、限速、熔断等。
\\nApache APISIX 是完全基于插件进行扩展的,二次开发难度比较低,而且还能通过 Lua、Java、Go 和 WASM 等来开发自定义插件。借助灵活的插件机制,可针对内部业务完成功能定制。
\\n这是 Apache APISIX 的架构图,左边是数据面(Data Plane),右边是管理面(Control Plane),配置中心选择了当下最成熟的基础设施:etcd,通过 watch etcd,拿到路由、上游等数据。
\\n在这个架构里面,找不到一个单点,其中任何一个服务出现异常宕机等事故,都不会影响 APISIX 正常对外提供服务的能力。当整体架构中的每一个点都支持高可用时,用户生产系统的高稳定性就非常容易实现。
\\nApache APISIX 有一个活跃健康的社区,截止到目前(主仓库)已经有 200 多个贡献者,和 Apache APISIX 相关的项目贡献者有近 300 人。Apache APISIX 自从 2019 年 6 月份开源以来,截止目前一共收到了 2200 多个 PR;坚持每个月发布一个版本,至今已经发布了 27 个版本。
\\n各公司技术团队引入服务网格有各自的原因,如:公司里技术栈比较分散,需要在不同技术栈内完成同样的服务治理;需要维护多个版本,不同版本由不同团队维护,沟通成本比较高,这可能会带来一些差异性,可能引发一些故障。
\\n服务网格有一个非常重要的特性,就是服务治理。把限流限速、服务发现、服务注册、熔断等功能通过服务网格的方式下沉到基础组件,使业务研发人员不需要去关注服务治理,全神贯注实现业务层的开发,效率会提高,同时服务的稳定性也会提升。这是引入服务网格可能会带来的一些好处。
\\nAPI 网关是 API 管理这个范畴的一个工具,除了把服务所提供的 API 暴露出来,供其他服务调用以外,也有一些和服务网格重叠的特性,如:服务治理 —— 服务发现、限流限速、熔断。同时还会在 API 网关层做认证、授权。这是 API 网关的一些优势。
\\n无论是使用服务网格,还是使用 API 网关,有一个共性原因是服务治理。既然二者有一些共性,那么 API 网关是否能够在服务网格里使用呢?Apache APISIX 是否能够胜任服务网格 sidecar 的角色呢?
\\n在 2021 年 1 月,我调研了全国十几家企业对服务网格的使用情况。这些企业中有一些正在做服务网格调研的,有些正在落地的,有些已经上生产环境了。调研结果总结归纳为以下三点:
\\n对于服务网格,大家关注的大多是上述比较基础的功能。但是服务网格的功能是十分强大的,而大家只看到了其中一小部分核心功能。
\\nApache APISIX 已经支持:
\\nApache APISIX 能与 Apache SkyWalking、Prometheus、ZipKin 等组件的结合,获取 metrics 和 tracing、 logging 的数据实现可观测性。
\\n由此可以看出 Apache APISIX 的功能满足服务网格数据面的要求。
\\n在服务网格场景下,数据面实例可能有很多,如何保证在实例数特别多时配置变更的下发延时较低?
\\n一个完整的服务网格方案必须有数据面和控制面,Apache APISIX 可以作为数据面,控制面该怎么选呢?是选现有的服务网格产品,如:Istio / Kuma / OpenServiceMesh ,还是自研?
\\n假设 Apache APISIX 需要做些修改才能在服务网格中使用,这些修改的范围有哪些?会不会太大?比如大到需要考虑 Lua 和 OpenResty 的生态。是否需要自研实现某些功能?自研过程中踩坑的成本有多大?
\\n如何及时获取配置变更?
\\n从 Apache APISIX 的架构图中可以看到,控制面是使用 etcd 作为配置中心的。
\\netcd 是一个强一致性的分布式 KV 存储,使用 Raft 协议做分布式共识。使用 Raft 协议,每一个读写请求都需要过一遍 Raft 的状态机,比如:一个有 5 节点的 etcd 集群,至少需要 3 个节点都确认某次请求,这次请求中的数据才会提交成功。
\\n由于 Raft 算法特性使得组件的 QPS 不能太高,客户端连接数不能太多。在服务网格中,控制面如果使用 etcd 下发配置数据,可能就会把 etcd 集群冲垮,etcd 成为了解决问题的瓶颈。
\\netcd Proxy 支持设置连接很多个客户端(比如一千或者更多),直接引入 etcd Proxy 组件是否能解决问题呢?答案是不能,因为 Apache APISIX 与 etcd 的通信协议是 HTTP 协议,依靠 etcd 集成的 gRPC gateway 把 HTTP 转成了 gRPC,etcd Proxy 不支持协议转换。
\\n在服务网格场景下,数据面实例可能有很多,为保证在实例数特别多时配置变更下发延时较低,只能通过对 etcd Proxy 组件二次开发来及解决延时问题,保证及时获取配置的变更。
\\n控制面的选型
\\n以下列出了现有的两类控制面:
\\n一类是 Istio、Kuma、OpenServiceMesh,这三个控制面的共性是数据面都是 Envoy,通过 xDS 协议把配置从控制面加载到数据面。
\\n另一类是 Linkerd,比较老牌的一个服务网格方案,数据面和控制面都是自研的。
\\n除了采用现有的控制面,还有一个方案就是自研。如果自研控制面,需要考虑很多方面。如:如何设计 CRDs (CustomResourceDefinition),能让管理员和控制面交互?如何解决数据从控制面下发到数据面?自研控制面的成本也是非常大的。
\\n对 Apache APISIX 的改造成本
\\n对 Apache APISIX 的改造成本涉及到 Apache APISIX 技术栈的生态。
\\n第一个要考虑的是 Lua 语言,因为 Lua 语音的使用者比较小众,虽然 Lua 很强大,但是对它生态和工具的支持都比较匮乏。
\\n第二个需要考虑的是 OpenResty,Apache APISIX 底层是基于 OpenResty 的,而 OpenResty 是通过将 LuaJIT 嵌入到 Nginx 里面,来实现其强大的动态能力,而因为 Nginx 社区不活跃,Lua 语言比较小众,导致 OpenResty 社区非常小,近几年社区也越来越不活跃。如果基于 OpenResty 做扩展,如:支持 xDS 协议,缺少 gRPC 的 IDL 翻译工具,需要 Envoy xDS 整套配置的 Lua 翻译,因为 Envoy 没有提供 Lua 版本的。
\\n计算机科学有一句名言:计算机科学的任意一个问题都能通过引入一个额外的间接层来解决掉。
\\n如果只在数据面中使用 Apache APISIX,上面三个问题很难解决,而且使用起来可能有很多的问题。所以结论是:开发一个间接层。间接层是起名为 apisix-mesh-agent,现已经开源,点击跳转项目地址。
\\napisix-mesh-agent 作为 Apache APISIX 和控制面的中间层,从控制面获取配置(变更),并模拟 etcd V3 API 使 Apache APISIX 获取到配置;并创建 iptables 规则劫持出入流量。
\\n接下来详细介绍下 apisix-mesh-agent 的功能与优势。
\\napisix-mesh-agent 支持 xDS 协议,这使得 Apache APISIX 能对接实现 xDS 协议的控制面,如:Istio。从控制面获得的配置格式也是 xDS 协议格式的,apisix-mesh-agent 把配置转换成 Apache APISIX 可识别的格式。使用 Apache APISIX 格式的配置有点好处:节省内存资源。因为 xDS 协议的字段比较冗余,Apache APISIX 的配置字段非常简洁,保存配置到内存,占用的内存资源比较少。
\\netcd V3 API 有两类的接口,一类是 etcd 实例之间进行 Raft 协议数据传递的 API,另一类是面向客户端的 API。apisix-mesh-agent 实现的是面向客户端的 API,目前只实现了 Apache APISIX 必用 API,如:Range 、Watch。实现这些接口后,只需要在 Apache APISIX 的配置里将 etcd 的地址配置到 apisix-mesh-agent 的监听地址,Apache APISIX 不需要任何改动就可以把数据从 apisix-mesh-agent 存到内存里。
\\n通过这个间接层,数据就能够从服务网格控制面传递到 Apache APISIX。
\\n架构是按照控制面和数据面来进行拆分的,架构图的上面是控制面,控制面可以选用 Istio、Kuma 等;架构图的下面是网格的数据面,每一个服务网格的数据面有三个 Pod, 每一个 Pod 的 instance 都有自己的 sidecar 容器,在这个容器里有两个进程,分别是 Apache APISIX 和对应的 apisix-mesh-agent。apisix-mesh-agent 和对应的控制面进行交互,及时获取数据,获取后转换成 Apache APISIX 能够解析的格式,Apache APISIX 和 apisix-mesh-agent 之间通过 etcd API 交互。如此一来 Apache APISIX 就能够及时获取配置的变更并生效。
\\n在服务网格里使用 Apache APISIX 有什么优势呢?
\\n第一,Apache APISIX 自身的优势。
\\nApache APISIX 是一个高性能 API 网关,上面已经介绍过它的特性,此处不再赘述。值得一提的是 Apache APISIX 是使用 Radix Tree 实现路由匹配,路由匹配性能和路由的数量无关,无论有多少路由 Apache APISIX 都能够保证非常快速地匹配到路由,时间复杂度是常数级别的。
\\n第二,复用 Apache APISIX 全部插件。
\\nApache APISIX 目前开源了 50 多个插件,使用 Apache APISIX 作为服务网格的数据面,可以复用这些插件。如果现有插件不能满足业务需求,也可以自行开发插件, 而且 Apache APISIX 支持多语言开发插件,如 Java 和 Go。
\\n第三,降低运维成本。
\\n如果南北向流量和东西向流量的技术栈无法统一,需要在东西向上使用 Envoy,在南北向上使用 Apache APISIX,运维团队需要同时维护 2 个组件,这对运维人员来说是一个挑战。
\\n使用基于 Apache APISIX 的服务网格方案,能够统一南北向和东西向的技术栈,只需要管理 1 个组件,大大降低了运维成本。
\\n截止目前,apisix-mesh-agent 开源仅两个月时间,还有许多功能要完善,以下是对 Apache APISIX 服务网格未来的一些规划。
\\n第一,对 xDS 协议做更多支持
\\n目前,apisix-mesh-agent 只支持了 xDS 协议中的 LDS、RDS、CDS 和 EDS,而且只使用 LDS 绑定RDS 需要的路由配置名称,直接获取路由;使用 CDS 和 EDS 直接获取服务集群的定义和服务集群的实例。
\\n未来我们计划:
\\n第二,提升可观测性
\\n在调研阶段发现,实际使用场景中大家十分重视服务的可观测性,未来支持对接更多可观测方面的组件,如:Apache SkyWalking、其他日志收集的服务器。
\\n第三,自研控制面
\\n现在服务网格的控制面依托其他开源组件(如:Istio、Kuma),使得我们可以以较低的成本使用现有的功能,而如果未来遇到问题很难解决,也会考虑去落地实现一个专属 Apache APISIX 的服务网格控制面 ,使 Apache APISIX 的能力更好地发挥出来,服务网格在使用中也更加高效、简便。
\\n","description":"服务网格(Service Mesh)是处理服务间通信的基础设施层。它负责构成现代云原生应用程序的复杂服务拓扑来可靠地交付请求。通常会为每个服务实例提供一个“边车”(sidecar)代理实例。边车会处理服务间的通信、监控和安全相关的问题, 以及任何可以从各服务中抽象出来的逻辑。 Apache APISIX 简介\\n\\nApache APISIX 是一个动态、实时、高性能的 API 网关, 提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。\\n\\n功能亮点\\n\\n下面列举出 Apache APISIX 的部分功能亮点,更多功能特性请访问 Gi…","guid":"https://www.apiseven.com/blog/service-grid-solution-based-on-apache-apisix","author":"张超","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-08-19T16:00:00.043Z","media":[{"url":"https://static.apiseven.com/202108/1631065632487-3e46ee68-c1fb-4546-a82f-0f81504ce560.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1631065708334-74c2c1bb-adf9-49a4-9008-4e04a815b27b.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1631065632487-3e46ee68-c1fb-4546-a82f-0f81504ce560.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1631065948150-c5dea6fe-469d-4246-b847-d4868407c64f.jpg","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Go 让 Apache APISIX 如虎添翼","url":"https://www.apiseven.com/blog/go-makes-apache-apisix-better","content":"Apache APISIX 允许用户通过插件的方式来拓展功能,如鉴权、限流、请求改写等核心功能都是通过插件的方式实现的。虽然 Apache APISIX 核心代码是使用 Lua 编写的,但是 Apache APISIX 支持多语言开发插件,比如 Go 、Java。\\n这篇文章将详细讲解如何用 Go 来开发 Apache APISIX 插件。通过拥抱 Go 的生态圈,为 Apache APISIX 开创一片新天地,希望 Go 能让 Apache APISIX 如虎添翼!
\\n采用库的方式来使用 Go Runner,apisix-go-plugin-runner 中的 cmd/go-runner
官方给出的例子,展示该如何使用 Go Runner SDK。未来也会支持通过 Go Plugin 的机制加载预先编译好的插件。
$ tree cmd/go-runner\\ncmd/go-runner\\n├── main.go\\n├── main_test.go\\n├── plugins\\n│ ├── say.go\\n│ └── say_test.go\\n└── version.go\\n
\\n上面是官方示例的目录结构。main.go
是入口,其中最关键的部分在于:
cfg := runner.RunnerConfig{}\\n...\\nrunner.Run(cfg)\\n
\\nRunnerConfig
可以用来控制日志等级和日志输出位置。
runner.Run
会让应用监听目标位置,接收请求并执行注册好的插件。应用会一直处于这一状态直到退出。
打开 plugins/say.go
:
func init() {\\n err := plugin.RegisterPlugin(&Say{})\\n if err != nil {\\n log.Fatalf(\\"failed to register plugin say: %s\\", err)\\n }\\n}\\n
\\n由于 main.go
导入了 plugins 包,
import (\\n ...\\n _ \\"github.com/apache/apisix-go-plugin-runner/cmd/go-runner/plugins\\"\\n ...\\n)\\n
\\n这样就在执行 runner.Run
之前通过 plugin.RegisterPlugin
注册了 Say
。
Say
需要实现以下方法:
Name
方法返回插件名。
func (p *Say) Name() string {\\n return \\"say\\"\\n}\\n
\\nParseConf
会在插件配置变化的时候调用,解析配置并返回插件特定的配置上下文。
func (p *Say) ParseConf(in []byte) (interface{}, error) {\\n conf := SayConf{}\\n err := json.Unmarshal(in, &conf)\\n return conf, err\\n}\\n
\\n该插件的上下文是这样的:
\\ntype SayConf struct {\\n Body string `json:\\"body\\"`\\n}\\n
\\nFilter
会在每个配置了 say 插件的请求中执行。
func (p *Say) Filter(conf interface{}, w http.ResponseWriter, r pkgHTTP.Request) {\\n body := conf.(SayConf).Body\\n if len(body) == 0 {\\n return\\n }\\n\\n w.Header().Add(\\"X-Resp-A6-Runner\\", \\"Go\\")\\n _, err := w.Write([]byte(body))\\n if err != nil {\\n log.Errorf(\\"failed to write: %s\\", err)\\n }\\n}\\n
\\n可以看到 Filter 把配置里面的 body 的值作为响应体。如果在插件中直接进行响应,就会中断请求。
\\nGo Runner SDK API 文档:https://pkg.go.dev/github.com/apache/apisix-go-plugin-runner
\\n把应用构建起来后(在示例里面是 make build
),在运行时需要设置两个环境变量:
APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock
APISIX_CONF_EXPIRE_TIME=3600
像这样:
\\nAPISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock APISIX_CONF_EXPIRE_TIME=3600 ./go-runner run\\n
\\n应用运行时会去监听 /tmp/runner.sock
。
首先要安装 Apache APISIX,需要和 Go Runner 位于同一实例上。
\\n上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 负责运行不同语言编写的外部插件。apisix-go-plugin-runner 就是这样支持 Go 语言的 runner。
\\n当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会把 plugin runner 作为自己的一个子进程,该子进程与 Apache APISIX 进程属于同一个用户,当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
\\n如果为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发 Apache APISIX 通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
\\n根据需要配置 plugin runner 的执行时机。
\\nplugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行其他语言编写的插件,并将结果返回给 Apache APISIX。
\\n这些插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
\\n为了展示如何开发 Go 插件,我们先设置 Apache APISIX 进入开发模式。在 config.yaml 中增加以下配置:
\\next-plugin:\\n path_for_test: /tmp/runner.sock\\n
\\n这个配置的意思是,命中路由规则后,Apache APISIX 会向 /tmp/runner.sock 发起 RPC 请求。
\\n接下来设置路由规则:
\\ncurl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\": \\"/get\\",\\n \\"plugins\\": {\\n \\"ext-plugin-pre-req\\": {\\n \\"conf\\": [\\n {\\"name\\":\\"say\\", \\"value\\":\\"{\\\\\\"body\\\\\\":\\\\\\"hello\\\\\\"}\\"}\\n ]\\n }\\n },\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n }\\n }\\n}\\n\'\\n
\\n注意插件名称配置在 name
里面,插件配置(经 JSON 序列化后)放在 value
里面。
如果在开发过程中看到 Apache APISIX 端有 refresh cache and try again
的 warning 和 Runner 端有 key not found
的 warning,这是因为配置缓存不一致导致的。因为开发状态下,Runner 不是由 Apache APISIX 管理的,所以内部状态会有可能不一致。不用担心,Apache APISIX 会重试。
然后我们请求一下:curl 127.0.0.1:9080/get
\\n$ curl http://127.0.0.1:9080/get\\nHTTP/1.1 200 OK\\nDate: Mon, 26 Jul 2021 11:16:11 GMT\\nContent-Type: text/plain; charset=utf-8\\nTransfer-Encoding: chunked\\nConnection: keep-alive\\nX-Resp-A6-Runner: Go\\nServer: APISIX/2.7\\n\\nhello\\n
\\n可以看到接口返回 hello 而且没有访问到任何上游。
\\n这里以 go-runner 为例,只需把运行命令行配置在 ext-plugin 里就可以运行了:
\\next-plugin:\\n # path_for_test: /tmp/runner.sock\\n cmd: [\\"/path/to/apisix-go-plugin-runner/go-runner\\", \\"run\\"]\\n
\\nApache APISIX 会把 plugin runner 作为自己的一个子进程,管理它的整个生命周期。
\\n注意:这时就不要配置 path_for_test 了。Apache APISIX 在启动 runner 时会自动分配一个 unix socket 地址供 runner 监听。APISIX_LISTEN_ADDRESS 和 APISIX_CONF_EXPIRE_TIME 这两个环境变量也不用手动设置。
\\n目前 Go Plugin Runner 还处于早期开发阶段,我们会陆续完善其功能。成功的开源项目离不开大家的贡献,欢迎各位参与到 apisix-go-plugin-runner 的开发中来,让我们一起共建 Apache APISIX 和 Go 的桥梁!\\n点击访问 apisix-go-plugin-runner.
\\n根据 GitHub 2020 年的统计显示,这一年新增了 6000 万个代码仓库,超过 5600 万的开发者参与到开源项目中。预计到 2025 年,在 GitHub 参与开源项目的开发者人数将会超过 1 亿。
\\n在这些快速增长的数字背后,隐藏的是开源项目为了赢得开发者而做出的各种宣传:硬核技术文章、社交活动、新媒体、周边礼物等,可以说是乱花渐欲迷人眼。那么对于开发者来说,如何能够在百花齐放的项目中,找出最适合自己公司的那一个呢?
\\n这就会涉及到开源项目的各种指标:
\\nStar 数:这是最直接的指标,它代表的是这个项目吸引了多少开发者的关注,可以体现这个项目的 marketing 水平。如果这个项目有商业公司资金的支持、强力的 PR 团队,或者是水军刷 Star,那么这个指标就很容易失真;
\\nIssue 和 PR 数:GitHub 提供了 Insights 功能,如下图所示:
\\n可以选择最近一周、最近一个月的时间内,这个开源项目的 Issue 和 PR 的新建和关闭数。上图是 Apache APISIX 最近一个月的数据。
\\nGitHub insights 提供了一个非常棒的开发者视角,但还不够完美:Issue 和 PR 的质量如何?这些是没有办法量化的;
\\n看到这里,你是不是觉得选择一个开源项目好复杂,看了这么多指标都得不出答案。有没有一个“金指标”,一个通过 marketing 砸不出来的指标?一个能够体现“开发者为核心”的指标?
\\n作为开源项目的维护者和开发者,我们也需要这样的金指标来指引我们。所以,我们提出了 “贡献者增长” 和 “活跃贡献者”这两个维度,并将统计和分析的过程开源出来:https://github.com/api7/contributor-graph。你也可以通过 www.apiseven.com/contributor-graph 直接进行检索。下面是 Apache APISIX 的示例:
\\n通过上面两个表格,你可以清晰的看到 Apache APISIX 从创办至今,贡献者都保持着稳定的增长,每个月都有 25 个左右的代码贡献者参与其中。
\\n“贡献者增长” 和 “活跃贡献者”图表都支持在多仓库之间比较。更重要的是,我们会拉取 Github API 每日/每月定时更新图表,只要一次性的复制使用我们提供的链接,您的仓库就可以始终显示实时的贡献者数据。
\\n贡献者增长曲线的数据来源是项目每个 contributor 首次提交 commit 的日期。通过贡献者增长曲线,我们可以在 Github 首页显示的贡献者总人数基础上观察贡献者增长情况,从而对社区的发展情况作出直观判断。
\\n通过同时展示同一领域中的多个仓库,我们也可以直观比较不同社区的发展情况。
\\n在上图中,我们可以看到 Apache APISIX 的贡献者人数以非常快的速度增长,仅仅用了两年时间,贡献者人数就基本赶上甚至超越了其他开源网关项目。
\\n月度贡献者曲线数据则来自于每月提交 commit 的贡献者数量。
\\n相比贡献者增长曲线,月度贡献者可以更好衡量短时间内的社区发展情况。
\\n例如在上图中,我们可以看到如今 Apache APISIX 是多个开源网关项目中的月度贡献者人数最多、最稳定的。
\\n这也解释了为何 Apache APISIX 可以在开源后如此短的时间内在总贡献者人数上赶上友商们。
\\n上面这张比较开源消息中间件社区的月度贡献者的图,曾在推特引发热议。
\\n通过这张图,我们可以看到 Apache Pulsar 在月度贡献者上迎头赶上了 Apache Kafka。
\\n目前贡献者图表已经在 Apache APISIX 、Apache Skywalking、Apache DolphinScheduler、Apache Openwhisk、Apache ShardingSphere、awesome-docker、TiDB docs-dm 等多个开源项目中使用。
\\n在用户使用并反馈的过程中,我们实现了更多的需求,比如添加“匿名”贡献者,或是项目由 SVN 迁至 GitHub 后添加 SVN 侧的贡献者等。
\\n好程序都是起源于程序员要解决的切身之痛。当我们聊 Contributor Graph 时,我们不仅希望借助这个工具生产更加直观的展示 Apache APISIX 社区活跃度的图表,我们同时开源了这个小工具,希望这个工具可以帮助到其他的开源项目。
\\n欢迎大家使用贡献者趋势图表来跟踪您的社区活跃度,任何需求和问题都欢迎到 Contributor Graph 的 GitHub 仓库中反馈。
\\n您可以通过以下链接或者点击阅读原文,访问 Contributor Graph repository。
\\n","description":"根据 GitHub 2020 年的统计显示,这一年新增了 6000 万个代码仓库,超过 5600 万的开发者参与到开源项目中。预计到 2025 年,在 GitHub 参与开源项目的开发者人数将会超过 1 亿。 在这些快速增长的数字背后,隐藏的是开源项目为了赢得开发者而做出的各种宣传:硬核技术文章、社交活动、新媒体、周边礼物等,可以说是乱花渐欲迷人眼。那么对于开发者来说,如何能够在百花齐放的项目中,找出最适合自己公司的那一个呢?\\n\\n这就会涉及到开源项目的各种指标:\\n\\nStar 数:这是最直接的指标,它代表的是这个项目吸引了多少开发者的关注…","guid":"https://www.apiseven.com/blog/contributors-the-golden-metric-of-opensource-projects","author":"Yiyiyimu","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-08-13T16:00:00.965Z","media":[{"url":"https://static.apiseven.com/202108/20210814001.webp","type":"photo","width":1080,"height":370,"blurhash":""},{"url":"https://static.apiseven.com/202108/20210814002.webp","type":"photo","width":1080,"height":405,"blurhash":""},{"url":"https://static.apiseven.com/202108/20210814003.webp","type":"photo","width":1080,"height":714,"blurhash":""},{"url":"https://static.apiseven.com/202108/20210814004.webp","type":"photo","width":1080,"height":658,"blurhash":""},{"url":"https://static.apiseven.com/202108/20210814005.webp","type":"photo","width":1080,"height":670,"blurhash":""},{"url":"https://static.apiseven.com/202108/20210814006.webp","type":"photo","width":1080,"height":649,"blurhash":""},{"url":"https://static.apiseven.com/202108/20210814007.webp","type":"photo","width":1080,"height":647,"blurhash":""}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"如何利用 Apache APISX 提升 Nginx 的可观测性","url":"https://www.apiseven.com/blog/using-apache-apisix-to-improve-the-observability-of-nginx","content":"“可观测性“是一种度量手段,方便掌握基础设施、系统平台或者应用程序的运行状况。常见的手段是收集 metrics、logging 和 tracing 及 events 数据,可以帮助开发人员和运维人员检测、调查、预警和纠正系统问题。
\\n本文将从 Nginx 可观测性、Apache APISIX 与 Nginx 的关系、Apache APISIX 可观测性,以及结合 Apache SkyWalking 进一步提升可观测性这些方面分享关于可观测性的方案与实践。
\\nNginx 在一定程度上能够做到可观测,以下罗列出 Nginx 的常见监控方式:
\\nngx_http_stub_status_module 主要收集实例级别的统计信息。
\\nVTS module 有 3 个比较明显的缺点:
\\n安装复杂:虽然 VTS module 能够采集指标,采集的指标类型也比较多,但是它的安装比较复杂。如果想要采用 VTS module,需要重新编译 Nginx,在编译 Nginx 之前加入 VTS moudle,完成编译后重新安装 Nginx 才可以正常使用 VTS。
\\n扩展能力弱:VTS 扩展能力分为两部分,一是在编译之前给 VTS 增加扩展;二是在编译之后增加扩展 —— 修改 nginx.conf 配置文件。通过修改 nginx.conf 文件来增加扩展会使 Nginx reload,生产环境直接 reload 或多或少会对业务产生一些影响。
\\n社区更新缓慢:VTS module 最新的一次更新是在 2018 年,已经停摆 3 年了。
\\nNginx Amplify 是一个 SaaS 服务,Nginx Amplify 在远端提供服务,在 Nginx 服务之外安装 Agent。\\n在 Nginx 之外安装采集模块,那么在采集指标上就会有限制,只能拿到 Nginx 暴露出来的信息,没有暴露的内部信息是拿不到的。
\\n另外,由于 Nginx Amplify SaaS 是一个 SaaS 服务,需要通过公网将采集到的数据传到服务端,这会带来一些安全隐患,同时把一些企业用户阻挡在外面。或许 Nginx Amplify 的目标群体是 Nginx plus 这样的企业用户,不是开源用户。
\\n另外,Nginx Amplify SaaS 社区也不活跃,已经停摆 2 年。
\\nNginx 在 Events 收集上自身有缺陷,这里列举出两个问题:
\\nNginx 基于 nginx.conf 进行配置,修改后通过 reload nginx.conf 文件使配置生效。除 reload 事件外,没有其他 Events 可用,我们无法得知每次修改文件的变化,如:起初只配置 1 个路由,修改文件增加 10 个路由,只有 reload 事件无法得知增加的到低是哪 10 个路由。
\\nNginx 开源产品缺少主动健康检查。Nginx 是一个反向代理,真正的后端服务可能会出现重启、升级或者异常的情况,如果没有主动的健康检查,依靠被动检查,只能在流量出现异常的时候,才知道服务出了问题,这会丢掉很多 Events,导致上游 Events 事件信息不完整。
\\nNginx 的开源版本没有提供非常好用的监控。虽然 Nginx 提供了一些监控工具,但这些工具的安装和配置非常复杂,几乎没有扩展性。可能这些工具的设计并不是为了可观测性,只是为了能看到指标或统计数据,方便定位问题。现在有各种可观测性设置类的产品,但是很难集成到 Nginx 上。
\\n另外,Nginx 社区停滞不前,导致 Nginx 迭代速度慢。
\\nApache APISIX 基于 Nginx 实现,但只依赖 Nginx 的网络库,在 Nginx 基础上,Apache APISIX 实现了自己的核心的代码,并预留了扩展机制。
\\n在表格中列出了 Apache APISIX 和 Nginx 的功能对比,Apache APISIX 既可以做反向代理,又可以实现一些 Nginx 不支持的功能,如:主动健康检查、流量管理、横向扩缩容等,而且这些功能都是开源的。
\\nApache APISIX 是一个动态、实时、高性能的 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。Apache APISIX 也是全世界最活跃的开源 API 网关项目,是生产可用的高性能网关。全球已有数百家企业使用 Apache APISIX 处理关键业务流量,涵盖金融、互联网、制造、零售、运营商等等,比如美国航空航天局(NASA)、欧盟的数字工厂、中国航信、中国移动、腾讯、华为、微博、网易、贝壳找房、360、泰康等。
\\n上图左边,从上往下是从单体服务到 SOA(面向服务的架构)到微服务的演进过程。
\\n在 SOA 下,网关一般采用 Nginx 或者 HAProxy;在微服务架构下,网关使用 Nginx 做负载均衡。微服务架构有两个比较常见的解决方案:一个是基于 Java 技术栈实现,如 Spring Cloud 系列;另一个是 Service Mesh。
\\n在这个演进过程中,Apache APISIX 处于什么位置,能做什么呢?
\\n简单的说,左图中红色的部分(Nginx / HAProxy / Kong / Spring Cloud Zuul / Spring Cloud Gateway / Traefik / Envoy / Ingress Nginx)都可以替换为 Apache APISIX 的解决方案。
\\n在 SOA 下有 Apache APISIX SLB 解决方案,在微服务架构下有 Apache APISIX Gateway,在 Kubernetes 部署有 Apache APISIX Ingress,在 Service Mesh 里部署有 Apache APISIX mesh。
\\n从业务请求的流量方面看,当客户端发起请求时会经过 LB,经过 Gateway,请求被分发到后端业务服务。红色的部分(LB / Gateway / Spring Cloud Gateway / K8s Ingress / Sidecar)都可以选择 Apache APISIX 作为解决方案。Apache APISIX 支持多语言开发插件,可以在 Java 体系下使用 Java 编写插件。
\\nApache APISIX 是全流量的数据面,在 LB、Gateway、Ingress、sidecar 方面 Apache APISIX 都有相应的解决方案,他们是统一的解决方案,在可观测性方面也是统一的方案。当解决方案统一时,管理控制链也是很容易实现出来的。
\\n简单了解完 Nginx 和 Apache APISIX 之后,现在有两个问题:Apache APISIX 在可观测性上可以做哪些事情?Apache APISIX 可观测性上的优势在哪里?
\\nApache APISIX 支持采集的数据类型:
\\nApache APISIX 是一个网关类的产品,可以替代 Nginx 或者其他的网关;在可观测性上 Apache APISIX 可以集成多个 APM 或可观测性系统,如:Tracing 部分可以集成 SkyWalking,Metrics 指标上可以集成 SkyWalking 或 Prometheus,Logging 可以集成 SkyWalking 以及其他一些日志系统。
\\n为什么 Apache APISIX 拥有强大的扩展能力?因为 Apache APISIX 支持多语言编写插件,可以使用 Lua、Java、Golang 等编程语言编写插件。Apache APISIX 可以通过插件扩展自身的能力。上文提到的三种数据类型,都是通过插件机制来实现的。
\\n举三个例子来介绍一下 Apache APISIX 灵活的配置能力。
\\n第一个例子是 Apache APISIX 可以在运行时修改 logging 的配置,如:增加或修改日志字段。修改日志字段是一个比较常见的需求,比如:业务刚开始上线时,配置好了日志字段,系统运行一段时间后,需要修改或者增加几个日志字段。如果使用 Nginx,通过修改 nginx.conf 文件实现需求,reload 使配置生效。 Apache APISIX 只需要通过脚本把字段配置好,就会动态生效。
\\n第二个灵活配置能力的例子是 Prometheus 的使用。在 Apache APISIX 里,想要创建 / 删除某一个 metric 或者扩展 metrics labels,只需要在 Prometheus 插件里新增一个 metircs 或者填写相关信息,Apache APISIX 有 hot reload 机制可以直接生效,不需要重启。
\\n第三个灵活的配置能力体现在 Apache APISIX 的实现。Apache APISIX 把路由对象全部管理起来,在内存里有一套对象管理机制。在 Apache APISIX 里给某个 API 加插件,生效的级别可以细化到 API,每一个 API 都可以绑定插件,也可以从 API 上把插件去掉。 Apache APISIX 可以精细化控制到每一个服务里面每一个 API 的可观测性数据采集。换句话说,你可以只采集最关心的数据,而且这些配置都是动态生效的,可以随时调整。
\\nApache APISIX 最重要的一个优势是有一个活跃的社区,一个活跃的社区可以让产品快速迭代、变得越来越完善,让大家的需求得到满足。
\\n上图展示的是 Apache APISIX(绿色)、Kong(浅蓝)、mosn(黄色)、bfe (深蓝)贡献者增长曲线,Apache APISX 增长趋势最快,曲线最为陡峭。 Apache APISIX 社区活跃度在同类型项目里面是最活跃的。
\\nApache APISIX 与 Apache SkyWalking 结合可以做哪些提升?除了 SkyWalking tracing 插件,还可以将tracing、metrics、logging、events 汇聚到 SkyWalking,借助 SkyWalking 的聚合能力让数据实现联动。
\\nSkyWalking Satellite 由 Apache APISIX社区、Apache SkyWalking 社区、百度深度合作开发。
\\nSkyWalking Satellite 按照上图步骤采集数据,SkyWalking Satellite 可以部署到更靠近产生数据的前端,以 sidecar 的形式存在。
\\n图中从上往下业务请求经过 Apache APISIX 代理到 Upstream,Satellite 在 Apache APISIX 的旁边,以 sidecar 的形式部署,收集 Apache APISIX 的 tracing、metrics、logging 这三种数据类型的数据,通过 GRPC 协议发送给 SkyWalking。
\\n最重要的一点是:在这种部署方式下,Apache APISIX 不需要做任何改动就可以直接将三种数据类型集成到 SkyWalking。
\\nALS (Access Log Service)将经过 Apache APISIX 的访问日志发送出来,在普通的 access log 上增加特殊的字段,如:增加关键字段便于生成拓扑图,同时聚合出 metrics。
\\nALS 方案最大的好处是可以直接通过 access log 方式分析和聚合出拓扑图、metrics 、logging 这三种类型的数据。\\n在使用 Prometheus 时,如果配置了 URI 级别的 metrics 指标的统计,会导致整个 metrics 急剧膨胀。因为 URI 级别的服务可能有几十个,每个 metrics 后面可能有许多 labels,这会降低网关性能,增加 metrics 获取难度。使用 ALS 方案,通过流的方式将数据发送给 SkyWalking,把计算的事情交给 SkyWalking,后续也方便查询,不会出现每隔几秒钟拉取一次非常庞大的数据的情况。
\\n常用的 Events 包括:配置分发、集群变化、健康检查。
\\n配置分发:在配置 API 分发时,可能会新增路由、修改路由、删除路由或增加插件。
\\n集群变化:集群发生变化时,需要知道集群里的服务数。如:扩容时 IP 会发生变化,变化体现在网关收到消息的时候。每个过程都是一个事件,这些事件都需要被暴露出来。
\\n健康检查:主动探测是否健康,例如:业务请求失败率突然变高,事件探测到业务服务不健康,此时可以快速定位到问题。
\\n问题:Apache APISIX 的扩展机制是怎么实现的?扩展这个功能是否对 Apache APISIX 本身稳定性有影响?
\\n答:Apache APISIX 扩展机制得益于它的架构,可以在各个 phases (rewrite / access / header_filter / body_filter / preread_filter / log)增加业务逻辑。
\\n至于稳定性方面, Apahce APISIX 已经开源了近 50 个插件,每一个插件都会有端到端的测试,这些插件都是经过验证的、是稳定可用的。但是自定义插件要遵循一定的规范,虽然很简单,但是大家也不能太随意。自定义插件的稳定性保证,需要由业务方自己来保证。
\\n问:Nginx 的 nginx.conf 文件里面可能配置了很多规则,后面的规则可能被前面的规则拦截,不清楚后面的规则是否生效,Apache APISIX 是否有什么方法知道哪些规则已生效?
\\n答:Nginx 的 nginx.conf 文件配置越多,配置服务越复杂,这个文件越难以维护。但是在 Apache APISIX 里配置文件是固定的,Apache APISIX 官方提供的配置就是在大多数场景下的最优配置,其他路由的配置是通过 API 的方式配置进去的,路由配置都是在内存里面的。
\\n在管理方式上,可以通过多种组织方式管理你的路由,例如,可以通过 Dashboard 来管理。
\\n举例说明,比如有一个服务叫 ABC,在这个服务下面可会有各种路由定义,路由定义通过列表的方式进行查看,路由里有一个字段叫优先级,可以通过配置路由的优先级字段,让相似的路由规则按照优先级依次匹配。另外一种路由查看方式是在 dashboard 中给 API 打上标签,可以让路由的管理变得更加人性化,便于按照标签过滤查询路由列表。
\\n金卫,Apache APISIX PMC 和 Apache SkyWalking committer。
\\nApache APISIX 是一个生产可用的开源七层全流量处理平台,可作为 API 网关处理业务入口流量,具有极高性能、超低延迟,官方支持 dashboard 以及超过五十种插件。如果你正在使用 Kong,对 APISIX 感兴趣又苦于难以上手,不妨试试我们刚开源的迁移工具 Kong-To-APISIX,助你一键平滑迁移。
\\nKong-To-APISIX 利用 Kong 和 APISIX 的声明式配置文件实现了配置数据的迁移,并根据两侧架构和功能的不同做出相应适配。目前我们支持了 Kong 一侧 Route、Service、Upstream、Target,Consumer 以及三个插件 Rate Limiting、Proxy Caching 以及 Key Authentication 的配置迁移,并以 Kong 的 Getting Started Guide 为例,完成了一个最小的 demo。
\\n使用 Deck 导出 Kong 声明式配置文件,点击查看具体步骤
\\n下载仓库并运行迁移工具,迁移工具会生成声明式配置文件 apisix.yaml
待使用
git clone https://github.com/api7/kong-to-apisix\\n\\ncd kong-to-apisix\\n\\nmake build\\n\\n./bin/kong-to-apisix migrate --input kong.yaml --output apisix.yaml\\n\\n# migrate succeed\\n
\\n使用 apisix.yaml
配置 APISIX, 点击查看具体步骤。
确保 docker 正常运行,部署测试环境,使用 docker-compose 拉起 APISIX、Kong
\\ngit clone https://github.com/apache/apisix-docker\\n\\ncd kong-to-apisix\\n\\n./tools/setup.sh\\n
\\n根据 Kong 的 Getting Started Guide,为 Kong 添加配置并进行测试:
\\na. 通过 Service 和 Route 暴露服务,进行路由转发
\\nb. 设置 Rate Limiting 和 Proxy Caching 插件做限流缓存
\\nc. 设置 Key Authentication 插件做认证
\\nd. 通过 Upstream 和 Target 设置负载均衡
\\n./examples/kong-example.sh\\n
\\n导出 Kong 的声明式配置文件到 kong.yaml
go run ./cmd/dumpkong/main.go\\n
\\n运行迁移工具,导入 kong.yaml
并生成 APISIX 配置文件 apisix.yaml
至 docker volumes
export EXPORT_PATH=./repos/apisix-docker/example/apisix_conf\\n\\ngo run ./cmd/kong-to-apisix/main.go\\n
\\n在 APISIX 一侧测试迁移过后的路由、负载均衡、插件等是否正常运行
\\n测试 key auth 插件
\\ncurl -k -i -m 20 -o /dev/null -s -w %{http_code} http://127.0.0.1:9080/mock\\n# output: 401\\n
\\n测试 proxy cache 插件
\\n# access for the first time\\ncurl -k -I -s -o /dev/null http://127.0.0.1:9080/mock -H \\"apikey: apikey\\" -H \\"Host: mockbin.org\\"\\n# see if got cached\\ncurl -I -s -X GET http://127.0.0.1:9080/mock -H \\"apikey: apikey\\" -H \\"Host: mockbin.org\\"\\n# output:\\n# HTTP/1.1 200 OK\\n# ...\\n# Apisix-Cache-Status: HIT\\n
\\n测试 limit count 插件
\\nfor i in {1..5}; do\\n curl -s -o /dev/null -X GET http://127.0.0.1:9080/mock -H \\"apikey: apikey\\" -H \\"Host: mockbin.org\\"\\ndone\\ncurl -k -i -m 20 -o /dev/null -s -w %{http_code} http://127.0.0.1:9080/mock -H \\"apikey: apikey\\" -H \\"Host: mockbin.org\\"\\n# output: 429\\n
\\n测试负载均衡
\\n httpbin_num=0\\n mockbin_num=0for i in {1..8}; do\\n body=$(curl -k -i -s http://127.0.0.1:9080/mock -H \\"apikey: apikey\\" -H \\"Host: mockbin.org\\")\\n if [[ $body == *\\"httpbin\\"* ]]; then\\n httpbin_num=$((httpbin_num+1))\\n elif [[ $body == *\\"mockbin\\"* ]]; then\\n mockbin_num=$((mockbin_num+1))\\n fi\\n sleep 1.5done\\n echo \\"httpbin number: \\"${httpbin_num}\\", mockbin number: \\"${mockbin_num}\\n # output:\\n # httpbin number: 6, mockbin number: 2\\n
\\n迁移工具的后续开发计划已在 Kong-To-APISIX 的 GitHub 仓库的 Roadmap 中呈现,欢迎大家访问 Kong-To-APISIX 的 GitHub 仓库地址 ,测试与使用 Kong-To-APISIX。\\n欢迎任何对这个项目感兴趣的人一同来为这个项目作贡献!有任何问题都可以在仓库的 Issues 区讨论。
\\n","description":"Apache APISIX 是一个生产可用的开源七层全流量处理平台,可作为 API 网关处理业务入口流量,具有极高性能、超低延迟,官方支持 dashboard 以及超过五十种插件。如果你正在使用 Kong,对 APISIX 感兴趣又苦于难以上手,不妨试试我们刚开源的迁移工具 Kong-To-APISIX,助你一键平滑迁移。 工具能力\\n\\nKong-To-APISIX 利用 Kong 和 APISIX 的声明式配置文件实现了配置数据的迁移,并根据两侧架构和功能的不同做出相应适配。目前我们支持了 Kong 一侧 Route、Service、Upstream…","guid":"https://www.apiseven.com/blog/kong-to-apisix","author":"Yiyiyimu","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-08-04T16:00:00.237Z","media":null,"categories":null,"attachments":null,"extra":null,"language":null},{"title":"插件编排在 Apache APISIX 中的应用与实践","url":"https://www.apiseven.com/blog/limit-rep-plug","content":"Apache APISIX 是一个生产可用的七层全流量处理平台,可作为 API 网关处理业务入口流量,具有极高性能、超低延迟的显著特性。它内置了 50 多种插件,覆盖身份验证、安全防护、流量控制、Serverless、可观测性等多个方面,可满足企业客户常见的使用场景。
\\n如下方架构图所示,Apache APISIX 分为数据面(左侧)与控制面(右侧)两部分:通过控制面下发配置到 ETCD,数据面借助丰富的插件处理内外流量。
\\nApache APISIX 暴露了一组接口,方便我们为 API 绑定插件。如果我们希望为 API 增加限速能力,只需为 API 绑定 limit-req
插件:
curl -X PUT http://127.0.0.1:9080/apisix/admin/routes/1 -d \'\\n {\\n \\"uri\\": \\"/get\\",\\n \\"methods\\": [\\"GET\\"],\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"httpbin.org:80\\": 1\\n }\\n },\\n \\"plugins\\": {\\n \\"limit-req\\": {\\n \\"rate\\": 1,\\n \\"burst\\": 2,\\n \\"rejected_code\\": 503,\\n \\"key\\": \\"remote_addr\\"\\n }\\n }\\n }\'\\n
\\n调用成功后,当请求到达该 API 时将进行限速管控。该示例使用 limit-req
实现 API 限速(特定功能),若针对“根据某个插件的处理结果,决定后续的请求处理逻辑”这种场景化需求,该怎么做呢?当前,现有的插件机制无法满足这种需求,这时便引申出插件编排的能力来解决这个问题。
插件编排是低代码的一种表现形式,它可以帮助企业降低使用成本、增加运维效率,是企业数字化转型过程中不可或缺的能力。借助低代码 API 网关 Apache APISIX 中插件编排能力,我们可以轻松地将 50+ 插件通过“拖拽”的方式进行组合编排,被编排的插件也能够共享上下文信息,最终实现场景化需求。
\\n扩展上述 API 限速的场景:请求使用 key-auth
插件进行身份认证,若认证通过,将由 kafka-logger
插件接管并进行日志记录;若认证失败(插件返回 401 状态码),将使用 limit-req
插件进行限速。
见如下操作视频:
\\n\\n\\n该视频中,Web 界面列出了目前已有的插件与画板,我们可以将插件拖拽到画板上进行编排,并填写插件绑定的数据,然后便完成了整个流程。在整个过程中:\\n那么 Apache APISIX 是如何与低代码能力结合的呢?这需要数据面 Apache APISIX 与控制面 Apache APISIX Dashboard 共同配合完成。整体流程如下:
\\n在 Apache APISIX 中,我们在 Route 实体中新增了 script 执行逻辑,可用于接收 Dashboard 生成的 Lua 函数并执行,它支持调用已有插件以复用代码。另外,它也作用于 HTTP 请求的生命周期中的各个阶段,如 access
、header_filer
、body_filter
等,系统会在相应阶段自动执行 script
函数对应阶段代码,见如下 script
示例:
{\\n \\"script\\": \\"local _M = {} \\\\n function _M.access(api_ctx) \\\\n ngx.log(ngx.INFO,\\\\\\"hit access phase\\\\\\") \\\\n end \\\\nreturn _M\\"\\n}\\n
\\n在 Dashboard 中,它包含了 Web 与 ManagerAPI 共两个子组件:Web 用于提供可视化界面,方便我们配置 API 网关;ManagerAPI 用于提供 RESTful API,供 Web 或其它客户端调用以便操作配置中心(默认为 ETCD),进而间接地控制 Apache APISIX。
\\n为了生成合法、有效的 script 函数,ManagerAPI 选择了 DAG 有向无环图的数据结构进行底层设计,并自主研发了 dag-to-lua
项目:它将根节点作为开始节点,根据判断条件决定下一个流转插件,这将有效避免逻辑死循环。如下为 DAG 数据结构的示意图:
对应到 ManagerAPI 接收的 script
参数上,示例如下:
{\\n \\"conf\\": {\\n \\"1-2-3\\": {\\n \\"name\\": \\"plugin-a\\",\\n \\"conf\\": {\\n ...\\n }\\n },\\n \\"4-5-6\\": {\\n \\"name\\": \\"plugin-b\\",\\n \\"conf\\": {\\n ...\\n }\\n },\\n \\"7-8-9\\": {\\n \\"name\\": \\"plugin-c\\",\\n \\"conf\\": {\\n ...\\n }\\n }\\n },\\n \\"rule\\": {\\n \\"root\\": \\"1-2-3\\", // 起始节点 ID\\n \\"1-2-3\\": [\\n [\\n \\"code == 200\\",\\n \\"4-5-6\\"\\n ], [\\n \\"\\",\\n \\"7-8-9\\"\\n ]\\n ]\\n }\\n}\\n
\\n即客户端将最终编排后的数据转换为上述格式后,ManagerAPI 会借助 dag-to-lua
项目生成 Lua 函数,并交给 Apache APISIX 执行。
在 Web 侧,经过挑选、对比与项目验证,我们选择了蚂蚁金服开源的 X6 图编辑引擎作为插件编排 Web 部分的底层框架,除了完善、清晰的文档外,一系列开箱即用的交互组件以及节点可定制化能力也是我们选择它的原因。
\\n在编排实现过程中,我们抽象出了通用元件与插件元件的概念:通用元件是指开始节点、结束节点与条件判断节点,插件元件则是每一个可用的 Apache APISIX 插件,通过将这些元件拖拽到画板中来完成插件编排的流程。如图所示:
\\n在拖拽过程中,我们需要限制一系列的边界条件,这里有几个例子:
\\n当插件未配置时,系统将出现「存在未配置的元件」的错误提示,可以直观地看到哪个插件没有配置数据:
\\n当编辑某条 API 时,若该 API 已经绑定了插件数据,当使用插件编排模式时,系统在检测后将出现警告信息,只有用户明确确认希望使用编排模式时,系统才能继续进行。这可以有效避免 API 数据被误操作的情况。
\\n此外,还存在诸如开始元件只能有一个输出、条件判断元件只能有一个输入等情况。试想:如果系统不加限制地让用户操作,不合理的插件组合既无意义,又会产生无法预料的错误,因此不断丰富边界条件,也是在设计插件编排时需要着重考虑的问题。
\\n当我们完成编排后,将使用 X6 暴露的 API 生成流程图的 JSON 数据,然后转换为系统需要的 DAG 数据,最终生成 Lua 函数。
\\n通过拖拽的方式,可以使得使用人员更方便地组合插件来满足不同的场景,以提升 API 网关可扩展能力与运维体验。在实际使用过程中,存在如下可以继续优化的问题:
\\nlocal _M = {\\n version = 0.1,\\n priority = 2500,\\n type = \'auth\',\\n name = plugin_name,\\n schema = schema,\\n # 新增的 result 字段,可存储插件运行结果,并传递到下个插件。\\n result = {\\n code = {\\n type = \\"int\\"\\n }\\n }\\n}\\n
\\n","description":"什么是 Apache APISIX? Apache APISIX 是一个生产可用的七层全流量处理平台,可作为 API 网关处理业务入口流量,具有极高性能、超低延迟的显著特性。它内置了 50 多种插件,覆盖身份验证、安全防护、流量控制、Serverless、可观测性等多个方面,可满足企业客户常见的使用场景。\\n\\n如下方架构图所示,Apache APISIX 分为数据面(左侧)与控制面(右侧)两部分:通过控制面下发配置到 ETCD,数据面借助丰富的插件处理内外流量。\\n\\nApache APISIX 暴露了一组接口,方便我们为 API 绑定插件。如果我们希望为…","guid":"https://www.apiseven.com/blog/limit-rep-plug","author":"琚致远","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-07-26T16:00:00.547Z","media":[{"url":"https://static.apiseven.com/202108/1630656070351-bc49128b-e0ef-4c93-830c-2ca7931dacce.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630657206662-02f0f699-8b9d-40f0-b36b-dbf700b16e02.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630658809809-af6b83e5-af52-4ad8-b9df-d406156f58ec.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630659104761-a9657939-9de1-4cb6-bd97-71fad26f923e.jpeg","type":"photo"},{"url":"https://static.apiseven.com/202108/1630659171895-53a07770-1d0a-4cea-951d-f2801e679481.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630659235474-5056489d-92b0-4253-9a6e-5135a60a5d3d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630659280585-2484bc8b-4396-4034-8399-de4cf639b81b.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"ApacheCon Asia 2021:Apache APISIX 技术议题一览","url":"https://www.apiseven.com/blog/apachecon-asia-2021","content":"ApacheCon 是 Apache 软件基金会的官方全球系列会议。自 1998 年以来,ApacheCon 一直吸引着各个层次的参与者,在 350 多个 Apache 项目及其不同的社区中探索 “明日的技术”。
\\nApacheCon Asia 是 ApacheCon 组委会针对亚太地区举办的 ApacheCon 在线会议,主要目标在于更好地服务亚太地区快速增长的 Apache 用户和贡献者。ApacheCon Asia 2021 将于今年 8 月 6-8 日在线举办。
\\n近期 ApacheCon Asia 2021 团队正式公布了大会日程,Apache APISIX 社区积极参与本次年度开源盛会,共提报了 8 个 API/微服务技术相关的议题,内容丰富,欢迎关注。同时,ApacheCon Asia 2021 也为无法参加在线会议的各位开源爱好者提供了每个议题的回放和录播视频,详情请移步 Apache Local Community 北京本地社区。
\\nAPI 是服务连接的基石,通过 API 我们可以将各种服务进行搭建,并提供给用户使用;随着应用的复杂度越来越高,单体应用逐渐被拆分为微服务,产品可以快速迭代的同时也带来安全、维护和可观测性方面的技术挑战。
\\nApache APISIX 是 Apache 顶级项目,也是全球最活跃的开源网关项目。在这个专题中,大家不仅可以了解 Apache APISIX 设计理念,也会学习到 Apache APISIX 项目的最佳实践。
\\n议题简介
\\n该演讲主题主要是讲述 Apache APISIX 在中国移动公有云对象存储 EOS 中的应用与实践经验分享。首先介绍了中国移动公有云建设规划及对象存储产品发展演进历程,然后阐述了我们为什么选择 Apache APISIX 作为负载均衡网关,并对 EOS 流量治理架构演进三个阶段进行进行了详细介绍。同时,我们还分享了基于 Apache APISIX 我们解决了哪些实际生产问题,做了哪些方案及开发工作,最后对我们未来的演进做了一些规划说明。
\\n分享嘉宾
\\n陈焱山 — 毕业后一直从事分布式存储软件开发及架构方案设计工作,深度参与了移动云建设过程,重点完成了对象存储相关的主要技术方案选型及落地开发建设工作。同时,在分布式对象存储领域拥有丰富的实战经验,目前正在思考基于APISIX七层网关实现对象存储流量治理工作,实现架构进一步升级。
\\n分享时间
\\n2021-08-07 15:30 GMT+8
\\n议题简介
\\n谈到限流限速,人们往往最先想到的是 Nginx。然而 Nginx 通过配置文件的方式实现,每次变更都需要 reload,这让运维工作极其繁杂。另一方面,限速的条件被限制在 Nginx 的变量范围内,使得 Nginx 难以实现业务上精细化的限流限速需求。
\\n本次分享将带来如何使用 Apache APISIX 来实现动态、精细化、分布式的限流限速,以及如何通过插件编排来实现更符合业务需求的限流限速。
\\n分享嘉宾
\\n陈军旭 — 互联网老兵,曾任职于新浪、迅雷、360等知名互联网公司。
\\n分享时间
\\n2021-08-06 13:30 GMT+8
\\n议题简介
\\nApache APISIX 是领先的 API 网关 OSS 之一。为了确保一切按计划进行,APISIX 使用了不同种类的测试,包括单元、e2e 和模糊测试。然而,我们仍然不确定,当一些不正常但不可避免的情况发生时,例如网络故障、IO 压力或 pod 故障,APISIX 会如何表现。
\\n因此,在这里我们使用 Chaos Mesh,一个基于 Kubernetes 的混沌工程平台,可以顺利地注入不同种类的混沌,并将其整合到我们的CI管道中。在这个讲座的最后,听众会了解到混沌工程会在哪些方面给 API 网关带来好处,以及如何将混沌网整合到你自己的测试管道中。
\\n分享嘉宾
\\nShuyang Wu — Apache APISIX 和 Chaos Mesh 的提交者,他领导了Chaos Mesh 与 Apache APISIX CI 的整合工作。
\\n分享时间
\\n2021-08-06 14:50 GMT+8
\\n议题简介
\\n认证和授权是 API 网关中非常必要的功能。这样一来,位于网关后面的服务就可以得到保护,避免未经授权或恶意的访问、数据泄露和黑客攻击。Apache APISIX 是一个动态、实时、高性能的API网关。而且它提供了许多插件,包括像 key-auth、Open-ID、wolf-RBAC 等认证和授权。本提案介绍了如何使用 Apache APISIX 来进行认证和授权。
\\n分享嘉宾
\\nXinxin Zhu — Apache APISIX 的提交者,有多年CDN工作经验,熟悉网关。
\\n分享时间
\\n2021-08-06 15:30 GMT+8
\\n议题简介
\\n在过去的一年里,Apahce APISIX 已经成为全世界最活跃的 API 网关项目,除了自身技术先进外,更得益于社区的高度活跃。截止目前,已经有来自世界各地 225 位贡献者参与贡献,并且还在保持高速增长。本次分享会介绍 APISIX 在践行“社区重于代码”过程的一些心得。作为一个理想主义创业者,又是如何与 Apache 文化结合,让创业公司也能高速发展。
\\n分享嘉宾
\\nYuansheng Wang — 开源爱好者 Apache APISIX创始人和PMC成员
\\n分享时间
\\n2021-08-06 16:10 GMT+8
\\n议题简介
\\n在这个议题中将介绍 apisix-mesh-agent 项目,它有一些能力将 Apache APISIX 扩展为服务网格场景中的边车程序,更重要的是,它使用 xDS 协议从 Istio、Kuma 等控制平面获取配置。之后,我将介绍关于在服务网中使用 Apache APISIX 的未来计划和期望。
\\n分享嘉宾
\\nChao Zhang — Apache APISIX PMC,OpenResty贡献者,开源爱好者,现在我正在研究 Service Mesh、Kubernetes 和API Gateway。
\\n分享时间
\\n2021-08-07 13:30 GMT+8
\\n议题简介
\\nApache APISIX是最受欢迎的API网关之一:https://github.com/apache/apisix,我将介绍一下 Apache APISIX 的发展,包括:
\\n分享嘉宾
\\nZexuan Luo — Apache APISIX 和OpenResty 的核心开发者
\\n分享时间
\\n2021-08-07 14:10 GMT+8
\\n议题简介
\\n介绍基于 Apache APISIX 的 Kubernetes Ingress 的优势以及 Apache APISIX Ingress 的特点。
\\n分享嘉宾
\\nWei Jin — Apache APISIX PMC / Apache apisix-ingress-controller Founder / Apache Skywalking Committer
\\n分享时间
\\n2021-08-07 14:50 GMT+8
\\n","description":"关于 ApacheCon Asia 2021 ApacheCon 是 Apache 软件基金会的官方全球系列会议。自 1998 年以来,ApacheCon 一直吸引着各个层次的参与者,在 350 多个 Apache 项目及其不同的社区中探索 “明日的技术”。\\n\\nApacheCon Asia 是 ApacheCon 组委会针对亚太地区举办的 ApacheCon 在线会议,主要目标在于更好地服务亚太地区快速增长的 Apache 用户和贡献者。ApacheCon Asia 2021 将于今年 8 月 6-8 日在线举办。\\n\\n近期 ApacheCon Asia…","guid":"https://www.apiseven.com/blog/apachecon-asia-2021","author":null,"authorUrl":null,"authorAvatar":null,"publishedAt":"2021-07-24T16:00:00.972Z","media":[{"url":"https://static.apiseven.com/202108/1630068124281-49ab6cdd-9b9f-4ddf-a498-7dcb101a2569.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630068124325-8a39eba3-43e6-4716-9577-d4727c4f621e.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630068124286-d6b2893d-bfee-48f2-a41c-3385f94e5c7a.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630068124311-50a0ca52-afab-461a-90e2-a87cdd13eb67.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630068124291-9f24abaf-310e-4d15-9022-6148ce52aff7.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630068124295-d8bb30c9-d8a2-4aeb-a503-c5fbb547cf55.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630068124301-91d8aa04-96a3-4485-9112-bd1341f23078.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630068124304-0d2eb7f5-2346-4be4-972b-7828f72b902e.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630068124297-bb14f11b-b2f4-46b9-b0c4-3e988581d759.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"API 网关 APISIX 在谷歌云 T2A 和 T2D 的性能测试","url":"https://www.apiseven.com/blog/how-is-google-cloud-tau-t2a-performing","content":"2022 年 7 月 13 日 Google Cloud 发布了第一个基于 Arm® 架构的 Tau T2A 的 VM 系列预览版。T2A VM 由基于 Ampere® Altra® Arm 的处理器提供支持,谷歌宣称其拥有极具吸引力的价格和卓越的单线程性能。
\\n值得注意的是,Ampere® Altra® Arm 是一款云原生处理器,基于 Ampere® Altra® Arm 处理器的 Tau T2A 虚拟机也因此能以高效的方式运行横向扩展的云原生应用程序。
\\n那么具体实际体验和性能如何呢?我们以一个云原生的 API 网关为例,带大家一起看看 Google Cloud Tau T2A 虚拟机的表现。这里,我们选择了 Apache APISIX 在 Google Cloud Tau T2A 服务器环境上进行安装测试。
\\nApache APISIX 是一个云原生、高性能、可扩展的 API 网关。基于 NGNIX + LuaJIT 和 etcd,APISIX 与传统 API 网关相比,具有动态路由和插件热加载特性,特别适合云原生架构下的 API 管理。
\\n首先需要在 Google Cloud 上启动一个 T2A 实例,操作系统选择 Ubuntu 20.04。
\\n然后安装 Docker,方便后续使用容器化的方式来安装部署 Apache APISIX。
\\nsudo apt-get update && sudo apt-get install docker.io\\n
\\nApache APISIX 使用 etcd 作为配置中心,所以这里需要先启动一个 etcd 实例。
\\nsudo docker run -d --name etcd \\\\\\n -p 2379:2379 \\\\\\n -e ETCD_UNSUPPORTED_ARCH=arm64 \\\\\\n -e ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 \\\\\\n -e ETCD_ADVERTISE_CLIENT_URLS=http://0.0.0.0:2379 \\\\\\n rancher/coreos-etcd:v3.4.16-arm64\\n
\\n启动 Apache APISIX 实例:
\\nsudo docker run --net=host -d apache/apisix:2.14.1-alpine\\n
\\n注册路由。
\\ncurl \\"http://127.0.0.1:9080/apisix/admin/routes/1\\" \\\\\\n-H \\"X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\\" -X PUT -d \'\\n{ \\n \\"uri\\": \\"/anything/*\\",\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"httpbin.org:80\\": 1\\n }\\n }\\n}\'\\n
\\n访问测试。
\\ncurl -i http://127.0.0.1:9080/anything/das\\n
\\nHTTP/1.1 200 OK\\n.....\\n
\\n从上述操作来看,Apache APISIX 在 Google Cloud Tau T2A 上的安装和兼容性测试都能顺利完成。那么 Google Cloud T2A 的实际性能到底如何呢?接下来我们将使用 Apache APISIX 分别在 Google Cloud T2A 和 Google Cloud T2D 上做性能测试对比,来看看其实际表现。
\\nGoogle Cloud T2D 是 Google Cloud Tau 系列的另一款机型,是基于 AMD x86 架构的,所以上述 etcd 安装步骤略有不同:
\\nsudo docker run -d --name etcd \\\\\\n -p 2379:2379 \\\\\\n -e ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 \\\\\\n -e ALLOW_NONE_AUTHENTICATION=yes \\\\\\n -e ETCD_ADVERTISE_CLIENT_URLS=http://0.0.0.0:2379 \\\\\\n bitnami/etcd:3.4.16\\n
\\n为简单起见,本次测试 APISIX 中只启用了一个 Worker,以下性能测试数据均在单核 CPU 上运行。
\\n该场景下将使用单个上游(不包含任何插件),主要测试 APISIX 在纯代理回源模式下的性能表现。在本地环境中进行测试:
\\n# apisix: 1 worker + 1 upstream + no plugin\\n\\n# 注册路由\\ncurl http://127.0.0.1:9080/apisix/admin/routes/1 \\\\\\n-H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\": \\"/hello\\",\\n \\"plugins\\": {\\n },\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\":1\\n }\\n }\\n}\'\\n
\\n该场景下将使用单个上游与两个插件进行,主要测试 APISIX 在开启 limit-count
和 prometheus
两个核心性能消耗插件时的表现。
# apisix: 1 worker + 1 upstream + 2 plugins (limit-count + prometheus)\\n\\n# 注册路由\\ncurl http://127.0.0.1:9080/apisix/admin/routes/1 \\\\\\n-H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\": \\"/hello\\",\\n \\"plugins\\": {\\n \\"limit-count\\": {\\n \\"count\\": 2000000000000,\\n \\"time_window\\": 60,\\n \\"rejected_code\\": 503,\\n \\"key\\": \\"remote_addr\\"\\n },\\n \\"prometheus\\": {}\\n },\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\":1\\n }\\n }\\n}\'\\n
\\n上述两个场景中,分别从请求 QPS(每秒查询数) 和延迟时间两个层面进行了相关的测试对比。结果如下:
\\n从以上数据也可以看出,在 API Gateway 等网络 IO 密集计算场景下,T2A 相比同系列的 T2D 虚拟机,在性能上仍然有差距。不过另一个好消息是,在同等配置情况下,T2A 的价格要比 T2D 便宜 10% 左右。在实际机器选型时,用户可以根据自己的业务体量来灵活决策。
\\n本文主要使用 Apache APISIX 对比 Google Cloud T2A 和 Google Cloud T2D 的性能。可以看出,在 API 网关等网络 IO 密集计算场景中,Google Cloud T2A 相比 T2D,表现虽然不是那么亮眼,但是作为 Google Cloud 在 ARM 架构下的第一次尝试,相信其会在 ARM 架构的虚拟机上持续发力,也期待它的后续迭代表现。
\\n","description":"背景 2022 年 7 月 13 日 Google Cloud 发布了第一个基于 Arm® 架构的 Tau T2A 的 VM 系列预览版。T2A VM 由基于 Ampere® Altra® Arm 的处理器提供支持,谷歌宣称其拥有极具吸引力的价格和卓越的单线程性能。\\n\\n值得注意的是,Ampere® Altra® Arm 是一款云原生处理器,基于 Ampere® Altra® Arm 处理器的 Tau T2A 虚拟机也因此能以高效的方式运行横向扩展的云原生应用程序。\\n\\n那么具体实际体验和性能如何呢?我们以一个云原生的 API 网关为例,带大家一起看看…","guid":"https://www.apiseven.com/blog/how-is-google-cloud-tau-t2a-performing","author":"赵士瑞","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-07-21T16:00:00.423Z","media":[{"url":"https://static.apiseven.com/2022/blog/0722/1.PNG","type":"photo"},{"url":"https://static.apiseven.com/2022/blog/0722/2.png","type":"photo"},{"url":"https://static.apiseven.com/2022/blog/0722/3.png","type":"photo"},{"url":"https://static.apiseven.com/2022/blog/0722/4.png","type":"photo"},{"url":"https://static.apiseven.com/2022/blog/0722/5.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"深度剖析 Apache APISIX Mesh Agent","url":"https://www.apiseven.com/blog/how-to-use-mesh-agent","content":"今年 6 月,支流科技推出了基于 Apache APISIX 的服务网格方案,其中 Apache APISIX 将作为服务网格的数据面,与支持 xDS 协议的控制面配合,进而托管服务间的流量。在该方案中有一个不可或缺的组件 apisix-mesh-agent,它作为数据面与控制面的中间层,完成了很多适配性的工作,进而让 Apache APISIX 在接近零改造的情况下即可完美地工作在服务网格中。
\\n本文将对 apisix-mesh-agent 进行分析,介绍其使用定位及其实现的功能。
\\n从使用角度上讲,apisix-mesh-agent 将和 Apache APISIX 共同运行在同一个(sidecar)容器内,事实上 Apache APISIX 也是由 apisix-mesh-agent fork 得到,这有点类似于 Istio 中 pilot-agent 与 Envoy 之间的关系。另外,它也负责在 Pod 启动后注入 iptables 规则(拦截服务实例的出入流量)。
\\n从图中可以看到,apisix-mesh-agent 负责和控制面交互(获取配置变更),Apache APISIX 负责实际的流量处理和转发。
\\n前面我们提到,apisix-mesh-agent 将和实现了 xDS 协议的控制面进行交互,从控制面处获取最新的配置变更,具体来说,apisix-mesh-agent 会通过 CDS (Cluster Disocvery Service)来获取集群列表,并进一步通过 EDS(Endpoint Discovery Service)获取这些集群的最新实例列表;集群列表和集群对应的实例列表将在 apisix-mesh-agent 内部转换为 Apache APISIX 的 Upstream 对象(EDS 的数据则是转换为 Upstream 的节点信息)。
\\n此外,apisix-mesh-agent 通过 LDS(Listener Discovery Service)获取动态监听器,apisix-mesh-agent 获取监听器后,主要的目的是获取其中的 HTTP Connection Manager 内的 RDS 名称表,进而能够发起 RDS 请求(Route Discovery Service),获取到具体的路由配置,这部分路由配置将被映射到 Apache APISIX 的 Route 对象。至于监听器本身,并不会为 Apache APISIX 所用。
\\n细心的读者可能会发现,这些监听器本身就是一个路由匹配条件,即目标服务的地址和端口信息,如果 Apache APISIX 忽略了这些监听器,那么是否会出现串路由的情况?事实上,我们通过在 Nginx 核心中添加了一个新的变量 $connection_original_dst,这个变量的值是流量原始的地址和端口信息(没有被 iptables 劫持的情况下),有了这一层判断以后,路由之间则不会出现乱串的情况。(感兴趣的同学可以点此了解这个变量的实现。)
\\n# 10.0.5.113:8000 监听器下的某路由配置\\n{\\n \\"name\\": \\"vhost1\\",\\n \\"domains\\": [\\n \\"apisix.apache.org\\"\\n ],\\n \\"routes\\": [\\n {\\n \\"name\\": \\"route1\\",\\n \\"match\\": {\\n \\"path_specifier\\": {\\n \\"prefix\\": \\"/foo/baz\\"\\n }\\n },\\n \\"action\\": {\\n \\"route\\": {\\n \\"cluster_specifier\\": {\\n \\"cluster\\": \\"httpbin.default.svc.cluster.local\\"\\n }\\n }\\n }\\n }\\n ]\\n}\\n\\n# 转换成 Apache APISIX 的配置后:\\n{\\n \\"uris\\": [\\n \\"/foo/baz*\\"\\n ],\\n \\"hosts\\": [\\n \\"apisix.apache.org\\"\\n ],\\n\\n # 该路由匹配时需要判断对应连接原始的目标地址是否是 \\"10.0.5.113:8000\\",即\\n # httpbin.default.svc.cluster.local 这一服务的 ClusterIP(只考虑 Kubernetes\\n # 场景)。\\n \\"vars\\": [\\n [\\"connection_original_dst\\", \\"==\\", \\"10.0.5.113:8000\\"]\\n ]\\n\\n # upstream_id 定义了 httpbin.default.svc.cluster.local 这一服务,\\n # 包含其最新的实例地址和其他相关的负载均衡、健康检查等配置。\\n \\"upstream_id\\": \\"90ba12b92e2d417f6802536696431724d59856ea\\"\\n}\\n
\\n转换后的配置将被缓存在 apisix-mesh-agent 的内存中。那么数据又该怎么传递给 Apache APISIX 呢?
\\nApache APISIX 使用 ETCD 作为其配置中心,通过 ETCD 的 watch 机制不断获取最新的配置从而保证其处理正确性。为了能让 Apache APISIX 在不做任何改变的情况下就能工作于服务网格场景中,我们让 apisix-mesh-agent 模拟了 ETCD V3 APIs,从而能够将其从控制面获取到的配置(加以转换后)传递到本地的 Apache APISIX 进程。
\\n目前 apisix-mesh-agent 主要实现的 API 有 Range (获取指定配置)和 Watch (监听指定配置变更)两个只读的 ETCD API 接口,并且支持了根据键值来获取不同的资源(如路由和上游资源)。对于 Watch 接口,我们需要推送增量更新事件,而类似 Istio 这样的控制面使用的是 xDS 协议中的 SotW(State of the World)变种,即每次都是推送全量数据,为了能够获取到更新事件,apisix-mesh-agent 会将当前获取到的数据与上一次的数据状态进行对比,从而对比得到增量更新事件然后传递到 Apache APISIX。
\\n通过引入 apisix-mesh-agent 这一中间层,我们成功地将 Apache APISIX 部署在服务网格中,未来 apisix-mesh-agent 也将支持 xDS 协议中更多的功能以及可观测性和证书管理等方面的能力,从而让 APISIX Mesh 变得更加成熟与强大。
\\n","description":"今年 6 月,支流科技推出了基于 Apache APISIX 的服务网格方案,其中 Apache APISIX 将作为服务网格的数据面,与支持 xDS 协议的控制面配合,进而托管服务间的流量。在该方案中有一个不可或缺的组件 apisix-mesh-agent,它作为数据面与控制面的中间层,完成了很多适配性的工作,进而让 Apache APISIX 在接近零改造的情况下即可完美地工作在服务网格中。 本文将对 apisix-mesh-agent 进行分析,介绍其使用定位及其实现的功能。\\n\\n使用定位\\n\\n从使用角度上讲,apisix-mesh-agent 将和…","guid":"https://www.apiseven.com/blog/how-to-use-mesh-agent","author":"张超","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-07-15T16:00:00.942Z","media":[{"url":"https://static.apiseven.com/202108/1630639686171-133e72d8-fcd1-4436-9be5-bc1d9b6ebb32.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Apache APISIX PMC 王院生:一线奋斗快二十年,希望我的代码有价值且长寿","url":"https://www.apiseven.com/blog/interview-yuanshengwang","content":"本文来自七牛云 ECUG 活动组对 Apache APISIX PMC 王院生的采访,现将文字摘录如下:
\\n问:请您简单介绍一下自己和目前从事的工作
\\n王院生:大家好,我叫王院生,是 Apache APISIX 的 PMC 成员,也是深圳支流科技创始人兼 CTO。2015 年通过一本电子书结识了社区中的广大朋友,以此开始在开源圈子里交了很多朋友。
\\n作为理想主义创业程序员,希望为世界做点贡献。于是 2019 年创造了开源项目 APISIX 并把它捐献给 Apache,同年创办了深圳支流科技,召集了很多志同道合热爱开源的伙伴一起创业。
\\n问:您自称是“理想主义青年”,请问您的“技术理想”是什么?
\\n王院生:我认为每个人都有理想主义情节,只是有些人害羞没有表达出来。作为程序员,我在一线奋斗快到二十年,我认为程序员的技术理想都差不多:希望我的代码可以被每个人用到。并且希望这些代码对社会、对世界是有价值并且长寿的。
\\n问:目前已经有很多可选的网关产品,为什么还要进入这个行业进行摸索?
\\n王院生:企业用户真正落地网关产品时会发现适合的网关产品其实并不多。网关产品是企业的流量出入口,还兼顾着保护和隐藏内部服务的作用,随着微服务、云原生等应用的更多落地,对 API 网关提出了新的需求,不仅要满足稳定性、安全性、性能、动态等基本要求,还需要支持动态扩缩容、容器化部署等云原生新特性。
\\n新时代有新需求,而我和创始人刚好在这方面有技术积累,所以就选择了这个行业。
\\n问:从诞生到成为 ASF 顶级项目只用了一年,您认为这中间最关键的因素是什么?
\\n王院生:这个问题经常被问到,Apache 的核心价值:社区大于代码。我和温铭从 2015 年开始组织社区,积累了大量社区用户,为 APISIX 快速毕业做了最好铺垫。通过下面贡献者增长曲线图可以看到,APISIX 从开源到现在一直是以成熟项目的速度在发展。
\\n问:云原生是当下的热门话题,但不同行业、领域的人对云原生的理解不同。您会如何定义或者理解云原生?
\\n王院生:看过很多这类定义,我给个比较简单的版本:支持容器化部署、支持弹性扩缩容。
\\n问:请就云原生相关生态在国内的发展趋势发表一些您的观点和看法吧。
\\n王院生:云原生相关生态在国内目前还是比较早期的阶段,基础设施这块整体来说国内还是追赶阶段。
\\n问:谈云原生离不开基础设施。您认为在云原生生态中的基础设施有什么特征?最关键的是什么?网关在当中是在承担一个什么角色?
\\n王院生:既然是基础设施,那么最典型的特征就是:具有强通用性,不绑定任何具体业务或软硬件平台。API 网关其实是把一些安全、审计、服务治理等一些通用功能内置实现,让应用只关心应用。
\\n问:有观点认为“Kubernetes 已经成为云时代的操作系统”;有人认为云原生的未来主要看 K8s,Service Mesh 和 Serverless 的发展,最终将从资源云化到业务云化。您怎么看?
\\n王院生:如果给未来十年后主流的后端架构投票,我会投给 Service Mesh。这个方向我是认可的。只不过它目前在易用、配套设施、效能等方面还没完全准备好,这需要时间,无法一蹴而就。
\\n问:您认为一线开发者,应该如何看待云原生?
\\n王院生:云原生是一套在云端构建和运行软件应用的方法,可以归结为一套技术方法论。作为一线开发者应尽早进入云原生世界,从中学习优秀的技术架构和基础设计,掌握方法论为公司和个人选择最适合的技术发展路线。
\\n","description":"本文来自七牛云 ECUG 活动组对 Apache APISIX PMC 王院生的采访,现将文字摘录如下: 问:请您简单介绍一下自己和目前从事的工作\\n\\n王院生:大家好,我叫王院生,是 Apache APISIX 的 PMC 成员,也是深圳支流科技创始人兼 CTO。2015 年通过一本电子书结识了社区中的广大朋友,以此开始在开源圈子里交了很多朋友。\\n\\n作为理想主义创业程序员,希望为世界做点贡献。于是 2019 年创造了开源项目 APISIX 并把它捐献给 Apache,同年创办了深圳支流科技,召集了很多志同道合热爱开源的伙伴一起创业。\\n\\n问:您自称是…","guid":"https://www.apiseven.com/blog/interview-yuanshengwang","author":null,"authorUrl":null,"authorAvatar":null,"publishedAt":"2021-07-12T16:00:00.247Z","media":[{"url":"https://static.apiseven.com/202108/1631256596586-671c5f27-1609-4029-98aa-8e7b879e545e.jpeg","type":"photo"},{"url":"https://static.apiseven.com/202108/1631256596591-fc5e48c5-8a7a-4d31-a6db-81722d1d60f4.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"张晋涛提名成为 Apache APISIX committer 同时提名成为中国首位 K8s ingress-nginx reviewer","url":"https://www.apiseven.com/blog/interview-apache-apisix-committer-jintaozhang","content":"近日,来自支流科技的工程师张晋涛通过投票提名成为 Apache APISIX committer,与此同时,张晋涛也被添加为 Kubernetes ingress-nginx 项目的 reviewer,这也是首位来自中国的 Kubernetes Ingress Controller reviewer。
\\n以下是 OSCHINA 对张晋涛的专访:
\\n问:请简单介绍下自己吧?
\\n张晋涛:我是张晋涛,是一个热爱开源,喜欢折腾的工程师。目前是 Apache APISIX committer, Kubernetes ingress-nginx reviewer 。在 Docker 和 Kubernetes 相关的很多项目都贡献过代码。我也是个一岁孩子的父亲。
\\n问:您是如何成为 Apache APISIX committer 的?成为 Apache APISIX committer 之后,有什么新的工作规划吗?
\\n张晋涛:我维护了 Apache APISIX 的 Helm chart 以及为 Apache APISIX Ingress Controller 增加了 consumer 和 annotation 等特性,同时还有一些社区的活动。在完成项目 GA 后,经过社区的投票和公示流程后,正式成为 Apache APISIX committer 。
\\n最主要的规划还是在 Apache APISIX Ingress controller 上,准备对其架构进行调整,让它更加好用。
\\n问:您是什么时候加入支流科技的?为什么加入,支流科技的哪些地方吸引您?目前主要负责什么工作?
\\n张晋涛:我是今年 4 月底加入支流科技的。支流科技是一家开源商业化公司,团队中的所有工程师都深度参与开源项目,在公司中也是以技术作为主导。全员远程,通过 GitHub 和 Slack 等进行协作,这种方式跟我平时参与开源项目体验一致。而且这里可以更好的发挥我的特长,也可以给我足够的自由,所以我比较喜欢。
\\n我在这边主要负责 Apache APISIX Ingress Controller ,我希望打造一款更棒的 Ingress Controller 。
\\n问:您成为 Kubernetes ingress-nginx 项目的 reviewer,可以给大家介绍下 reviewer 需要做些什么吗?项目选择 reviewer 的流程是怎样的?一般注重考察什么?
\\n张晋涛:reviewer 除了对项目进行代码贡献外,最主要就是去 review 其他贡献者的代码了,以保证项目的代码质量和正确性。与此同时,也需要去跑测试,来验证 PR 是否符合预期等。
\\n至于项目选择 reviewer 的流程,这个大前提是对项目要有持续的贡献,以及非常熟悉该项目。此外还要求至少是 5 个 PR 的主要 reviewer,以及合并过至少 20 个 实质性的 PR 。通过项目的 approver 进行提名,且没有其他人反对,就可以通过 PR 把名字写在项目的 OWNERS 文件中了。Kubernetes 相关项目的 reviewer 详细职责和选择流程等可参考此文档
\\n刚才也提到了,能否把握项目代码的质量和正确性这个是基础,也是大前提。在此基础上会重点考察贡献度和对项目的熟悉程度。
\\n问:您也是目前 Kubernetes Ingress Controller 开源项目唯一一位来自中国的 reviewer。可以聊聊 Kubernetes Ingress Controller 在 Kubernetes 生态中的地位和影响吗?有没有什么“过来人”的建议可以给到国内开发者?
\\n张晋涛:Kubernetes Ingress Controller 是 Kubernetes 社区的 Ingress Controller 实现,也是当前使用最为广泛的 Ingress Controller 。很多公司或者产品都在使用它作为 Kubernetes 集群的流量入口。目前在 GitHub 上有 10.5K 的 star 。
\\nKubernetes Ingress Controller 这个项目在各种生产环境下久经考验,代码质量和功能都是很不错的推荐大家可以关注和学习下。我在此项目中也看到过很多来自国内的开发者,说明大家对此项目也都是有所关注的,希望大家能够持续贡献。
\\n问:您运营「K8S 生态周报」已经两年多了,有没有总结出一些规律,比如大家更关注什么样的信息?
\\n张晋涛:自我 2019 年开始运营「K8S 生态周报」的这两年多的时间里,发现大家更关注 Kubernetes 自身的一些特性变更或者漏洞之类的,这也是我在 「K8S 生态周报」的每一篇中都有一个部分介绍“上游进展”的原因。此外,大家对于一些新项目,或者新的提案也比较感兴趣,会给我留言,或者加我微信来讨论。
\\n问:在「K8S 生态周报」内容的选取上有什么偏好或者原则吗?
\\n张晋涛:在每篇「K8S 生态周报」的开头,我都有写:「K8S 生态周报」内容主要包含我所接触到的 Kubernetes 生态相关的每周值得推荐的一些信息。
\\n我在《K8S 生态周报一周年了》这篇文章中也曾介绍我最初的想法。“Kubernetes 生态中相关信息和变化有很多,在这个信息爆炸的时代,稍不留神就会错过很多有价值的信息,但持续的去追这些消息,也过于浪费时间,而且还需要去筛选信息。”所以我维护的 「K8S 生态周报」并非简单的信息收集,还包含着我的思考及评价。每次周报的内容,都是我个人认为值得推荐和关注的信息。尤其是这是一份技术型的周报,而非纯资讯型,这也是和其他人或组织维护的周报最大的不同。
\\n问:您在许多技术社区都开设了专栏,也经常更新文章,写文章给您带来了哪些收获?您是如何在写代码之余还保持热情和精力大量产出文章的?
\\n张晋涛:写文章对我而言也是一个总结和学习的过程。一方面,写文章的时候,对知识进行总结归纳,可以让我加深印象以及梳理清楚其中的逻辑。另一方面,毕竟写文章和记笔记不同,会公开出来,所以对其中可能之前含糊的点,在写文章的时候,也会再次考证和实践。同时,因为我写的文章,也结识了不少朋友。
\\n写文章确实需要花费不少的时间和精力,我个人认为主要还是得做好时间得规划和管理。这方面我也还在探索和学习,做的并不好。目前可能更多的还是选择压榨其他时间吧。我一般会选择早上起来写文章。我使用 GitHub 的 Project 和 Issue 等来管理自己需要做的事情。
\\n问:看您之前的采访是 2014 年从 Docker “入坑”容器技术领域,近几年非常关注 Kubernetes,能对二者的发展做简单预测吗?对 Kubernetes 弃用 Docker 怎么看?
\\n张晋涛:其实 Docker 和 Kubernetes 我都在持续的关注。我在 Docker 主仓库的贡献者排行榜中是第 66 位。
\\nDocker 目前仍然是使用最为广泛的容器运行时和桌面容器化开发者工具。而且 Docker 目前的定位,也确实在做开发者工具方面投入了很多精力,包括默认集成了漏洞扫描工具,更好的磁盘管理工具等。未来的三五年内,Docker 在这个方面应该仍然是开发者的第一选择。
\\nKubernetes 是云原生的基石,未来的三五年内,仍然会是最主要的技术方向。此外,Kubernetes 也正在扩展其应用场景,包括 IoT 等领域。
\\n在 Kubernetes 宣布 kubelet 中废弃对 dockershim 维护后,我曾专门写过一篇文章 《Kubernetes 弃用 Docker 了?Docker 不能用了?别逗了!》 事实上,这件事情影响并没那么大。因为不用在 Kubernetes 代码仓库中的 dockershim 组件,也可以使用外部的 dockershim 组件。另外,从 Docker 中捐赠出来的 containerd 项目,已经是 CNCF 毕业项目了,我认为迁移到 containerd 也是个不错的选择。开发者本地的环境,可以继续使用 Docker 作为开发工具。
\\n问:此外您也是 Containerd、Docker、Helm、Kubernetes、KIND 等众多开源项目的 contributor,可以分享下参与开源项目贡献和开源社区活动的经验和想法吗?
\\n张晋涛:我认为参与开源贡献和开源社区活动等,主要还是应该从兴趣出发。在参与项目的时候,应该尽可能选择自己接触较多的,或者更感兴趣的项目。不要为了参与而参与,这样会把自己搞的比较累,而且对自己和社区都不一定是好事儿。
\\n开源社区是开放和包容的,无论你是提交 PR 来改进项目,还是提 issue 反馈 bug ,社区都是欢迎的。
\\n另外需要补充的一点,也是之前很多人在问我的一个问题,“参与开源社区有什么回报?”我参与开源很久了,除了目前我在支流科技可以全职做开源外,之前待过的任何一家公司,我都只能利用自己的业余时间去参与,花费了挺多时间和精力。但其实并没有任何物质上的回报。可能只是兴趣所在吧,恰好现在把兴趣变成了工作(还有一份不错的薪水)。欢迎任何对开源感兴趣的小伙伴给我发邮件交流,zhangjintao@moelove.info
\\n问:云原生向来也是开源争议比较多的领域之一,比如在开源上贡献较多的公司和另一些从开源项目中获取价值较多的公有云厂商在利益上的冲突。您怎么看?这种矛盾可以解决吗?
\\n张晋涛:这个问题由来已久,但也不是不能调和。就目前我看到的情况来说,相比 3 年多之前已经好很多了,多数云厂商也正在积极贡献。无论说是为了争取拿到更多话语权,还是为了解决自己所遇到的问题,在回馈社区。我觉得都是好事儿。只有这样持续的进行正循环,开源软件和社区才能更好的发展。
\\n","description":"近日,来自支流科技的工程师张晋涛通过投票提名成为 Apache APISIX committer,与此同时,张晋涛也被添加为 Kubernetes ingress-nginx 项目的 reviewer,这也是首位来自中国的 Kubernetes Ingress Controller reviewer。 以下是 OSCHINA 对张晋涛的专访:\\n\\n问:请简单介绍下自己吧?\\n\\n张晋涛:我是张晋涛,是一个热爱开源,喜欢折腾的工程师。目前是 Apache APISIX committer, Kubernetes ingress-nginx reviewer 。在…","guid":"https://www.apiseven.com/blog/interview-apache-apisix-committer-jintaozhang","author":"OSCHINA","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-07-07T16:00:00.028Z","media":[{"url":"https://static.apiseven.com/202108/1631245191267-54671967-3bdf-4327-9bb1-09220023bfdc.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"差之毫厘:etcd 3 完美支持 HTTP 访问?","url":"https://www.apiseven.com/blog/etcd3-support-http-access-perfectly","content":"etcd 升级到 3.x 版本后,其对外 API 的协议从普通的 HTTP1 切换到了 gRPC。为了兼顾那些不能使用 gRPC 的特殊群体,etcd 通过 gRPC-gateway 的方式代理 HTTP1 请求,以 gRPC 形式去访问新的 gRPC API。(由于 HTTP1 念起来太过拗口,以下将之简化成 HTTP,正好和 gRPC 能够对应。请不要纠结 gRPC 也是 HTTP 请求的这种问题。)
\\nApache APISIX 开始用 etcd 的时候,用的是 etcd v2 的 API。从 Apache APISIX 2.0 版本起,我们把依赖的 etcd 版本升级到 3.x。由于 Lua 生态圈里面没有 gRPC 库,所以 etcd 对 HTTP 的兼容帮了我们很大的忙,这样就不用花很大心思去补这个短板了。
\\n从去年 10 月发布 Apache APISIX 2.0 版本以来,现在已经过去了 8 个月。在实践过程中,我们也发现了 etcd 的 HTTP API 的一些跟 gRPC API 交互的问题。事实上,拥有 gRPC-gateway 并不意味着能够完美支持 HTTP 访问,这里还是有些细微的差别。
\\n就在几天前,etcd 发布了 v3.5.0 版本。这个版本的发布,了却困扰我们很长时间的一个问题。
\\n跟 HTTP 不同的是,gRPC 默认限制了一次请求可以读取的数据大小。这个限制叫做 “MaxCallRecvMsgSize”,默认是 4MiB。当 Apache APISIX 全量同步 etcd 数据时,假如配置够多,就会触发这一上限,报错 “grpc: received message larger than max”。
\\n神奇的是,如果你用 etcdctl 去访问,这时候却不会有任何问题。这是因为这个限制是可以在跟 gRPC server 建立连接时动态设置的,etcdctl 给这个限制设置了一个很大的整数,相当于去掉了这一限制。
\\n由于不少用户碰到过同样的问题,我们曾经讨论过对策。
\\n一个想法是用增量同步模拟全量同步,这么做有两个弊端:
\\n另一个想法是修改 etcd。既然能够在 etcdctl 里面去除限制,为什么不对 gRPC-gateway 一视同仁呢?同样的改动可以作用在 gRPC-gateway 上。
\\n我们采用了第二种方案,给 etcd 提了个 PR
\\n最新发布的 v3.5.0 版本就包含了我们贡献的这个改动。如果你遇到 “grpc: received message larger than max”,不妨试一下这个版本。这一改动也被 etcd 开发者 backport 到 3.4 分支上了。3.4 分支的下一个发布,也会带上这个改动。
\\n这件事也说明 gRPC-gateway 并非百试百灵。即使用了它,也不能保证 HTTP 访问能够跟 gRPC 访问有一样的体验。
\\nApache APISIX 增加了对 etcd mTLS 的支持后,有用户反馈一直没法完成校验,而用 etcdctl 访问则是成功的。在跟用户交流后,我决定拿他的证书来复现下。
\\n在复现过程中,我注意到 etcd 日志里面有这样的报错:
\\n2021-06-09 11:10:13.022735 I | embed: rejected connection from \\"127.0.0.1:50898\\" (error \\"tls: failed to verify client\'s certificate: x509: certificate specifies an incompatible key usage\\", ServerName \\"\\")\\nWARNING: 2021/06/09 11:10:13 grpc: addrConn.createTransport failed to connect to {127.0.0.1:12379 0 }. Err :connection error: desc = \\"transport: authentication handshake failed: remote error: tls: bad certificate\\". Reconnecting...\\n
\\n“bad certificate” 错误信息,初看像是因为我们发给 etcd 的客户端证书不对。但仔细瞧瞧,会发现这个报错是在 gRPC server 里面报的。
\\ngRPC-gateway 在 etcd 里面起到一个代理的作用,把外面的 HTTP 请求变成 gRPC server 能处理的 gRPC 请求。
\\n大体架构如下:
\\netcdctl ----\x3e gRPC server\\nApache APISIX ---\x3e gRPC-gateway ---\x3e gRPC server\\n
\\n为什么 etcdctl 直连 gRPC server 能通,而中间加一层 gRPC-gateway 就不行?
\\n原来当 etcd 启用了客户端证书校验之后,用 gRPC-gateway 连接 gRPC server 就需要提供一个客户端证书。猜猜这个证书从哪来?
\\netcd 把配置的服务端证书直接作为这里的客户端证书用了。
\\n一个证书既在服务端上提供验证,又在客户端上表明身份,看上去也没什么问题。除非……
\\n除非证书上启用了 server auth 的拓展,但是没有启用 client auth。
\\n对有问题的证书执行openssl x509 -text -noout -in /tmp/bad.crt
会看到这样的输出:
\\nX509v3 extensions:\\nX509v3 Key Usage: critical\\nDigital Signature, Key Encipherment\\nX509v3 Extended Key Usage:\\nTLS Web Server Authentication\\n
\\n注意这里的 “TLS Web Server Authentication”,如果我们把它改成 “TLS Web Server Authentication, TLS Web Client Authentication”,抑或不加这个拓展,就没有问题了。
\\netcd 上也有关于这个问题的 issue
\\n虽然我们在上文列出了几点小问题,但是瑕不掩瑜,etcd 对 HTTP 访问的支持还是一个非常有用的特性。
\\n感谢 Apache APISIX 的用户们,正是因为我们有着广阔的用户群,才能发现 etcd 的这些细节上的问题。我们作为 etcd 的一大用户,在之后的日子里也将一如既往地跟 etcd 的开发者多多交流。
\\n","description":"etcd 升级到 3.x 版本后,其对外 API 的协议从普通的 HTTP1 切换到了 gRPC。为了兼顾那些不能使用 gRPC 的特殊群体,etcd 通过 gRPC-gateway 的方式代理 HTTP1 请求,以 gRPC 形式去访问新的 gRPC API。(由于 HTTP1 念起来太过拗口,以下将之简化成 HTTP,正好和 gRPC 能够对应。请不要纠结 gRPC 也是 HTTP 请求的这种问题。) Apache APISIX 开始用 etcd 的时候,用的是 etcd v2 的 API。从 Apache APISIX 2.0 版本起,我们把依赖的…","guid":"https://www.apiseven.com/blog/etcd3-support-http-access-perfectly","author":"spacewander","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-06-29T16:00:00.992Z","media":[{"url":"https://static.apiseven.com/202108/1639465584634-26435c89-3e1c-4fb9-b094-057fce0f769d.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1639465662863-30bc4fa9-8b7c-47d9-a73e-810bd690a588.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Apache APISIX × Rancher: 极速部署更好用的开源网关和 Ingress Controller","url":"https://www.apiseven.com/blog/deploy-great-open-source-gateway-and-ingress-controller-fast","content":"Rancher 是一个开源的企业级多集群 Kubernetes 管理平台,实现了 Kubernetes 集群在混合云+本地数据中心的集中部署与管理,以确保集群的安全性,加速企业数字化转型。
\\nApache APISIX 是一款开源的高性能、动态云原生网关,由深圳支流科技有限公司于 2019 年捐赠给 Apache 基金会,当前已经成为 Apache 基金会的顶级开源项目,也是 GitHub 上最活跃的开源网关项目。Apache APISIX 当前已经覆盖了 API 网关,LB,Kubernetes Ingress,Service Mesh 等多种场景。
\\n在 Rancher 的 Tools - Catalogs 页面可以应用商店(catalogs)的配置,我们在这里添加 Apache APISIX 的 Helm 仓库。
\\n保存完成后,即可选择 Apps 页面进行 Apache APISIX 的部署了。选择 Launch 便可看到 Apache APISIX 的仓库信息了。这里我们直接选择 apisix 即可。
\\n接下来着只需要在此页面中进行简单的配置即可。 因为我们想要同时部署 APISIX Ingress controller,所以在底部的 Answers 中填入 ingress-controller.enabled=true
这个配置项 。保存即可完成部署。
稍等片刻即可完成部署。
\\n我们使用 kennethreitz/httpbin
作为示例项目进行演示。这里也直接在 Rancher 中完成部署。
我们先演示如何使用 Apache APISIX 作为网关代理 Kubernetes 集群中的服务。
\\nroot@apisix:~$ kubectl -n apisix exec -it `kubectl -n apisix get pods -l app.kubernetes.io/name=apisix -o name` -- bash\\nbash-5.1# curl httpbin.default/get\\n{\\n \\"args\\": {},\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Host\\": \\"httpbin.default\\",\\n \\"User-Agent\\": \\"curl/7.76.1\\"\\n },\\n \\"origin\\": \\"10.244.3.3\\",\\n \\"url\\": \\"http://httpbin.default/get\\"\\n}\\n
\\n可以看到在 Apache APISIX 的 Pod 内可正常访问示例项目。接下来使用 Apache APISIX 对该示例项目进行代理。
\\n这里我们使用 curl
调用 Apache APISIX 的 admin 接口,创建一条路由。将所有 host 头为 httpbin.org
的请求转发给 httpbin.default:80
这个实际的应用服务上。
bash-5.1# curl \\"http://127.0.0.1:9180/apisix/admin/routes/1\\" -H \\"X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\\" -X PUT -d \'\\n{\\n \\"uri\\": \\"/*\\",\\n \\"host\\": \\"httpbin.org\\",\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"httpbin.default:80\\": 1\\n }\\n }\\n}\'\\n{\\"action\\":\\"set\\",\\"node\\":{\\"value\\":{\\"uri\\":\\"\\\\/*\\",\\"create_time\\":1623834078,\\"update_time\\":1623834078,\\"priority\\":0,\\"upstream\\":{\\"type\\":\\"roundrobin\\",\\"hash_on\\":\\"vars\\",\\"pass_host\\":\\"pass\\",\\"nodes\\":{\\"httpbin.default:80\\":1},\\"scheme\\":\\"http\\"},\\"id\\":\\"1\\",\\"status\\":1,\\"host\\":\\"httpbin.org\\"},\\"key\\":\\"\\\\/apisix\\\\/routes\\\\/1\\"}}\\n
\\n你会得到类似上面的输出,接下来验证是否代理成功:
\\nbash-5.1# curl http://127.0.0.1:9080/get -H \\"HOST: httpbin.org\\"\\n{\\n \\"args\\": {},\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Host\\": \\"httpbin.org\\",\\n \\"User-Agent\\": \\"curl/7.76.1\\",\\n \\"X-Forwarded-Host\\": \\"httpbin.org\\"\\n },\\n \\"origin\\": \\"127.0.0.1\\",\\n \\"url\\": \\"http://httpbin.org/get\\"\\n}\\n
\\n得到上面的输出,说明已经通过 Apache APISIX 代理了示例项目的流量。接下来我们试试在集群外通过 Apache APISIX 访问示例项目。
\\nroot@apisix:~$ kubectl -n apisix get svc -l app.kubernetes.io/name=apisix\\nNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\\napisix-admin ClusterIP 10.96.142.88 <none> 9180/TCP 51m\\napisix-gateway NodePort 10.96.158.192 <none> 80:32763/TCP 51m\\n
\\n在使用 Helm chart 部署的时候,默认会将 Apache APISIX 的端口通过 NodePort 的形式暴露出去。我们使用 Node IP + NodePort 的端口进行访问测试。
\\nroot@apisix:~$ curl http://172.18.0.2:32763/get -H \\"HOST: httpbin.org\\"\\n{\\n \\"args\\": {},\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Host\\": \\"httpbin.org\\",\\n \\"User-Agent\\": \\"curl/7.58.0\\",\\n \\"X-Forwarded-Host\\": \\"httpbin.org\\"\\n },\\n \\"origin\\": \\"10.244.3.1\\",\\n \\"url\\": \\"http://httpbin.org/get\\"\\n}\\n
\\n可以看到,在集群外已经可以通过 Apache APISIX 作为网关代理 Kubernetes 集群内的服务了。
\\n我们可以直接在 Rancher 中添加 Ingress ,Apache APISIX Ingress controller 会自动将路由规则同步至 Apache APISIX 中,完成服务的代理。
\\n注意右下角, 我们添加了 kubernetes.io/ingress.class: apisix
的 annotation 配置,用于支持集群内多 ingress-controller 的场景。
保存后,可看到如下界面:
\\n在终端下测试是否代理成功:
\\nroot@apisix:~$ curl http://172.18.0.2:32763/get -H \\"HOST: httpbin-ing.org\\"\\n{\\n \\"args\\": {},\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Host\\": \\"httpbin-ing.org\\",\\n \\"User-Agent\\": \\"curl/7.58.0\\",\\n \\"X-Forwarded-Host\\": \\"httpbin-ing.org\\"\\n },\\n \\"origin\\": \\"10.244.3.1\\",\\n \\"url\\": \\"http://httpbin-ing.org/get\\"\\n}\\n
\\n可以看到也正常代理了。
\\n除了以上方式外,Apache APISIX Ingress controller 通过 CRD 的方式对 Kubernetes 进行了扩展,你也可以通过发布 ApisixRoute
等这种自定义资源来完成 Kubernetes 中服务的对外暴露。
你可以在 Rancher 中使用 Apache APISIX 的官方 Helm 仓库直接部署 Apache APISIX 和 APISIX Ingress controller 。并且 Apache APISIX 可通过作为网关,或者 APISIX Ingress controller 的数据面来承载业务流量。
\\nApache APISIX 已经与 Rancher 社区达成合作,未来你可以直接在 Rancher 自带的应用仓库中找到 Apache APISIX ,不再需要手动添加 Helm 仓库了。
\\n","description":"Rancher 介绍 Rancher 是一个开源的企业级多集群 Kubernetes 管理平台,实现了 Kubernetes 集群在混合云+本地数据中心的集中部署与管理,以确保集群的安全性,加速企业数字化转型。\\n\\nApache APISIX 介绍\\n\\nApache APISIX 是一款开源的高性能、动态云原生网关,由深圳支流科技有限公司于 2019 年捐赠给 Apache 基金会,当前已经成为 Apache 基金会的顶级开源项目,也是 GitHub 上最活跃的开源网关项目。Apache APISIX 当前已经覆盖了 API 网关,LB,Kubernetes…","guid":"https://www.apiseven.com/blog/deploy-great-open-source-gateway-and-ingress-controller-fast","author":"Jintao Zhang","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-06-23T16:00:00.769Z","media":[{"url":"https://static.apiseven.com/202108/1630113667126-2ddff7a7-4f0f-4596-bbf9-fef381c1134b.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630113736719-fe1e7065-f4e3-4921-b0ab-781a85d1f7e7.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630113793613-e1a7b6af-4d6e-4435-88c7-f7a116dec11b.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630113851464-0698e370-3073-4af4-8400-b9c2e81e5bde.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630113893968-c54842fd-354e-4210-b7bc-2a139f6e03b4.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630113957198-fa73dee2-52b8-4840-9bbc-b1bbc2c620eb.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630114006945-ae48d3d2-b706-4353-b5d9-f372727faade.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630114069907-3de3d9d0-be9b-4b78-ad9f-1553480057be.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"使用 Java 编写 Apache APISIX 插件","url":"https://www.apiseven.com/blog/use-java-to-write-apache-apisix-plugins","content":"Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有视频教程。
\\n在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java 和 Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
\\n开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
\\n现在 Apache APISIX 支持多语言开发插件,更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
\\n上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
\\n当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
\\n如果你为一个给定的路由配置了 ext-plugin-* 插件,命中该路由的请求将触发 Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
\\n根据需要配置 plugin runner 的执行时机。
\\nplugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
\\n多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
\\n首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 构建 Apache APISIX,以及 Java 项目的开发环境,参考 构建 apisix-java-plugin-runner。
\\n注意:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
\\n这里是指让 Apache APISIX 以调试的方式运行外部插件,在 config.yaml
中增加以下配置
ext-plugin:\\n path_for_test: /tmp/runner.sock\\n
\\n这个配置的意思是,Apache APISIX 相当于 client 端,会监听位于 /tmp/runner.sock
位置上的 Unxi Domain Socket 链接。
在启动 Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)
之前,需要配置用户级的环境变量 APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock
和 APISIX_CONF_EXPIRE_TIME=3600
。
如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
\\napisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 /tmp/runner.sock
文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
\\n先给插件命名为 TokenValidator
,然后设计属性,为了尽可能做到动态配置,属性设计如下
{\\n \\"validate_header\\": \\"token\\",\\n \\"validate_url\\": \\"https://www.sso.foo.com/token/validate\\",\\n \\"rejected_code\\": \\"403\\"\\n}\\n
\\n启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 TokenValidator
插件,示例如下
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H \'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1\' -X PUT -d \'\\n{\\n \\"uri\\":\\"/get\\",\\n \\"plugins\\":{\\n \\"ext-plugin-pre-req\\":{\\n \\"conf\\":[\\n {\\n \\"name\\":\\"TokenValidator\\",\\n \\"value\\":\\"{\\\\\\"validate_header\\\\\\":\\\\\\"token\\\\\\",\\\\\\"validate_url\\\\\\":\\\\\\"https://www.sso.foo.com/token/validate\\\\\\",\\\\\\"rejected_code\\\\\\":\\\\\\"403\\\\\\"}\\"\\n }\\n ]\\n }\\n },\\n \\"upstream\\":{\\n \\"nodes\\":{\\n \\"httpbin.org:80\\":1\\n },\\n \\"type\\":\\"roundrobin\\"\\n }\\n}\\n
\\n需要注意的是,TokenValidator
的属性需要经过 json 转义,作为 string 类型进行配置。
(这里上游地址配置为 httpbin.org,方便调试)
\\n在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 TokenValidatr.java
,代码初始骨架如下
package org.apache.apisix.plugin.runner.filter;\\n\\nimport org.apache.apisix.plugin.runner.HttpRequest;\\nimport org.apache.apisix.plugin.runner.HttpResponse;\\nimport org.springframework.stereotype.Component;\\nimport reactor.core.publisher.Mono;\\n\\n\\n@Component\\npublic class TokenValidator implements PluginFilter {\\n\\n @Override\\n public String name() {\\n return \\"TokenValidator\\";\\n }\\n\\n @Override\\n public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {\\n return chain.filter(request, response);\\n }\\n}\\n
\\n需要继承 PluginFilter
接口,重写 name
和 filter
函数。
重写 name
的返回值,和前面配置 APISIX 的路由属性中 \\"name\\" 保持一致。
完整代码如下:
\\npackage org.apache.apisix.plugin.runner.filter;\\n\\nimport com.google.gson.Gson;\\nimport org.apache.apisix.plugin.runner.HttpRequest;\\nimport org.apache.apisix.plugin.runner.HttpResponse;\\nimport org.springframework.stereotype.Component;\\nimport reactor.core.publisher.Mono;\\n\\nimport java.util.HashMap;\\nimport java.util.Map;\\n\\n@Component\\npublic class TokenValidator implements PluginFilter {\\n\\n @Override\\n public String name() {\\n return \\"TokenValidator\\";\\n }\\n\\n @Override\\n public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {\\n // parse `conf` to json\\n String configStr = request.getConfig(this);\\n Gson gson = new Gson();\\n Map<String, Object> conf = new HashMap<>();\\n conf = gson.fromJson(configStr, conf.getClass());\\n\\n // get configuration parameters\\n String token = request.getHeader((String) conf.get(\\"validate_header\\"));\\n String validate_url = (String) conf.get(\\"validate_url\\");\\n boolean flag = validate(token, validate_url);\\n\\n // token verification results\\n if (!flag) {\\n String rejected_code = (String) conf.get(\\"rejected_code\\");\\n response.setStatusCode(Integer.parseInt(rejected_code));\\n return chain.filter(request, response);\\n }\\n\\n return chain.filter(request, response);\\n }\\n\\n private Boolean validate(String token, String validate_url) {\\n //TODO: improve the validation process\\n return true;\\n }\\n}\\n
\\n在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
\\ncurl -H \'token: 123456\' 127.0.0.1:9080/get\\n{\\n \\"args\\": {},\\n \\"headers\\": {\\n \\"Accept\\": \\"/\\",\\n \\"Host\\": \\"127.0.0.1\\",\\n \\"Token\\": \\"123456\\",\\n \\"User-Agent\\": \\"curl/7.71.1\\",\\n \\"X-Amzn-Trace-Id\\": \\"Root=1-60cb0424-02b5bf804cfeab5252392f96\\",\\n \\"X-Forwarded-Host\\": \\"127.0.0.1\\"\\n },\\n \\"origin\\": \\"127.0.0.1\\",\\n \\"url\\": \\"http://127.0.0.1/get\\"\\n}\\n
\\n插件开发完成后,部署操作可以参考 部署 apisix-java-plugin-runner。
\\nApache APISIX 是 Apache 基金会下的顶级项目,目前在生产环境中已经通过每日几百亿次请求量的考验。随着社区的发展,Apache APISIX 的功能越来越多,需要与外部组件产生的交互也越来越多,随之而来的不确定性呈指数级增长。在社区中,我们也收到了用户反馈的一些问题,这里举两个例子。
\\n在 Apache APISIX 的配置中心, etcd 与 Apache APISIX 之间出现意外的高网络延迟时,Apache APISIX 能否仍然正常运行进行流量过滤转发?
\\n用户在 issue 反馈,当 etcd 集群中的一个节点失效而集群仍然可以正常运行时,会出现与 Apache APISIX admin API 交互报错的情况。
\\n尽管 Apache APISIX 在 CI 中通过单元 / e2e / fuzz 测试覆盖了大部分情景,然而尚未覆盖到与外部组件的交互。当发生网络波动、硬盘故障、或是进程被杀掉等难以预料的异常行为时,Apache APISIX 能否给出合适的错误信息、是否可以保持或自行恢复到正常的运行状态呢?为了测试覆盖到用户提出的场景,以及在投入生产环境前主动发现类似的问题,经过社区讨论决定使用 PingCAP 开源的混沌工程平台 Chaos Mesh 进行测试。
\\n混沌工程是一种在系统基础设施上进行试验,主动找出系统中的脆弱环节的方法,从而确保系统具有抵御生产环境中失控环境的能力。混沌工程最早由 Netflix 提出,用以模拟从而抵御早期云服务的不稳定性。随着技术的演进,现在的混沌工程平台提供了更多种类的故障可供注入,依靠 Kubernetes 也可以更方便地控制故障半径。这些都是 Apache APISIX 选择 Chaos Mesh 的重要原因,但作为开源社区,Apache APISIX 深知只有活跃的社区才能确保软件稳定使用和快速迭代,而这也是 Chaos Mesh 更加吸引人的特点。
\\n混沌工程在单纯的注入故障以外,逐渐形成了一套完整的方法论。根据 Principle of Chaos Engineering 的推荐,部署混沌工程实验需要五个步骤:
\\n接下来以上述两个用户反馈场景为例,依照这五个步骤为大家介绍 Apache APISIX 应用混沌工程的流程。
\\n用一幅图来描述这个场景。对照上面的五个步骤,首先需要找到衡量 Apache APISIX 正常运行的可量化指标。在测试时最主要的方法是利用 Grafana 对 Apache APISIX 运行指标进行监测,找到可衡量的指标后,在 CI 中就可以从 Prometheus 中单独提取数据进行比较判断,这里使用了路由转发的 Request per Second(RPS)和 etcd 的可连接性 作为评价指标。另一点就是需要对日志进行分析,对于 Apache APISIX 就是查看 Nginx 的 error.log 判断是否有报错以及报错是否符合预期。
\\n在对照组也就是引入 Chaos 前进行实验,检测 set/get route 均能成功,etcd 可连接,并记录此时的 RPS。之后,使用 network chaos 添加 5s 的网络延迟 ,再次进行实验,此时 set route 失败,get route 成功,etcd 无法连接,RPS 与之前相比无明显变化。实验符合预期。
\\n进行同样的对照组实验之后引入 pod-kill chaos,复现了预期的错误。在随机删除集群中少数 etcd 节点的情况下,etcd 可连接性表现出时有时无,日志则打印出了大量连接拒绝的报错。更加有趣的是,在删除 etcd 端点列表的第一个或第三个节点时,设置路由正常返回,而只有在删除 etcd 端点列表中的第二个节点时,设置路由会报错 “connection refused”。
\\n排查发现原因在于 Apache APISIX 使用的 etcd lua API 选择端点时并不是随机而是顺序选择,因此新建 etcd client 进行的操作就相当于只绑定在一个 etcd 端点上导致持续性的失败。修复这个问题之后,还为 etcd lua API 添加了健康检查,确保不会在断开连接的 etcd 上进行大量的重复;以及增加了 etcd 集群完全断开连接时的回退检查,避免大量报错。
\\n目前在 Apache APISIX 中,仍然主要依靠人来识别系统中可能的脆弱点进行测试修复。对于开源社区来说,与之前提到的 Netflix 在企业中应用混沌工程不同,尽管在 CI 中测试,无需担心混沌工程的故障半径对生产环境的影响,但同时也无法覆盖生产环境中的复杂而全面的场景。
\\n为了覆盖更多的场景,未来社区计划利用现有的 e2e 测试模拟更加完整的场景,进行更大范围、更强随机性的混沌测试。
\\n除了为 Apache APISIX 找到更多可能的脆弱点之外,社区还计划为 Apache APISIX Dashboard 和 Apache APISIX Ingress Controller 等更多项目添加混沌测试。
\\n在部署 Chaos Mesh 时遇见一些暂不支持的功能,包括网络延迟的目标不支持选择 service,网络混沌无法指定容器端口注入等,Apache APISIX 社区未来也会协助 Chaos Mesh 添加相关功能。希望开源社区都会越来越好。
\\n","description":"Apache APISIX 是 Apache 基金会下的顶级项目,目前在生产环境中已经通过每日几百亿次请求量的考验。随着社区的发展,Apache APISIX 的功能越来越多,需要与外部组件产生的交互也越来越多,随之而来的不确定性呈指数级增长。在社区中,我们也收到了用户反馈的一些问题,这里举两个例子。 问题场景\\n场景一\\n\\n在 Apache APISIX 的配置中心, etcd 与 Apache APISIX 之间出现意外的高网络延迟时,Apache APISIX 能否仍然正常运行进行流量过滤转发?\\n\\n场景二\\n\\n用户在 issue 反馈,当 etcd…","guid":"https://www.apiseven.com/blog/chaos-mesh-helps-apache-apisix-improve-stability","author":"Yiyiyimu","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-06-15T16:00:00.043Z","media":[{"url":"https://static.apiseven.com/202108/1630115370517-7863c3ec-0e9d-4486-a4e8-dc17017bc6a7.png","type":"photo"},{"url":"https://static.apiseven.com/202108/1630115436031-885e3edc-c03b-4c68-beed-d9e170cf78d8.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Apache APISIX 和 Envoy 性能大比拼","url":"https://www.apiseven.com/blog/apache-apisix-and-envoy-performance-comparison","content":"在 CNCF 组织的一场技术分享会上,第一次听到了 Envoy 这么一个东西,分享的嘉宾巴拉巴拉讲了一大堆,啥都没记住,就记住了一个特别新颖的概念“通信总线”,后面 google 了下 Envoy 这个东西到底是什么,发现官网上如是描述:
\\n“Envoy 是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通信总线”
\\n也就是说, Envoy 是为了解决 Server Mesh 领域而诞生一款 L7 代理软件,这里我网上找了一张图,我理解的 Envoy 大概是如下的部署架构。(如果错了请大佬指教)
\\n既然是 L7 的代理软件嘛,作为常年混迹 OpenResty 社区的老司机,自然忍不住把它拿来搞一搞,对比对比。
\\n我们选择的比试对象是 Apache APISIX,它是基于 OpenResty 实现的 API 网关。(其实也就是 L7 代理然后加了路由、认证,限流、动态上游等等之类的功能)
\\n为什么选择它呢,因为有一次社区分享的时候听说这货的路由实现非常棒,正好我们的现在业务的路由系统乱七八糟,扒拉了下 APISIX 的源码,发现确实是 6 到飞起,吊打我看到过的同类产品, 所以印象深刻,就它了!
\\n这里附上一张在 APISIX 官网扒拉的图,真是一图胜千言,一看就知道这玩意儿是怎么工作的。
\\n开搞吧,首先我们去官网找到两个产品的最版本:
\\nApache APISIX 1.5 和 Envoy 1.14
\\n(笔者在写这篇文章时的最新版)
\\n这里我们用 NGINX 搭建了一个上游服务器,配置 2 个 worker,接收到请求直接应答 4k 内容,参考配置如下:
\\nserver {\\n listen 1980;\\n\\n access_log off;\\n location = /hello {\\n echo_duplicate 400 \\"1234567890\\";\\n }\\n}\\n
\\n首先我们找到 APISIX 的入门配置指南,我们添加一条到 /hello 的路由,配置如下:
\\ncurl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d \'{、\\n \\"uri\\": \\"/hello\\",\\n \\"upstream\\": {\\n \\"type\\": \\"roundrobin\\",\\n \\"nodes\\": {\\n \\"127.0.0.1:1980\\": 1\\n }\\n }}\'\\n
\\n需要注意的是,这里没并没有开始 proxy_cache 和 proxy_mirror 插件,因为 Enovy 并没有类似的功能;
\\n然后我们参考 Envoy 官方压测指导 为 Envoy 添加一条路由:
\\nstatic_resources:\\n listeners:\\n - name: listener_0\\n address:\\n socket_address: { address: \\"0.0.0.0\\", port_value: 10000 }\\n\\n filter_chains:\\n - filters:\\n - name: envoy.http_connection_manager\\n config:\\n generate_request_id: false,\\n stat_prefix: ingress_http\\n route_config:\\n name: local_route\\n virtual_hosts:\\n - name: local_service\\n domains: [\\"*\\"]\\n routes:\\n - match: { prefix: \\"/hello\\" }\\n route: { cluster: service_test }\\n http_filters:\\n - name: envoy.router\\n config:\\n dynamic_stats: false\\n clusters:\\n - name: service_test\\n connect_timeout: 0.25s\\n type: LOGICAL_DNS\\n dns_lookup_family: V4_ONLY\\n lb_policy: ROUND_ROBIN\\n hosts: [{ socket_address: { address: \\"127.0.0.1\\", port_value: 1980 }}]\\n circuit_breakers:\\n thresholds:\\n - priority: DEFAULT\\n max_connections: 1000000000\\n max_pending_requests: 1000000000\\n max_requests: 1000000000\\n max_retries: 1000000000\\n - priority: HIGH\\n max_connections: 1000000000\\n max_pending_requests: 1000000000\\n max_requests: 1000000000\\n max_retries: 1000000000\\n
\\n上面的 generaterequest_id、dynamic_stats 和 circuit_breakers 部分,在 Envoy 内部是默认开启,但本次压测用不到,需要显式关闭或设置超大阈值从而提升性能。(谁能给我解释下为什么这玩意儿配置这么复杂 --!)
\\n单条路由,不开启任何插件。开启不同 CPU 数量,进行满载压力测试。说明:对于 NGINX 叫 worker 数量,Envoy 是 concurrent ,为了统一后面都叫 worker 数量。
\\n进程数 | \\nAPISIX QPS | \\nAPISIX Latency | \\nEnvoy QPS | \\nEnvoy Latency | \\n
---|---|---|---|---|
1 worker | \\n18608.4 | \\n0.96 | \\n15625.56 | \\n1.02 | \\n
2 workers | \\n34975.8 | \\n1.01 | \\n29058.135 | \\n1.09 | \\n
3 workers | \\n52334.8 | \\n1.02 | \\n42561.125 | \\n1.12 | \\n
注:原始数据公开在 gist 预览。(https://gist.github.com/aifeiasdf/9fc4585f6404e3a0a70c568c2a14b9c9)
\\nQPS:每秒钟完成的请求数,数量越多越好,数值越大代表单位时间内可以完成的请求数量越多。从 QPS 结果看,APISIX 性能是 Envoy 的 120% 左右,核心数越多 QPS 差距越大。
\\nLatency:每请求的延迟时间,数值越小越好。它代表每请求从发出后需要经过多长时间可以接收到应答。对于反向代理场景,该数值越小,对请求的影响也就最小。从结果上看,Envoy 的每请求延迟要比 APISIX 多 6-10% ,核心数量越多延迟越大。
\\n可以看到两者在单工作线程|进程的模式下,QPS 和 Latency 两个指标差距不大,但是随着工作线程|进程的增加他们的差距逐渐放大,这里我分析可能有以下两方面的原因,NGINX 在高并发场景下用多 worker 和系统的 IO 模型进行交互是不是会更有优势,另外一方面,也可能是 NGINX 自身在实现上面对内存和 CPU 的使用比较“抠门”,这样累积起来的性能优势,以后详细评估评估。
\\n总体来说 APISIX 在响应延迟和 QPS 层面都略优于 Envoy, 由于 NGINX 的多 worker 的协作方式在高并发场景下更有优势,得益于此,APISIX 在开启多个 worker 进程后性能提升较 Enovy 更为明显;但是两者并不冲突, Envoy 的总线设计使它在处理东西向流量上有独特的优势, APISIX 在性能和延迟上的表现使它在处理南北向流量上具有海量的吞吐能力,根据自己的业务场景来选择合理的组件配合插件构建自己的服务才是正解。
\\n","description":"在 CNCF 组织的一场技术分享会上,第一次听到了 Envoy 这么一个东西,分享的嘉宾巴拉巴拉讲了一大堆,啥都没记住,就记住了一个特别新颖的概念“通信总线”,后面 google 了下 Envoy 这个东西到底是什么,发现官网上如是描述: “Envoy 是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通信总线”\\n\\n也就是说, Envoy 是为了解决 Server Mesh 领域而诞生一款 L7 代理软件,这里我网上找了一张图,我理解的 Envoy 大概是如下的部署架构。(如果错了请大佬指教)\\n\\n既然是 L7 的代理软件嘛,作为常年混迹…","guid":"https://www.apiseven.com/blog/apache-apisix-and-envoy-performance-comparison","author":"王院生","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-06-09T16:00:00.049Z","media":[{"url":"https://static.apiseven.com/202108/20210617001.png","type":"photo"},{"url":"https://static.apiseven.com/202108/20210617002.png","type":"photo"},{"url":"https://static.apiseven.com/202108/20210617003.png","type":"photo"},{"url":"https://static.apiseven.com/202108/20210617004.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"GigaOm 发布 API 网关评测报告:API7 和 Kong 企业版本性能对比","url":"https://www.apiseven.com/blog/api7-and-kong-enterprise-performance-comparison","content":"近期,GigaOm 发布了一份 API 网关的性能评测报告,报告主要介绍了在不同压测场景下, API7(基于 Apache 顶级项目 APISIX 的企业版本) 和 Kong EE(Kong 企业版本) 二者的性能差异,结果显示 API7 性能明显优于 Kong EE,最高有数百倍的差距。
\\n我们从完整的报告中摘录了测试场景和数据:
\\n下面图表中,横坐标表示请求的分布百分比,纵坐标表示延迟的毫秒数。所以,延迟越低越好,越稳定越好。这表示网关可以稳定、高效的处理终端请求。
\\n下图是在不启用任何插件的情况下,APISIX 和 Kong 企业版的延迟对比。对于 95% 请求而言差异很小,但在 95% 之后延迟差异随后呈指数级增长,在达到 99.99 % 时,Kong EE 的延迟是 API7 的 30 多倍。
\\n横坐标表示请求的分布百分比,纵坐标表示延迟的毫秒数,数值越小说明性能越好。
\\n在启用了 JWT 插件后,API7 和 Kong EE 的性能差距进一步拉大:Kong EE 的最大延迟到了 3778 毫秒,处于不可用状态,而同时 API7 的最大延迟仅有 14 毫秒,两者是数百倍的差距。
\\n横坐标表示请求的分布百分比,纵坐标表示延迟的毫秒数,数值越小说明性能越好。
\\n上面两个场景都只有 1 条路由,在用户的实际生产环境,一般会有几百上千条路由。所以,下面的测试覆盖了 1000 条路由的情况。**在这个场景下,Kong EE 和 API7 也是接近 100 倍的差距。**\\n横坐标表示请求的分布百分比,纵坐标表示延迟的毫秒数,数值越小说明性能越好。
\\nAPI7 在各种测试场景下,都保持了低延迟和稳定,这对于企业用户尤为关键。
\\nApache APISIX 是新一代的云原生 API 网关,提供丰富的流量管理功能,如负载均衡、动态上游、灰度发布、服务熔断、身份验证、可观测性等。
\\nAPI7 是深圳支流科技基于 Apache APISIX 实现的商业产品,除了包括上面提到基础功能外,还针对企业用户实现了多集群管理、多工作分区、权限管理、版本管理、审计、统计等功能。
\\n","description":"近期,GigaOm 发布了一份 API 网关的性能评测报告,报告主要介绍了在不同压测场景下, API7(基于 Apache 顶级项目 APISIX 的企业版本) 和 Kong EE(Kong 企业版本) 二者的性能差异,结果显示 API7 性能明显优于 Kong EE,最高有数百倍的差距。 我们从完整的报告中摘录了测试场景和数据:\\n\\n1 万 rps 的压测,1 条路由,不启用插件\\n1 万 rps 的压测,1 条路由,启用 JWT 插件\\n1 万 rps 的压测,1000 条路由\\n\\n下面图表中,横坐标表示请求的分布百分比,纵坐标表示延迟的毫秒数。所以…","guid":"https://www.apiseven.com/blog/api7-and-kong-enterprise-performance-comparison","author":"赵若妃","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-05-31T16:00:00.666Z","media":[{"url":"https://static.apiseven.com/202108/da52e6a2b6674d7b812ba1a21b5dd516~tplv-k3u1fbpfcp-watermark.image","type":"photo"},{"url":"https://static.apiseven.com/202108/GigaOm-1.png","type":"photo"},{"url":"https://static.apiseven.com/202108/GigaOm-2.png","type":"photo"},{"url":"https://static.apiseven.com/202108/GigaOm-3.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"基于 Apache APISIX 实现的服务网格项目正式开源","url":"https://www.apiseven.com/blog/apisix-mesh-agent-release","content":"基于 Apache APISIX 开发的服务网格项目正式开源!欢迎大家下载使用。
\\n服务网格(Service Mesh),作为服务间通信的中间层,将诸如服务发现、负载均衡、熔断、限流、重试等的基础功能,下沉到一个轻量级的边车(Sidecar)组件,使得应用程序开发者可以更聚焦于应用本身的开发,不需要关注这类基础功能,从而提升开发效率。
\\nA 公司微服务的技术栈涉及 Go、Java 和 C++ 等不同语言,同时为每种开发语言设计了基础框架,以完成服务治理的功能,然而每次框架的更新都需要覆盖各语言的版本以及联系所有业务开发团队进行更新。并且不同语言的框架由不同团队维护,导致沟通成本高昂且容易出现不兼容情况。
\\n因而 A 公司的架构师决定引入服务网格方案,将所有服务治理的能力下沉到网格,基础功能迭代不再与业务开发耦合,同时业务开发不再依赖开发框架,业务本身更加简洁。
\\nB 公司现有的服务治理框架功能落后,年久失修,因业务发展及合规性等原因,现在需要实现协议转换和双向认证,技术负责人调研以后决定引入服务网格方案,借助网格的能力实现这些功能,同时摆脱现有服务治理框架的历史债,使得所有应用变得更加稳定和轻量。
\\n鉴于 Apache APISIX 的优秀设计,我们不仅可以将 Apache APISIX 用于南北向流量管理,也可以用它管理服务网格的东西向流量,我们通过引入 APISIX-Mesh-Agent 这一组件,配合 Apache APISIX 进行使用,从而使得 Apache APISIX 可以对接业内广泛使用的服务网格控制面,例如: Istio 和 Kuma 等。
\\nAPISIX-Mesh-Agent 作为 Apache APISIX 的协议适配器,实现了 Envoy xDS 协议,将数据从 xDS 格式转换为 Apache APISIX 兼容的格式。
\\n同时其实现了 ETCD V3 API 使得在 Apache APISIX 看来,它就是一个 ETCD 集群,由于 Apache APISIX 对 ETCD 的原生支持, 配置即可顺利地从某个服务网格控制面下发到 Apache APISIX 。
\\n得益于 Apache APISIX 的良好设计,基于 Apache APISIX 的服务网格方案性能更佳、资源占用更少、二次开发和定制的成本更低(Lua 语言上手容易,且 Apache APISIX 已经支持使用多语言进行插件开发),并且由于兼容 xDS 协议,从 Istio、Kuma 等网格方案进行迁移也更加平滑。
\\n下载 APISIX-Mesh-Agent 0.6-Release 源代码及二进制安装包,请访问下载页面。\\nhttps://github.com/api7/apisix-mesh-agent/releases/tag/0.6
在本次发布过程中,我们也在持续更新和发布新的使用文档,欢迎大家提出宝贵的意见。\\nhttps://github.com/api7/apisix-mesh-agent/tree/main/docs
流量切分(traffic split)是指将流量按照定义好的规则和比例分摊到多个后端服务,像常见的 API 网关产品(例如 Apache APISIX,Traefik)、服务网格 Sidecar Proxy(例如 Envoy,linkerd2-proxy),都提供了流量切分的功能,以此来实现细粒度的 金丝雀发布,蓝绿部署 等功能。
\\n作为 Kubernetes 集群流量入口,Ingress Controller 自然也需要支持流量切分的功能,在后端应用需要发布时,能够提供逐步切流,回滚的能力,降低应用发布带来的风险。本文先后介绍了 Ingress Nginx 和 Kong Ingress Controller 中提供的流量切分功能(有时也称为金丝雀发布),之后介绍了流量切分在 Apache APISIX Ingress Controller 中的实现。
\\n(注:为了描述方便,下文用术语 “灰度应用” 表示命中金丝雀发布规则后对应的后端应用和术语“稳定应用”表示金丝雀发布规则未命中时对应的后端应用。例如,在下图中,灰度应用是 “foo-canary”,稳定应用是 “foo”。)
\\nIngress Nginx 提供了金丝雀发布的功能,我们可以为 Ingress 资源添加 nginx.ingress.kubernetes.io/canary: “true” 注解来启用该功能,Ingress Nginx 支持使用以下几个注解来自定义金丝雀发布的规则。
\\n通过某个请求头的值来判断流量应该被转发到灰度应用(值为 always)还是稳定应用(值为 never)。
\\n该注解扩展了 nginx.ingress.kubernetes.io/canary-by-header,通过判断指定请求头的值是否与该注解的值匹配,来决定流量的去向(匹配则转发到灰度应用,否则转发到稳定应用)。
\\n该注解和 nginx.ingress.kubernetes.io/canary-by-header 类似,只是匹配采用了 PCRE 兼容的正则表达式。
\\n通过 Cookie 中某个字段的值来判断流量应该被转发到灰度应用(值为 always)还是稳定应用(值为 never)。
\\n为灰度应用设定一个大小位于 [0, 100] 的权重,流量将按照权重在灰度应用和稳定应用之间分配。权重为 0 则所有流量都会被转发到稳定应用;权重为 100 则所有流量都会被转发到灰度应用。
\\n下图的例子将携带 User-Agent 头部匹配 “.Mozilla.” 模版,URI path 前缀为 /get 的请求转发到灰度应用 foo-canary。
\\napiVersion: networking.k8s.io/v1beta1\\nkind: Ingress\\nmetadata:\\n annotations:\\n kubernetes.io/ingress.class: nginx\\n nginx.ingress.kubernetes.io/canary: \\"true\\"\\n nginx.ingress.kubernetes.io/canary-by-header: \\"User-Agent\\"\\n nginx.ingress.kubernetes.io/canary-by-header-pattern:\\n\\".*Mozilla.*\\"\\n name: ingress-v1beta1\\n
\\nKong 提供了金丝雀发布的插件,并且通过 KongPlugin 这个 CRD 资源将该功能暴露到了 Kong Ingress Controller 中。管理员/用户首先需要创建一个 KongPlugin 对象,填入金丝雀发布的规则,然后在目标 Kubernetes Service 中加入注解 konghq.com/plugins 并赋予该对象的名称;亦或是创建一个 KongClusterPlugin 对象,进而使得该插件在集群内生效。
\\napiVersion: configuration.konghq.com/v1\\nkind: KongPlugin\\nmetadata:\\n name: foo-canary\\nconfig:\\n percentage: 30\\n upstream_host: foo.com\\n upstream_fallback: false\\n upstream_port: 80\\nplugin: canary\\n---\\napiVersion: v1\\nkind: Service\\nmetadata:\\n name: foo-canary\\n labels:\\n app: foo\\n annotations:\\n konghq.com/plugins: foo-canary\\nspec:\\n ports:\\n - port: 80\\n targetPort: 80\\n protocol: TCP\\n name: http\\n selector:\\n app: foo\\n canary: true\\n
\\n上述例子将 foo-canary 这个服务标记为灰度应用,并为其建立了一条金丝雀发布规则,要求 30% 的流量转发到该应用。
\\nApache APISIX 提供的 traffic-split 插件支持配置自定义规则进行流量切分。Apache APISIX Ingress Controller 在此基础之上,结合 ApisixRoute 灵活的路由规则配置,将流量切分实现为了 ApisixRoute 中的第一类功能(无须通过注解定义)。
\\n基于权重的流量切分可以通过为单条路由规则配置多个 Kubernetes Service 后端来实现,如:
\\napiVersion: apisix.apache.org/v2alpha1\\nkind: ApisixRoute\\nmetadata:\\n name: foo-route\\nspec:\\n http:\\n - name: rule1\\n match:\\n hosts:\\n - foo.org\\n paths:\\n - /get*\\n backends:\\n - serviceName: foo-canary\\n servicePort: 80\\n weight: 10\\n - serviceName: foo\\n servicePort: 80\\n weight: 5\\n
\\n上述示例将 ⅔ 的满足 Host 为 foo.org,URI path 前缀为 /get 的请求转发到了 foo-canary 这个 service,剩下 ⅓ 的请求将被路由到 foo。
\\n在实际应用中,可以为灰度应用设定较小的权重,进行小规模的验证,确认没有问题后修改 ApisixRoute 资源,逐步放大其权重,最终将流量全部转发到该灰度应用,完成发布。
\\nApisixRoute 资源允许用户添加路由匹配表达式 - Exprs 字段,来自定义路由匹配;此外,单个 ApisixRoute 资源允许插入多条路由规则,因此基于规则的流量切分被 Apache APISIX Ingress Controller 以一种无缝的方式集成。
\\napiVersion: apisix.apache.org/v2alpha1\\nkind: ApisixRoute\\nmetadata:\\n name: foo-route\\nspec:\\n http:\\n - name: rule1\\n priority: 1\\n match:\\n hosts:\\n - foo.org\\n paths:\\n - /get*\\n backends:\\n - serviceName: foo\\n servicePort: 80\\n - name: rule2\\n priority: 2\\n match:\\n hosts:\\n - foo.org\\n paths:\\n - /get*\\n exprs:\\n - subject:\\n scope: Query\\n name: id\\n op: In\\n set:\\n - \\"3\\"\\n - \\"13\\"\\n - \\"23\\"\\n - \\"33\\"\\n backends:\\n - serviceName: foo-canary\\n servicePort: 80\\n
\\n上述示例,将满足 Host 为 foo.org,URI path 前缀为 /get 的请求,分为两部分:
\\nid 参数是 3、13、23、33 其中之一,这部分请求将命中路由规则 rule2,从而被转发到 foo-canary 这一服务;
\\n其他请求将命中路由规则 rule1,从而被转发到 foo 这一服务。
\\nIngress Nginx 支持基于权重和基于 Header 规则的金丝雀发布,但是需要通过 annotations 的方式进行配置,语义不强;而 Kong 的方案仅支持基于权重进行金丝雀发布,某些场景下无法满足使用需求,且需要多处配置;Apache APISIX Ingress Controller 则较好地同时支持了两种使用场景,并且其提供的路由规则灵活多变,配置简单且易于理解。
\\n","description":"流量切分(traffic split)是指将流量按照定义好的规则和比例分摊到多个后端服务,像常见的 API 网关产品(例如 Apache APISIX,Traefik)、服务网格 Sidecar Proxy(例如 Envoy,linkerd2-proxy),都提供了流量切分的功能,以此来实现细粒度的 金丝雀发布,蓝绿部署 等功能。 作为 Kubernetes 集群流量入口,Ingress Controller 自然也需要支持流量切分的功能,在后端应用需要发布时,能够提供逐步切流,回滚的能力,降低应用发布带来的风险。本文先后介绍了 Ingress…","guid":"https://www.apiseven.com/blog/traffic-split-in-apache-apisix-ingress-controller","author":"Chao Zhang","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-03-26T16:00:00.808Z","media":[{"url":"https://static.apiseven.com/202108/pasted%20image%202.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"使用 Cypress 获取前端测试覆盖率","url":"https://www.apiseven.com/blog/get-front-end-test-coverage-with-cypress","content":"在《使用 Cypress 让产品持续稳定交付》文章中,我们讨论了为什么选用 Cypress 作为 E2E 测试框架。在花了近两个月时间完善测试案例后,我们需要测试覆盖率来量化测试覆盖是否足够。本文将介绍如何使用 Cypress 获取 APISIX Dashboard 前端 E2E 覆盖率。
\\n代码覆盖是软件测试中的一种度量,描述程序中源代码被测试的比例和程度,所得比例称为代码覆盖率。测试代码覆盖率一定程度上反映了代码的健康程度。
\\n想要收集测试覆盖数据,我们需要将原有的业务代码放一些探针以供 Cypress 收集数据。
\\nCypress 官方推荐两种方式,第一种是通过 nyc 生成临时目录,把已经写入探针的代码运行起来以收集测试覆盖数据。第二种方法是通过代码转换管道实时做代码转换,这就少去了临时文件夹烦恼,使得收集测试覆盖率数据比较清爽。我们选择第二种方式收集前端 E2E 覆盖率。
\\nyarn add babel-plugin-istanbul --dev\\n
\\nyarn add @cypress/code-coverage --dev\\n
\\n// web/config/config.ts\\nextraBabelPlugins: [\\n [\'babel-plugin-istanbul\', {\\n \\"exclude\\": [\\"**/.umi\\", \\"**/locales\\"]\\n }],\\n ],\\n
\\n// web/cypress/plugins/index.js\\nmodule.exports = (on, config) => {\\n require(\'@cypress/code-coverage/task\')(on, config);\\n return config;\\n};\\n
\\n// web/cypress/support/index.js\\nimport \'@cypress/code-coverage/support\';\\n
\\n配置完毕后,需要我们运行测试案例,在测试案例运行结束后,Cypress 会生成 coverage 和\\n.nyc_output 文件夹,里面包含测试覆盖率的报告。
\\n执行下面的命令后测试覆盖率信息会出现在控制台。
\\nnpx nyc report --reporter=text-summary\\n
\\n在 coverage 目录下,会有更详细的报告网页,如图所示:
\\nStatements 表示是否每个语句都执行了
\\nBranchs 表示是否每个 if 代码块都执行了
\\nFunctions 表示是否每个函数都调用了
\\nLines 表示是否每一行都执行了
\\n测试覆盖率的高低一定程度上反映了项目的质量。目前 APISIX Dashboard 前端 E2E 覆盖率已经达到了 71.57%, 我们将持续协同社区,继续增强测试覆盖率,为用户提供更可靠稳定的产品。
\\n","description":"背景 在《使用 Cypress 让产品持续稳定交付》文章中,我们讨论了为什么选用 Cypress 作为 E2E 测试框架。在花了近两个月时间完善测试案例后,我们需要测试覆盖率来量化测试覆盖是否足够。本文将介绍如何使用 Cypress 获取 APISIX Dashboard 前端 E2E 覆盖率。\\n\\n什么是代码覆盖率\\n\\n代码覆盖是软件测试中的一种度量,描述程序中源代码被测试的比例和程度,所得比例称为代码覆盖率。测试代码覆盖率一定程度上反映了代码的健康程度。\\n\\n安装依赖&配置\\n\\n想要收集测试覆盖数据,我们需要将原有的业务代码放一些探针以供 Cypress 收集数据。…","guid":"https://www.apiseven.com/blog/get-front-end-test-coverage-with-cypress","author":"孙毅","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-03-01T16:00:00.515Z","media":[{"url":"https://static.apiseven.com/202108/pasted%20image%200.png","type":"photo"},{"url":"https://static.apiseven.com/202108/pasted%20image%201.png","type":"photo"},{"url":"https://static.apiseven.com/202108/pasted%20image%203.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"使用 Helm Charts 安装 Apache APISIX","url":"https://www.apiseven.com/blog/install-apache-apisix-from-helm-charts","content":"日前支流科技提供了一个在线 Helm Charts 仓库 https://charts.apiseven.com, 用户可通过该仓库轻松安装 Apache APISIX、Apache apisix-dashboard 和 Apache apisix-ingress-controller (而不需要提前 clone 对应的项目)。
\\n只需通过以下几步即可安装 Apache APISIX 2.1 版本。
\\n添加仓库并获取更新
\\n$ helm repo add apisix https://charts.apiseven.com\\n$ helm repo update\\n
\\n查看仓库中可用的 Charts 包
\\n$ helm search repo apisix\\n\\nNAME CHART VERSION APP VERSION DESCRIPTION\\napisix/apisix 0.1.2 2.1.0 A Helm chart for Apache APISIX\\napisix/apisix-dashboard 0.1.0 2.3.0 A Helm chart for Apache APISIX Dashboard\\n
\\n安装 Apache APISIX 到目标 Kubernetes 集群中
\\n$ helm install apisix-gw apisix/apisix --namespace default\\n\\nNAME: apisix-gw\\nLAST DEPLOYED: Fri Feb 19 11:34:14 2021\\nNAMESPACE: default\\nSTATUS: deployed\\nREVISION: 1\\nTEST SUITE: None\\nNOTES:\\n1. Get the application URL by running these commands:\\n export NODE_PORT=$(kubectl get --namespace default -o jsonpath=\\"{.spec.ports[0].nodePort}\\" services apisix-gw-gateway)\\n export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath=\\"{.items[0].status.addresses[0].address}\\")\\n echo http://$NODE_IP:$NODE_PORT\\n
\\n作为流量管理人员,有时候,即使做好了万全准备,也难挡突发状况的出现。构建四通八达的 API 网关至关重要!今天就来为大家介绍**Amazon EKS + Ingress APISIX!**是如何帮助我们解决这个问题的。
\\nKubernetes 是一个开源系统,用于自动化容器化应用程序的部署、扩展和管理。Amazon Elastic Kubernetes Service(Amazon EKS)作为一种托管的 Kubernetes 服务,您可以在亚马逊云科技上轻松运行 Kubernetes 负载而无需对控制平面或节点进行安装和维护。
\\nApache APISIX 是一个动态、实时、高性能的 API 网关。它提供了丰富的流量管理功能,如负载平衡、动态上游、灰度部署、流量分割、身份验证和可观测性等。您可以使用 Apache APISIX 处理传统客户端和服务器之间的南北流量以及服务之间的东西流量。
\\nIngress APISIX 可以将 Apache APISIX 作为 Kubernetes 的入口控制器使用,从而为 Kubernetes 引入 Apache APISIX 的各项优秀功能。借助妥善设计的 Controller 组件的驱动,可以帮助用户满足复杂的流量管理需求。
\\n准备运行前,请在亚马逊云科技上配置好可用的 Amazon EKS 集群。
\\n你自己的环境中应具备 kubectl 工具,请运行如下命令将上下文设置为自己的 Amazon EKS 集群:
\\naws eks update-kubeconfig --name <your eks cluster name> --region <your region>\\n
\\nKubernetes 集群就绪后,创建名为 ingress-apisix 的名称空间,后续用到的所有资源都将创建于该名称空间中。
\\nkubectl create namespace ingress-apisix\\n
\\n我们将使用 Helm 部署 Ingress APISIX(Apache APISIX 和 apisix-ingress-controller)的所有组件,因此也请按照安装指南 来安装 Helm。适用于 Apache APISIX 和 apisix-ingress-controller 的 helm chart 位于 apache/apisix-helm-chart 和 apache/apisix-ingress-controller 路径下,请克隆这些路径以获得相应的 chart。
\\nApache APISIX 充当了apisix-ingress-controller的代理平面,应提前部署完成。
\\ncd /path/to/apisix-helm-chart\\nhelm repo add bitnami https://charts.bitnami.com/bitnami\\nhelm dependency update ./chart/apisix\\nhelm install apisix ./chart/apisix \\\\\\n --set gateway.type=LoadBalancer \\\\\\n --set allow.ipList=\\"{0.0.0.0/0}\\" \\\\\\n --namespace ingress-apisix\\nkubectl get service --namespace ingress-apisix\\n
\\n上述命令将创建两个 Kubernetes Service 资源,一个为负责处理真实流量的 apisix-gateway,另一个为充当控制平面并处理所有配置改动的 apisix-admin。此处我们将 apisix-gateway 创建为 LoadBalancer 类型的服务,可借助 Amazon Network Load Balancer 将其暴露至互联网。我们可通过下列命令找到负载均衡器的主机名:
\\nkubectl get service apisix-gateway \\\\\\n--namespace ingress-apisix \\\\\\n-o jsonpath=\'{.status.loadBalancer.ingress[].hostname}\'\\n
\\n另外要注意:allow.ipList 字段应根据我们自己 Amazon EKS 集群中的 EKS CIDR Ranges 进行定制,这样 apisix-ingress-controller 即可由 Apache APISIX 进行授权(用于推送资源)。
\\n如果还有其他需求,请参阅 value.yaml 进一步了解所有配置项。
\\n成功部署 Apache APISIX 后,需要安装 Controller 组件了。
\\ncd /path/to/apisix-ingress-controller\\n# install base resources, e.g. ServiceAccount.\\nhelm install ingress-apisix-base -n ingress-apisix ./charts/base\\n# install apisix-ingress-controller\\nhelm install ingress-apisix ./charts/ingress-apisix \\\\\\n --set ingressController.image.tag=dev \\\\\\n --set ingressController.config.apisix.baseURL=http://apisix-admin:9180/apisix/admin \\\\\\n --set ingressController.config.apisix.adminKey={YOUR ADMIN KEY} \\\\\\n --namespace ingress-apisix\\n
\\ningress-apisix-base chart 会为 apisix-ingress-controller 安装一些基本依赖项,例如 ServiceAccount 及其专用 CRD 等内容。
\\ningress-apisix chart 将引导我们安装 Controller 自身,我们可以将 image 标签更改为所需的发布版本,并可更改上述命令中 ingressController.config.apisix.adminKey 的值,这些配置可根据实际场景进行调整(并确保此处使用的 Admin key 与 Apache APISIX 部署中所用的 Key 相同)。如果还有其他需求,可以参阅 value.yaml 进一步了解所有配置项。
\\n随后试着打开 Amazon EKS 控制台,选择自己的集群并单击 Workloads 标签,所有将能看到 Apache APISIX 的所有 Pod、etcd 以及 apisix-ingress-controller 均已就绪。
\\n至此我们已经部署了 Ingress APISIX 的所有组件,请务必验证一切均可正常运行。随后我们将部署一个 httpbin 服务并要求 Apache APISIX 将所有到”local.httpbin.org”主机的请求路由至该服务。
\\n为此,我们首先需要创建 httpbin 工作负载并将其暴露出来。
\\nkubectl run httpbin --image kennethreitz/httpbin --port 80\\nkubectl expose pod httpbin --port 80\\n
\\n为了让 Apache APISIX 对请求进行正确的路由,我们需要创建一个 ApisixRoute 资源驱动这一过程。
\\n# ar-httpbin.yaml\\napiVersion: apisix.apache.org/v1\\nkind: ApisixRoute\\nmetadata:\\n name: httpserver-route\\nspec:\\n rules:\\n - host: local.httpbin.org\\n http:\\n paths:\\n - backend:\\n serviceName: httpbin\\n servicePort: 80\\n path: /*\\n
\\n上述 ApisixRoute 资源会让 Apache APISIX 将主机头为“local.httpbin.org”的请求路由至(我们刚刚创建的)httpbin 后端。
\\n随后应用该设置,但请注意:该服务和 ApisixRoute 资源应放置在同一个名称空间中,apisix-ingress-controller 不允许跨越名称空间。
\\nkubectl apply -f ar-httpbin.yaml\\n
\\n从可触达 Apache APISIX 服务的任意位置通过一个简单的 curl 调用测试结果。
\\n$ curl http://{apisix-gateway-ip}:{apisix-gateway-port}/headers -s -H \'Host: local.httpbin.org\'\\n\\n\\n{\\n \\"headers\\": {\\n \\"Accept\\": \\"*/*\\",\\n \\"Host\\": \\"httpbin.org\\",\\n \\"User-Agent\\": \\"curl/7.64.1\\",\\n \\"X-Amzn-Trace-Id\\": \\"Root=1-5ffc3273-2928e0844e19c9810d1bbd8a\\"\\n }\\n}\\n
\\n如果 Serivce 类型为 ClusterIP,则需要登录到 Amazon EKS 集群中的一个 Pod,随后使用 ClusterIP 或 Service FQDN 访问 Apache APISIX。如果已经暴露(无论暴露了 NodePort或 LoadBalancer),则可直接访问可触达的外部端点。
\\n注:该文章转自 aws 微信公众号。
\\n","description":"背景 作为流量管理人员,有时候,即使做好了万全准备,也难挡突发状况的出现。构建四通八达的 API 网关至关重要!今天就来为大家介绍**Amazon EKS + Ingress APISIX!**是如何帮助我们解决这个问题的。\\n\\n简介\\n\\nKubernetes 是一个开源系统,用于自动化容器化应用程序的部署、扩展和管理。Amazon Elastic Kubernetes Service(Amazon EKS)作为一种托管的 Kubernetes 服务,您可以在亚马逊云科技上轻松运行 Kubernetes 负载而无需对控制平面或节点进行安装和维护。\\n\\nApache…","guid":"https://www.apiseven.com/blog/how-amazon-eks-and-apisix-ingress-controller-work-together-to-manage-complex-traffic","author":"亚马逊云科技 AWS云计算","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-02-06T16:00:00.723Z","media":[{"url":"https://static.apiseven.com/202102/WechatIMG3731.jpeg","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"使用 Cypress 让产品持续稳定交付","url":"https://www.apiseven.com/blog/stable-product-delivery-with-cypress","content":"Apache APISIX Dashboard 的设计是为了让用户通过前端界面尽可能方便地操作 Apache APISIX。从项目初始化到现在,已经有 552 commits、发布了 10 个版本。在如此之快的产品迭代过程中,确保开源产品质量显的尤为重要。为此,我们引入了 E2E 测试模块以确保稳定的产品交付。
\\nE2E,是“End to End”的缩写,可以翻译成“端到端”测试。它模仿用户操作行为,从某个入口开始,逐步执行操作,直到完成某项工作。完善的测试可以防止代码改动时破坏原有的逻辑。
\\n我们在选型调研期分别使用 Taiko、Puppeteer、TestCafe 、Cypress 书写创建路由的测试案例,通过使用每个测试框架书写案例,来体会其各自的特点。
\\nTaiko 的特点是具有 smart selector, 可以根文字内容、位置关系智能定位想要操作的元素 ,上手成本也比较低,能够很快的完成测试案例。但是,在书写测试案例时并不友好,当用户误操作退出终端后,所书写的测试案例也全部丢失。如果想要完整地运行测试案例,还需要配合其它的 test runner 一起使用,这无疑又增加了用户的学习成本。
\\nPuppeteer 具有最好的性能表现。但是,测试并不是 Puppeteer 的重点。它被广泛用于网页爬虫。我们的项目起初使用的是 Ant Design 官方推荐的 E2E 测试框架即 Puppeteer ,使用了一段时间后发现 Puppeteer 对非前端开发者不是那么友好,很难让其他用户参与进来。当用户编写测试案例时,缺少智能元素定位的功能加持使得用户学习曲线很高。
\\nTestCafe 的安装简单程度令人惊喜,它具有内置的等待机制,用户不用主动的去 sleep 等待页面交互,并且支持多浏览器并发测试,这对多浏览器兼容性测试很有帮助。缺点是它的调试过程并不是那么友好,每次测试案例更改后都要从新跑一遍用例。对于开发人员而言,要有一定的 Javascript 语法基础。其次,它的运行速度相对于其它几个框架而言比较慢,尤其是执行 withText() 查找元素时。
\\n综合比较后,我们最终选用了 Cypress 作为我们的前端 E2E 框架,列出四点主要原因:
\\nCypress 测试所使用的语法非常简单,而且容易阅读和书写。稍加练习后,就能掌握创建测试案例,这对于开源项目来说是很重要的,因为这样可以让社区里有兴趣参加 E2E 测试案例的用户以最低的学习成本参与到书写测试案例中。
\\n在调试测试用例时,我们可以使用 Cypress 的 Test Runner。Test Runner 可以展示多维度的数据,通过这些信息,我们可以快速定位到问题所在。
\\nCypress 有一个庞大的用户社区,社区里面总是有很多人在分享他们的经验和主意。
\\n这在遇到问题时很有帮助,你很有可能遇到别人在之前就已经遇到的问题。另外,当有新的功能需求时,我们也可以参与到社区,通过讨论,把自己想加入的特性加入到 Cypress 中,就像我们 Apache APISIX 社区做的事一样:听取社区的意见并反哺社区。
\\nCypress 的文档结构更加清晰全面。在使用初期,我们根据官方文档指引很快的就能把 Cypress 引入到我们的项目中并书写第一个案例。此外,在其文档站中,有大量的文档可供参阅,这会给用户很好的指引,会让用户知道怎么样做才是最好的实践。
\\n目前 APISIX Dashboard 已经书写 49 个测试案例。我们在 GitHub Action 中配置对应的 CI,确保每次合并代码前测试通过以保证代码质量。我们参考 Cypress 的最佳实践并结合我们的项目,和大家分享一下 Cypress 在 APISIX Dashboard 的使用。
\\n以登录为例,登录是进入系统必不可少的环节, 我们把登录环节封装成命令,这样,在每次运行案例之前,进行登录命令调用。
\\nCypress.Commands.add(\\"login\\", () => {\\n cy.request(\\n \\"POST\\",\\n \'http://127.0.0.1/apisix/admin/user/login\',\\n {\\n username: \\"user\\",\\n password: \\"user\\",\\n }\\n ).then((res) => {\\n expect(res.body.code).to.equal(0);\\n localStorage.setItem(\\"token\\", res.body.data.token);\\n });\\n});\\n
\\nbeforeEach(() => {\\n // init login\\n cy.login();\\n});\\n
\\n为了让用户更直观理解测试代码的含义,我们将 selector 和 data 抽成公共变量。
\\nconst data = {\\n name: \\"hmac-auth\\",\\n deleteSuccess: \\"Delete Plugin Successfully\\",\\n};\\nconst domSelector = {\\n tableCell: \\".ant-table-cell\\",\\n empty: \\".ant-empty-normal\\",\\n refresh: \\".anticon-reload\\",\\n codemirror: \\".CodeMirror\\",\\n switch: \\"#disable\\",\\n deleteBtn: \\".ant-btn-dangerous\\",\\n};\\n
\\n我们在使用 Cypress 的前期使用 cy.wait(someTime),但在使用中发现,cy.wait(someTime) 过度依赖网络环境以及测试机器的性能,当网络环境或者机器性能差时,会导致测试案例报错。推荐的做法是配合 cy.intercept() 使用以明确指定需要等待的网络资源。
\\ncy.intercept(\'https://apisix.apache.org/\').as(\'fetchURL\');\\ncy.wait(\'@fetchURL\');\\n
\\n目前 APISIX Dashboard 已经书写 49 个测试案例。未来,我们将持续增强前端 E2E 覆盖率,在社区中约定每次提交新的特性或者 bugfix 都需要书写对应的测试案例以保证产品的稳定性。
\\n欢迎大家加入我们一起打磨世界级的网关产品。
\\n项目地址:https://github.com/apache/apisix-dashboard
\\n","description":"背景 Apache APISIX Dashboard 的设计是为了让用户通过前端界面尽可能方便地操作 Apache APISIX。从项目初始化到现在,已经有 552 commits、发布了 10 个版本。在如此之快的产品迭代过程中,确保开源产品质量显的尤为重要。为此,我们引入了 E2E 测试模块以确保稳定的产品交付。\\n\\n什么是前端 E2E\\n\\nE2E,是“End to End”的缩写,可以翻译成“端到端”测试。它模仿用户操作行为,从某个入口开始,逐步执行操作,直到完成某项工作。完善的测试可以防止代码改动时破坏原有的逻辑。\\n\\n为什么选择 Cypress\\n\\n我们在选型…","guid":"https://www.apiseven.com/blog/stable-product-delivery-with-cypress","author":"孙毅","authorUrl":null,"authorAvatar":null,"publishedAt":"2021-02-06T16:00:00.485Z","media":[{"url":"https://static.apiseven.com/202108/apisix-dashboard-e2e.gif","type":"photo"},{"url":"https://static.apiseven.com/202102/image.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Apache APISIX 助力企业数字化转型","url":"https://www.apiseven.com/blog/apache-apisix-helps-enterprises-transform-digitally","content":"随着互联网、大数据、云计算、人工智能、物联网、区块链等一系列技术创新与行业服务的加速融合,行业产品创新能力正在不断提升,数字化、智能化不断催生新兴的服务模式和新产品,已成为企业数字化转型升级的新方向。
\\n企业用户采购 API 网关作为企业自身数字化转型的一环,为后续持续转型和升级做铺垫,逐步向“全面云化”、“分布式化”、“智能化”、“开放化”的新技术体系演进。云原生 API 网关 Apache APISIX,可以完美的助力企业完成 API 管理和微服务架构转型。此外基于开源 APISIX 还有 k8s Ingress Controller 和 Service Mesh 产品,企业用户后续升级到 Kubernetes 和服务网格,提供统一、顺滑的过渡方案。底层技术栈的统一,极大降低学习、管理维护成本。
\\n同时,在云原生架构下,开源 + 购买商业支持的方式是首选,这不仅仅保证企业自身不被具体商业公司锁定,更重要的是,可以让企业保持快速的技术升级,以便让技术满足产品的迭代, 最终在竞争中取得优势。
\\nAPISIX 是 Apache 基金会的顶级项目,同时也在云原生软件基金会(CNCF)的全景图中,与 Apache 基金会旗下的各种大数据组件和 CNCF 的各种云原生组件,有着非常好的生态,可以方便的对接企业用户在大数据和云原生领域的其他系统。
\\n目前已有众多国内外知名互联网和传统公司采用 Apache APISIX,使用案例分布在金融、电信运营商、物联网、零售、在线教育、航空航天等多个行业,包括 NASA、航天网信、欧盟数字工厂、思必驰、中国移动、腾讯、虎牙、奈雪的茶、雪球、空中云汇、泰康人寿、作业帮、嘀嗒出行、明源云等。
\\n深圳支流科技是 Apache APISIX 的原厂,初始团队来自中国知名互联网公司,投资方包括真格基金和真成投资,可以提供本地化和专业的服务。
\\n需求 | \\n说明 | \\nAPISIX支持情况 | \\n
---|---|---|
控制台 | \\n支持操作人员在控制台上操作,完成 API 管理、监控等需要 | \\nAPISIX 提供了方便使用的 dashboard,支流科技在开源 APISIX 的基础上增加了用户、角色、工作区、多集群等企业级功能。 | \\n
用户认证 | \\n支持 AK/SK、JWT 用户认证 | \\nAPISIX 支持 Consumer,可以直接完成用户认证,除了常见 AK/SK、JWT 外,还支持 Basic-Auth、Key-Auth 等多种用户认证。 | \\n
动态路由、上游 | \\n动态添加修改路由、上游 | \\n在 APISIX 中路由、上游的添加修改是原生动态的,内存生效不需要任何进程替换,相比 Nginx 等需要 reload 的实现方案要好,不会产生流量抖动。 | \\n
负载均衡器 | \\n反向代理支持指定不同负载均衡算法 | \\n除了已支持带有权重的 roundrobin 和一致性哈希算法外,还支持指数加权移动平均法(EWMA)和最小连接数算法。 APISIX 是目前唯一支持用户自定义负载均衡策略的 API 网关,满足企业用户的一些特殊场景需求。 | \\n
限流、限速熔断 | \\n为保护上游对请求流量做频度控制 | \\n支持单机和集群两种方式限流限速。 单机主要有三种: 1. limit-count:指定时间限制请求总数。 2. limit-req:限制请求频率。 3. limit-conn:限制并发数。 集群支持两种: limit-count 和 limit-conn。 | \\n
监控告警 | \\n对 API 请求、API 网关自身做监控,支持设置阈值完成告警 | \\n监控,目前已支持下面三种类型: 1. Metric:支持 Prometheus 对接。 2. Logging:将访问日志(动态自定义)发送到指定 HTTP、TCP 或 UDP 服务。 3. Tracing: OpenTracing 协议,支持 SkyWalking 、 Zipkin 等实现。 告警: 1. 支持任何 HTTP 或 syslog 方式发送告警信息。 2. 支持插件方式完成企业自定义。 | \\n
上游健康检查 | \\n剔除不健康节点 | \\n检查方式支持下面两种: 1. 主动健康检查:主动探测上游服务是否健康,剔除不健康节点。 2. 被动健康检查:根据请求应答码更新节点状态,剔除不健康节点。 | \\n
多集群管理 | \\n管理控制台统一登录,同时管理不同集群的 API | \\n在 API7 支持多集群:不同集群有完全独立的 API 和资源。企业不同主要业务线,为了避免相互干扰,优先推荐集群方式隔离。 | \\n
API 编排 | \\n通过一个请求来调用多个微服务,并对返回结果做数据处理,最终整合成一个结果 | \\n支持两种方式完成此特性: 1. 通过 GraphQL 方式直接完成 API 的编排,目前 APISIX 已经开源支持。 2. 通过自定义插件方式扩充满足企业 API 编排需求。 | \\n
swagger 格式 API 导入 | \\n使用 swagger 标准完成 API 批量导入 | \\n已内置支持 OpenAPI Specification3.0 方式导入 swagger 。 | \\n
1. Apache 顶级项目
\\nApache APISIX 是中国最快毕业的孵化器项目,也被纳入了 CNCF 全景图中。
\\n目前很多流行的 AI、大数据类开源项目,主要集中在 Apache 基金会(300 多顶级项目)。APISIX 与这些项目具有相同的文化认同,更容易完成生态对接(如下图)。
\\n2. CNCF 基金会生态
\\nAPISIX 的配置中心使用 etcd ,更适合云原生技术架构,降低用户使用和运维成本。
\\n支流科技还捐献了 APISIX Ingress Controller 到 Apache 基金会,为 Kubernetes 流量入口转发多一个选择。APISIX 也支持 helm chart 方式安装,简化 Kubernetes 环境内 APISIX 部署。
\\n3. 全世界最活跃 API 网关项目
\\nApache APISIX 是全球最活跃的开源 API 网关项目,在中国所有开源项目中排名第 22 位。参考维度(如下图)有活跃开发者数量、活跃 PR 和 Issue 数量等。
\\n4. 智能面,插件编排
\\n开发者可以使用 DAG(有向无环图)对插件进行编排,通过决策树对请求流量进行实时分析和处理,以此实现了低代码 API 网关。
\\n用户在界面上通过拖拉拽方式,自由编排插件执行顺序,让产品经理或运维可以直接完成业务需求。利用该特性,可以让 APISIX 直接与智能 AI 服务配合。
\\n插件编排是 APISIX 独创,是全球唯一支持插件编排的智能 API 网关。文档不支持动画,可以在支流科技官网查看动画演示:www.apiseven.com 。
\\n5. 架构优势,内置高可用
\\nAPISIX 是一整套完整的 API 网关解决方案,不仅提供数据面(Data Plane)实现,也提供了控制面(Control Plane)实现,二者均为无状态设计,可以根据需求自由扩缩容。
\\n6. 路由、上游、SSL 等对象全部支持动态指定
\\n与传统 HAProxy、Nginx、Spring Cloud Gateway、Zuul 等不支持动态路由的方案相比, APISIX 的所有对象全部是内存动态添加或更新,数据替换或更新时不会产生任何进程重启,最小化影响线上流量。
\\n7. 性能指标最好 API 网关
\\nAPISIX 是目前所有开源 API 网关产品中性能技术指标表现最好,毫秒级低延迟,满足企业用户对 API 的实时性要求。
\\n8. 使用案例
\\n目前已有众多国内外知名互联网和传统行业公司采用 Apache APISIX,使用案例分布在金融、电信运营商、物联网、零售、在线教育、航空航天等多个行业,包括 NASA、航天网信、欧盟数字工厂、思必驰、中国移动、腾讯、虎牙、奈雪的茶、雪球、空中云汇、作业帮、嘀嗒出行、明源云等。
\\n对非常关心延迟指标的金融、证券行业,也在生产环境使用了 APISIX,比如前面提到的空中云汇等。
\\n1. 团队成员
\\n2. 融资背景
\\n支流科技在半年时间内,完成了数百万美元的融资,投资方为真格基金和真成投资。
\\n1. Kubernetes Ingress controller
\\nAPISIX Ingress Controller 基于 APISIX, 集成 Kubernetes 的集群管理能力,支持使用 YAML 申明的方式动态配置入口流量的分发规则、绑定插件,并且支持服务发现、配置校验等能力。APISIX Ingress Controller 将配置写入 APISIX,由 APISIX 承载业务流量。
\\nAPISIX Ingress Controller 除了覆盖 NGINX Ingress Controller 已有的能力外,还解决了一些 Nginx Ingress Controller 的痛点。目前该项目已捐给 Apache:https://github.com/apache/apisix-ingress-controller 。
\\n\\n | APISIX Ingress Controller | \\n
---|---|
所属 | \\nApache 基金会 | \\n
架构 | \\n基于 Apache APISIX | \\n
动态路由 | \\n原生支持 | \\n
二次开发难度 | \\n简单,基于 Lua 插件或插件编排(低代码) | \\n
自定义 RPC 协议 | \\n容易 | \\n
性能 | \\n高 | \\n
2. Service Mesh
\\n服务网格是企业内部服务的治理方案。目前通行的方案是 istio + Envoy 的组合。但这个组合也会有很多性能和通用性上问题。
\\n支流科技基于 Apache APISIX,给出了更简洁、更通用的服务网格解决方案。
\\n3. 架构演变
\\n下图是后端服务架构演变史,APISIX 助力企业完成数字化转型,统一技术栈,降低企业开发、维护成本。开源,不锁定企业用户,建立公开、透明的 IT 市场,让企业用户专注于业务需求自身。
\\n伴随着社会数字化的趋势,企业用户数字化、智能化、开放化转型已是大势所趋,行业信息系统的全面转型也是势在必行。“驱动企业数字化转型,协助企业管理并可视化 API 和微服务等关键业务流量,通过大数据和人工智能(AI)加速企业业务决策”,这是支流科技使命。
\\n","description":"背景 随着互联网、大数据、云计算、人工智能、物联网、区块链等一系列技术创新与行业服务的加速融合,行业产品创新能力正在不断提升,数字化、智能化不断催生新兴的服务模式和新产品,已成为企业数字化转型升级的新方向。\\n\\n企业用户采购 API 网关作为企业自身数字化转型的一环,为后续持续转型和升级做铺垫,逐步向“全面云化”、“分布式化”、“智能化”、“开放化”的新技术体系演进。云原生 API 网关 Apache APISIX,可以完美的助力企业完成 API 管理和微服务架构转型。此外基于开源 APISIX 还有 k8s Ingress Controller 和…","guid":"https://www.apiseven.com/blog/apache-apisix-helps-enterprises-transform-digitally","author":null,"authorUrl":null,"authorAvatar":null,"publishedAt":"2021-02-03T16:00:00.926Z","media":[{"url":"https://static.apiseven.com/logo/20210203/1.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/2.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/3.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/4.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/5.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/6.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/7.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/8.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/9.png","type":"photo"},{"url":"https://static.apiseven.com/logo/20210203/10.png","type":"photo"},{"url":"https://static.apiseven.com/202102/11.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"初探 Kubernetes Service APIs","url":"https://www.apiseven.com/blog/a-first-look-at-kubernetes-service-api","content":"我们知道 Kubernetes 为了将集群内部服务暴露出去,有多种方案实现,其中一个比较受大众推崇的就是 Ingress。Ingress 作为一种对外暴露服务的标准,有相当多的第三方实现,每种实现都有各自的技术栈 和 所依赖的网关的影子,相互之间并不兼容。
\\n为了统一各种 Ingress 的实现,便于 Kubernetes 上统一管理,SIG-NETWORK 社区推出了Kubernetes Service APIs 一套标准实现,称为第二代 Ingress 。
\\n本文从几个问题入手,对 Kubernetes Service APIs 的基本概念进行介绍。
\\nKubernetes Service APIs 设计之初,目标并没有局限在 Ingress, 而是为了增强 service networking,着重通过以下几点来增强:表达性、扩展性、RBAC。
\\nkind: HTTPRoute\\napiVersion: networking.x-k8s.io/v1alpha1\\n...\\nmatches:\\n - path:\\n value: \\"/foo\\"\\n headers:\\n values:\\n version: \\"2\\"\\n - path:\\n value: \\"/v2/foo\\"\\n
\\nKubernetes Service APIs 基于使用者角色,将定义了以下几种资源:
\\nGatewayClass, Gateway, Route
\\n与 Gateway 的关系,类似 ingress 中的 ingess.class annotation;
\\nGatewayClass 定义了一组共享相同配置和行为的网关。每个 GatewayClass 将由单个 controller 处理,controller 与 GatewayClass 是一对多的关系;
\\nGatewayClass 是 cluster 资源。必须至少定义一个 GatewayClass 才能具有功能网关。
\\n作用:把集群外的流量引入集群内部。这个才是真正的 ingress 实体;
\\n它定义了对特定 LB 配置的请求,该配置也是 GatewayClass 的配置和行为的实现;
\\nGateway 资源可以由操作员直接创建,也可以由处理 GatewayClass 的 controller 创建;
\\nGateway 与 Route 是多对多的关系;
\\n另外,Kubernetes Service APIs 为了能够灵活的配置后端服务,特地定义了一个 BackendPolicy 资源对象。
\\n通过 BackendPolicy 对象,可以配置 TLS、健康检查 以及指定后端服务类型,比如 service 还是 pod。
\\nKubernetes Service APIs 作为一种实现标准,带来了以下改变:
\\n通用性: 可以有多种实现,就像 ingress 有多种实现一样,可以根据网关的特点去自定义 ingress controller,但是他们都有一致的配置结构。一种数据结构,可以配置多种 ingress controller。
\\nClass 概念:GatewayClasses 可以配置不同负载均衡实现的类型。这些类 class 使用户可以轻松而明确地了解哪些功能可以用作资源模型本身。
\\n共享网关:通过允许独立的路由资源 HTTPRoute 绑定到同一个 GatewayClass,它们可以共享负载平衡器和 VIP。按照使用者分层,这使得团队可以安全地共享基础结构,而无需关心下层 Gateway 的具体实现。
\\n带类型的后端引用: 使用带类型的后端引用,路由可以引用 Kubernetes Services,也可以引用任何类型的设计为网关后端的 Kubernetes 资源,比如 pod,又或者是 statefulset 比如 DB, 甚至是可访问的集群外部资源。
\\n跨命名空间引用:跨不同命名空间的路由可以绑定到 Gateway。允许跨命名空间的互相访问。同时也可以限制某个 Gateway 下的 Route 可以访问的命名空间范围。
\\n目前已知的从代码层面能看到对 Kubernetes Service APIs 资源对象支持的 Ingress 有 Contour, ingress-gce。
\\nKubernetes Service APIs 按照使用者的维度分为 3 个角色
\\n基础设施提供方 GatewayClass
\\n集群操作人员 Gateway
\\n应用开发者 Route
\\nRBAC(基于角色的访问控制)是用于 Kubernetes 授权的标准。允许用户配置谁可以对特定范围内的资源执行操作。 RBAC 可用于启用上面定义的每个角色。
\\n在大多数情况下,希望所有角色都可以读取所有资源
\\n三层模型的写权限如下。
\\n\\n | GatewayClass | \\nGateway | \\nRoute | \\n
---|---|---|---|
Infrastructure Provider | \\nYes | \\nYes | \\nYes | \\n
Cluster Operators | \\nNo | \\nYes | \\nYes | \\n
Application Developers | \\nNo | \\nNo | \\nYes | \\n
网关的需求非常丰富,同一个场景实现的方式多种多样,各有利弊。Kubernetes Service APIs 提炼出 多层 资源对象,同时也预留了一些扩展点。
\\n目前 Kubernetes Service APIs 的扩展点基本集中在 Route 上:
\\nRouteMatch 可以扩展 Route 匹配规则。
\\nspcify Backend 可以扩展特定类型的 后端服务, 除了上面提到的 Kubernetes 资源外,还可以扩展比如 文件系统,函数表达式等。
\\nRoute filter 可以在 Route 的生命周期中增加扩展点,处理 request/response 。
\\nCustom Route 以上扩展点都不能满足时,可以完全自定义一个 Route。
\\n本文通过提问的方式,对 Kubernetes Service APIs 做了一些基本介绍,从整体来看,Kubernetes Service APIs 提炼了很多 ingress 的最佳实践,比如表达能力的增强,其实就是扩展了 Route 的能力,再比如 BackendPolicy 对象,可以为 upstream 指定几乎所有的 Kubernetes 后端资源。当然,项目初期也有不足的地方,目前 Kubernetes Service APIs 虽然已经从大的层面上规定了资源对象,但资源对象内部还有不少细节需要讨论之后再确定,以防止可能出现的冲突场景,结构上存在一定变数。
\\n","description":"前言 我们知道 Kubernetes 为了将集群内部服务暴露出去,有多种方案实现,其中一个比较受大众推崇的就是 Ingress。Ingress 作为一种对外暴露服务的标准,有相当多的第三方实现,每种实现都有各自的技术栈 和 所依赖的网关的影子,相互之间并不兼容。\\n\\n为了统一各种 Ingress 的实现,便于 Kubernetes 上统一管理,SIG-NETWORK 社区推出了Kubernetes Service APIs 一套标准实现,称为第二代 Ingress 。\\n\\n主题描述\\n\\n本文从几个问题入手,对 Kubernetes Service APIs…","guid":"https://www.apiseven.com/blog/a-first-look-at-kubernetes-service-api","author":"金卫","authorUrl":null,"authorAvatar":null,"publishedAt":"2020-12-17T16:00:00.564Z","media":[{"url":"https://gateway-api.sigs.k8s.io/images/api-model.png","type":"photo","width":2414,"height":1418,"blurhash":"L07UI{j[fQj[j[fQfQfQfQfQfQfQ"},{"url":"https://gateway-api.sigs.k8s.io/images/schema-uml.svg","type":"photo","width":576,"height":284,"blurhash":"L07UI{offQofoffQfQfQfQfQfQfQ"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"如何彻底避免正则表达式的灾难性回溯?","url":"https://www.apiseven.com/blog/how-to-avoid-catastrophic-backtracking-completely","content":"正则表达式的灾难性回溯(Catastrophic Backtracking)是指,正则在匹配的时候回溯过多,造成 CPU 100%,正常服务被阻塞。
\\n这里有一篇文章详细的描述了一次正则回溯导致 CPU 100% 的发现和解决过程,原文比较长,我之前也在 OpenResty 的开发中遇到过两次类似的问题。
\\n这里简单归纳下,你就可以不用花费时间去了解背景了:
\\n站在开发的角度,修复完有问题的正则表达式,就告一段落了。最多再加上一个保险机制,限制下回溯的次数,比如在 OpenResty 中这样设置:
\\nlua_regex_match_limit 100000;\\n
\\n这样即使出现灾难性回溯,也会被限制住,不会跑满 CPU。
\\n嗯,看上去已经很完美了吗?让我们来跳出开发的层面,用不同的维度来看待这个问题。
\\n只用一台机器,发送一个请求,就可以打跨对方的服务器,这简直就是黑客梦寐以求的核武器。与之相比,什么 DDoS 弱爆了,动静大还花钱多。
\\n这种攻击也有自己的名字:ReDoS (RegEx Denial of Service)。
\\n由于正则表达式应用非常广泛,几乎存在于后端服务的各个部分,所以只要找到其中一个漏洞,就有机可趁。
\\n试想一个场景,黑客发现了 WAF 中存在 ReDoS 漏洞,发送一个请求打垮了 WAF;你无法在短时间内定位这个问题,甚至意识不到这是一次攻击;为了保证业务的正常,你选择重启或者暂时关闭 WAF;在 WAF 失效期间,黑客利用 SQL 注入,拖走了你的数据库。而你,可能还完全蒙在鼓里。
\\n*由于开源软件和云服务的广泛使用,只保证自己写的正则表达式没有漏洞,也是不够的。*这是另外一个话题了,我们这里先只讨论自己可控范围内的正则。
\\n解决问题的第一步,就是发现问题,而且要尽量发现所有问题,也就是所谓安全的发现能力。
\\n指望人工 code review 来发现有问题的正则,自然是靠不住的。大部分开发者是没有这方面安全意识的,就算有意去找,人也不可能从复杂的正则表达式中找到问题所在。
\\n这正是自动化工具大显身手的时候。
\\n我们有以下两种自动化的方法来解决:
\\n这类工具可以扫描代码中正则表达式,根据一定的算法,从中找出有灾难性回溯的正则。
\\n比如 RXXR2,它是基于一篇 paper 中的算法来实现,把正则转换为ε-NFA,然后再进行搜索,但并不支持正则表达式的扩展语法,所以会有漏报。
\\nfuzz 测试是一种通用的软件测试方法,通过长时间输入大量随机的数据,来检测软件是否有崩溃、内存泄漏等问题。
\\n同样的,在正则的测试中我们也可以用到这种方法。我们可以根据已有的正则表达式来生成测试数据,也可以完全随机生成。
\\nSlowFuzz 是其中一个开源的工具,也是基于一篇 paper 的算法实现,本文最后会列出 paper,它是一个通用的工具,并没有针对正则的结构做处理,所以会有漏报。
\\nSDLFuzzer 是几年前微软开发的一个专门的 ReDoS 检测工具,但已经不再维护了。
\\n这方面的工具可选择的不多,而且关注度不高。不过让我兴奋的是,在搜索资料的过程中,发现了南京大学几位老师和博士关于 ReDoS 的一篇 paper,并且和 paper 一起开源了 ReScue 这个工具:https://2bdenny.github.io/ReScue/。这个工具已经找出了几个开源项目中的 ReDoS 漏洞。
\\n下面是 paper 中对比测试的结果:
\\n即使我们用了这类工具,有难免会有误报和漏报,那么有没有一劳永逸的方式来解决 ReDoS 呢?
\\n那么我们就要回到问题产生的根源去寻找答案:正则引擎使用了回溯的方式来匹配。
\\n如果我们弃用这种方法,是不是就可以了呢?没错,已经有不少其他的正则引擎的实现,都可以一劳永逸的来解决。他们都放弃了回溯,用 NFA/DFA 自动机的方法来实现,优点是适合流式匹配,也更加安全,缺点不支持很多正则的扩展语法,比如 backreferences,好在这些一般也用不到。
\\n谷歌的 RE2 是其中完成度比较高开源项目。它支持 PCRE 的大部分语法,而且有 Go、Python、Perl、Node.js 等多种开发语言的库实现,上手和替换成本很低。
\\n我们以 Perl 为例,看下 RE2 是否可以避免灾难性回溯问题。
\\n我们先来看下这个结果对比图:
\\n代码如下,感兴趣的可以自己试试看:
\\ntime perl -e \'if (\\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\" =~ /a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/) {print(\\"hit\\");}\'\\n\\n40.80s user 0.00s system 99% cpu 40.800 total\\n
\\n需要 40.8 秒才能跑完这个正则,期间 CPU 99%。
\\n采用 RE2 之后,对比非常明显:
\\ntime perl -e \'use re::engine::RE2; if (\\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\" =~ /a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/) {print(\\" hit\\");}\'\\n\\nperl -e 0.00s user 0.00s system 34% cpu 0.011 total\\n
\\nIntel Hyperscan 也是类似 RE2 的正则引擎,也有Perl、Python 等语言的库,上手难度不大。
\\n只不过按照 Intel 的惯例,多了平台的绑定,只能跑在 x86 中。
\\n如果非要说有什么独特的好处,可能是能够和 Intel 的指令集还有硬件更好的配合,有性能的提升,比如结合下自家的 DPDK。
\\n开源的网络入侵检测工具 Snort,也用 Hyperscan 替换了之前的正则引擎,熟悉 Snort 的同学可以试试看。
\\n这里有几篇正则表达式方面的 paper,感兴趣的可以作为扩展阅读。
\\n[1] SlowFuzz: Automated Domain-Independent Detection of Algorithmic Complexity Vulnerabilities: https://arxiv.org/pdf/1708.08437.pdf
\\n[2] Static Analysis for Regular Expression Exponential Runtime via Substructural Logics:https://arxiv.org/abs/1405.7058.pdf
\\n[3] ReScue: Crafting Regular Expression DoS Attacks:https://dl.acm.org/doi/10.1145/3238147.3238159
\\n[4] Regular Expression Matching Can Be Simple And Fast: https://swtch.com/~rsc/regexp/regexp1.html
\\n","description":"正则表达式的灾难性回溯(Catastrophic Backtracking)是指,正则在匹配的时候回溯过多,造成 CPU 100%,正常服务被阻塞。 背景\\n\\n这里有一篇文章详细的描述了一次正则回溯导致 CPU 100% 的发现和解决过程,原文比较长,我之前也在 OpenResty 的开发中遇到过两次类似的问题。\\n\\n这里简单归纳下,你就可以不用花费时间去了解背景了:\\n\\n大部分开发语言的正则引擎是用基于回溯的 NFA 来实现(而不是基于 Thompson’s NFA);\\n如果回溯次数过多,就会导致灾难性回溯,CPU 100%;\\n需要用 gdb 分析 dump…","guid":"https://www.apiseven.com/blog/how-to-avoid-catastrophic-backtracking-completely","author":"温铭","authorUrl":null,"authorAvatar":null,"publishedAt":"2020-12-16T16:00:00.435Z","media":[{"url":"https://static.apiseven.com/202108/v2-79b82522f7d06f0ae3c4ccc7aa6adc2d_1440w_2.jpg","type":"photo"},{"url":"https://static.apiseven.com/202108/v2-37843f350cfce190610379f54a665e00_1440w_2.jpg","type":"photo"},{"url":"https://static.apiseven.com/202108/v2-98eb63b55972c76d2257b7814b5a81ab_1440w_2.jpg","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"Envoy 与 Apache APISIX: filter 的另一种实现方式","url":"https://www.apiseven.com/blog/another-way-to-implement-envoy-filter","content":"Envoy 是由 lyft 开源的可编程边缘和和服务代理,并捐赠给CNCF基金会。在云原生时代,Envoy 被广泛地使用,在服务网格中,Istio、亚马逊 AWS App Mesh 等都使用Envoy作为默认数据面。
\\nEnvoy 是面向服务架构设计的L7代理和通信总线,核心是一个 L3/L4 网络代理。可插入 Filter 链机制允许开发人员编写 Filter 来执行不同的代理任务并将其插入到主体服务中。
\\n现有的 Filter 可能无法满足用户的个性化需求,这时候就需要对 Envoy 进行功能扩展,通过在现有的过滤链基础上自定义新的 Filter,实现定制化需求。\\n用户可以通过以下三种方式对 Envoy 进行扩展:
\\n\\n | Getting Started difficulty | \\nstability | \\ndevelopment efficiency | \\nDeploy and compile | \\n
---|---|---|---|---|
C++ | \\nhigh | \\nstable | \\nlow | \\nlong time to compile | \\n
Lua | \\nlow | \\nstable | \\nHigh | \\nno need to compile, deploy directly | \\n
WASM | \\nhigh-medium | \\non the fence | \\ndepends on language | \\ncompilation time depends on language | \\n
这种方式直接在 Envoy 基础上编写 C++ 代码进行功能增强,实现自定义的 filter 之后,重新编译新的二进制可执行文件,完成现有业务的升级替换。这种方式有以下两方面问题:
\\nLua 天生就是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能,被广泛应用。
\\nHTTP Lua Filter 允许在请求和响应流程中运行 Lua 脚本,目前支持的主要功能包括:对传输的请求或响应流,提供头部、正文和尾部的检查;对头部和尾部进行修改;对上游主机执行异步HTTP调用;直接执行响应并跳过后续的过滤器等。
\\n目前很多人配置中直接分发 Lua 代码,不利于代码组织管理,也难以与其他人共享形成生态。
\\n用户可以使用自己擅长的编程语言编写 filter,并使用工具编译成 WASM 格式,嵌入到 Envoy 中运行。
\\n它目前支持相对较少的语言,而且使用这些语言来扩展开发仍然不是那么简单。另一方面很多人对 WASM 仍然持保留态度,不会直接投入使用。
\\nApache APISIX 是一个动态、实时、高性能的 API 网关,基于 Nginx 网络库和 Lua 实现, 提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。\\n基于以上分析,我们可以看到 Lua 是很适合用来扩展 Envoy ,而且它简单易学,开发效率极高,因为嵌入到 Envoy 中,没有额外的网络等开销,性能表现不俗。\\nApache APISIX 基于 Lua 提出了自己的解决方案,那就是提供一个强大而灵活的基础库,实现将 Apache APISIX 的所有插件以及未来会开发的插件运行的 Envoy 上,用户也可以基于此基础库开发自己的个性化插件。
\\n具体的代码实现和运行请查看仓库:https://github.com/api7/envoy-apisix
\\n其中 Envoy 的主要配置如下:
\\n定义 Filter
\\nhttp_filters:\\n- name: entry.lua\\n typed_config:\\n \\"@type\\": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua\\n source_codes:\\n entry.lua:\\n filename: /apisix/entry.lua\\n
\\n对路由启用 Filter,并使用 metadata 进行配置
\\nroutes:\\n- match:\\n prefix: \\"/foo\\"\\n route:\\n cluster: web_service\\n typed_per_filter_config:\\n envoy.filters.http.lua:\\n \\"@type\\": type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute\\n name: entry.lua\\n metadata:\\n filter_metadata:\\n envoy.filters.http.lua:\\n plugins:\\n - name: uri-blocker\\n conf:\\n rejected_code: 403\\n block_rules:\\n - root.exe\\n - root.m+\\n
\\n我们无需对 Envoy 进行大幅修改,只需要进行部分优化。
\\n我们在插件层屏蔽平台差异,所有需要使用的接口都抽象在了底层框架,我们称之为 apisix.core ,这样所有插件就可以同时运行在 Envoy 和 Apache APISIX 上。
\\n我们以前面的示例来展示整个插件运行过程是怎么样的
\\n第一步,读取配置
\\n我们通过 metadata 进行配置,决定每个路由上需要运行什么插件,以及插件的配置是什么。
\\n示例中,我们对前缀为 /foo 的路由配置了 uri-blocker 插件以及它的 block 规则和需要 block 时响应的 status 。
\\n第二步,读取客户端请求数据
\\n我们进行了封装,将客户端请求数据统一封装到 ctx 中,以便在整个流程中都可以直接使用。
\\n第三步,运行插件
\\n我们通过匹配配置的规则和获取到的 uri 来确定是否需要 block 此次请求,如果需要 block ,则调用 respond 直接响应,否则放行。
\\n越来越多 APISIX 插件可以运行在 Envoy 上,最后实现在 Envoy 上运行 APISIX 所有及未来开发的所有插件。\\n同时,我们希望未来能与 Envoy 社区一起,在 Lua Filter 方向发力,优化和完善 Lua Filter ,增强 envoy 扩展能力,降低 Envoy 扩展难度。
\\n","description":"Envoy filter 现状 关于 Envoy\\n\\nEnvoy 是由 lyft 开源的可编程边缘和和服务代理,并捐赠给CNCF基金会。在云原生时代,Envoy 被广泛地使用,在服务网格中,Istio、亚马逊 AWS App Mesh 等都使用Envoy作为默认数据面。\\n\\nEnvoy Filter 机制\\n\\nEnvoy 是面向服务架构设计的L7代理和通信总线,核心是一个 L3/L4 网络代理。可插入 Filter 链机制允许开发人员编写 Filter 来执行不同的代理任务并将其插入到主体服务中。\\n\\n扩展方式\\n\\n现有的 Filter 可能无法满足用户的个性化需求…","guid":"https://www.apiseven.com/blog/another-way-to-implement-envoy-filter","author":null,"authorUrl":null,"authorAvatar":null,"publishedAt":"2020-12-15T16:00:00.080Z","media":[{"url":"https://static.apiseven.com/filters.png","type":"photo"},{"url":"https://static.apiseven.com/main.png","type":"photo"},{"url":"https://static.apiseven.com/workflow.png","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null},{"title":"如何在 Apache APISIX 上实现插件编排","url":"https://www.apiseven.com/blog/how-to-implement-plugin-orchestration-in-api-gateway","content":"Apache APISIX 和 Kong 都是开源的微服务 API 网关,那么在这两者之间,如何去做比较和选择呢?
\\n这两个项目都有完善的文档和测试来覆盖,也有不少的生产用户在使用,所以不用去担心稳定性和它们的可持续发展,本文会从功能和性能这两个最直接和可验证的角度去做下对比。
\\n从 API 网关核心功能点来看,两者均已覆盖:
\\n功能 | \\nApache APISIX | \\nKONG | \\n
---|---|---|
动态上游 | \\n支持 | \\n支持 | \\n
动态路由 | \\n支持 | \\n支持 | \\n
健康检查和熔断器 | \\n支持 | \\n支持 | \\n
动态 SSL 证书 | \\n支持 | \\n支持 | \\n
七层和四层代理 | \\n支持 | \\n支持 | \\n
分布式追踪 | \\n支持 | \\n支持 | \\n
自定义插件 | \\n支持 | \\n支持 | \\n
REST API | \\n支持 | \\n支持 | \\n
CLI | \\n支持 | \\n支持 | \\n
更详细的比较:
\\n功能 | \\nApache APISIX | \\nKONG | \\n
---|---|---|
项目归属 | \\nApache 软件基金会 | \\nKong Inc. | \\n
技术架构 | \\nNginx + etcd | \\nNginx + postgres | \\n
交流渠道 | \\n微信群、QQ 群、邮件列表、GitHub、meetup | \\nGitHub、论坛、freenode | \\n
单核 QPS (开启限流和 prometheus 插件) | \\n18000 | \\n1700 | \\n
平均延迟 | \\n0.2 毫秒 | \\n2 毫秒 | \\n
支持 Dubbo 代理 | \\n是 | \\n否 | \\n
配置回滚 | \\n是 | \\n否 | \\n
支持生命周期的路由 | \\n是 | \\n否 | \\n
插件热更新 | \\n是 | \\n否 | \\n
用户自定义:负载均衡算法、路由 | \\n是 | \\n否 | \\n
resty <--\x3e gRPC 转码 | \\n是 | \\n否 | \\n
支持 Tengine 作为运行时 | \\n是 | \\n否 | \\n
MQTT 协议支持 | \\n是 | \\n否 | \\n
配置生效时间 | \\n事件通知,低于 1 毫秒更新 | \\n定期轮询,5 秒 | \\n
自带控制台 | \\n是 | \\n否 | \\n
对接外部身份认证服务 | \\n是 | \\n否 | \\n
配置中心高可用(HA) | \\n是 | \\n否 | \\n
指定时间窗口的限速 | \\n是 | \\n否 | \\n
支持任何 Nginx 变量做路由条件 | \\n是 | \\n否 | \\n
在开启了 limit-count 和 prometheus 这两个插件后,Apache APISIX 的性能是 Kong 的十倍,\\n这里有比较详细的步骤,\\n感兴趣的开发者可以按图索骥,来进行验证。
\\n这里,我们讨论下功能和性能差异背后的原因:
\\nApache APISIX 的路由复杂度是 O(k),只和 uri 的长度有关,和路由数量无关;kong 的路由时间复杂度是 O(n),随着路由数量线性增长。
\\nApache APISIX 的 IP 匹配时间复杂度是 O(1),不会随着大量 IP 判断而导致 CPU 资源跑满。
\\nApache APISIX 的路由匹配,接受 Nginx 的所有变量作为条件,并且支持自定义函数;其他网关都是内置的几个条件。
\\nApache APISIX 使用 etcd 作为配置中心,没有单点,任意宕掉一台机器,网关集群还能正常运行。其他基于关系型数据库的网关都会有单点问题。
\\nApache APISIX 的配置下发只要 1 毫秒就能达到所有网关节点,使用的是 etcd 的 watch;其他网关是定期轮询数据库,一般需要 5 秒才能获取到最新配置。
\\nApache APISIX 的插件都经过精心调优,在高压力下依然保持毫秒级别延迟。
\\nApache APISIX 独有的插件编排和低代码功能,可以大大降低二次开发的门槛。
\\nApache APISIX 是一个很年轻的项目,2019 年 6 月份开源,7 月份加入到 CNCF 全景图,10 月份进入 Apache 孵化器,所以我会和大家分享一下 APISIX 是如何从 0 到 1,进入 Apache 孵化器的。
\\nApache APISIX 现在有 17 个 committer,分别来自 16 家不同的公司,是一个非常社区化的项目。每个 committer 有一票,决定版本的发布、选举新的 committer 和 PPMC 等比较重大的事情。
\\nApache Way 是大家都比较熟悉的概念:社区大于代码。烂代码可以改,Apache 的导师并不会指导你怎么写出更高水平的代码,他们更关心的是社区是否在健康的发展,只要有一个好的社区,烂代码一定会有更高水平的人进行重构,变成更好的代码。所以只要社区在,那这个项目就能够一直存活下去,这在 Apache 是最重要的。
\\n邮件列表优先是另一个重要的点,没有在邮件列表中出现过的,就当做不存在。这在中国其实是一个非常大的挑战,大家在文化上和习惯上都不太喜欢用邮件:第一是时间不够及时,可能发一封邮件后隔 1-2 天才能收到回复;第二是邮件列表的很多东西是公开的,有些人喜欢私聊;第三邮件列表里面只能出现英文,但其实中国人的英文是不差的,我们比大部分其他国家的人的英语已经好很多了,毕竟我们学了很多年英语,还有各种翻译的软件,即使出现语法错误,都不是大问题。
\\n第三是精英治理,在 Apache 社区中大家用贡献来获得更多的话语权,更高的 title 意味着更多的付出和责任。
\\n第四是民主,所有人都可以参与 Apache 的投票,即使你不在 Apache 社区,但不是所有人的票都是有效的。比如 APISIX 当时进 Apache 孵化器的时候需要投票,我也可以投支持票,但后面要写 no binding,表示我支持并关注这个项目,但我是一个观察员的身份,但这一票对于项目能否进 Apache 是没有决定性的。只有对孵化器做了贡献并得到社区认可的人,即 Apache 孵化器的 PMC,他们的票才是有效的,这就是 Apache 社区的民主。
\\n我们知道很多开源项目有一些是在基金会下面,有一些则不是。在基金会下面的项目,比如 Linux 基金会、Apache 基金会,他们的治理模式叫做“社区共识”,需要先在社区内讨论,在达成一个共识后进行投票,而非直接投票。如果直接投票,没有前面的讨论和共识,那这个投票是没有意义的。这个效率可能会很慢,但只有整个社区达成共识,后面才没有异议。
\\n第二种是商业公司共识,只要商业公司的人达成共识,那么这个 PR 或者 feature 就可以被合并,而社区的人说话是没有用的,因为它是被商业公司控制的一个项目,而如果你给商业公司贡献代码,能否被合并决定权在商业公司手里。这对于个人开发者可能无所谓,但是对于参与项目的企业则是有所谓的,通常企业会有私有版本,企业想把自己的 feature 贡献回社区,但商业公司可能因为这个东西和自己的商业版本冲突,就会拒绝掉。
\\n第三种是仁慈的独裁者,最典型的就是 Python,个人决定着开源项目的发展。
\\n上述是开源社区的三种模式,如果是企业选择项目,一般的我们会推荐 Apache、Linux 基金会的项目,它首先在法律上是没有隐患的,其次它是一个社区共识,我们可以通过向社区贡献这种方式获得更多的话语权,这样就形成了一个良性的循环。
\\nApache 现在有接近 50 个孵化器的项目,其中来自中国的有 10 个,APISIX 是现在国内唯一一个由创业公司进入 Apache 的项目,其他很多是来自华为、阿里、百度等大公司的项目。
\\n一个项目要想进入 Apache 孵化器,需要明白以下名词和步骤:
\\n国内的 Apache 项目会遇到很多不一样的挑战,这和国内外的开源环境和文化有关系。
\\n比如国内的工程师会觉得太忙,经常 996 加班,所以没有时间和精力去做开源。但其实不少工程师在工作中也会使用到开源项目,写过开源项目的 feature,但是他们并不会主动提交 PR,也不会在写代码之前在社区内发起讨论,这就是很多文化上不同的地方。
\\n沟通方式上,Apache 提倡的是在邮件列表中公开讨论,但是国内的很多开发者更喜欢微信、QQ、电话等非公开的方式来沟通。特别是如果一个项目的 PPMC 大都来自同一家公司,那么可能开早会的时候就把一个功能敲定了,但在邮件列表里也没有出现,这就不符合 Apache 的文化。
\\n关于投票,很多开发者可能觉得自己英语不好或者人微言轻,不太愿意在邮件列表中发表自己的意见,也不参与投票,那么最终他就会被忽略掉。所以你需要积累一些”功绩“,去帮助别人,慢慢地增加自己的影响力。Apache 是一个由个人组成的基金会,每个人的行为都只代表自己,不代表公司,每个PMC 的一票都是对等的。
\\n关于 Title,在 Apache 里,最高的职位叫做 Apache 基金会主席,每个项目的管理者是 VP,然后是 PMC(项目管理员会)、 Committer、 Contributor ,他有一个类似于我们企业内职称晋级的通道。但是在 Apache里,即使你的职位变得很高,也并不意味着拥有更多的投票权,更多的是义务,比如对于 Apache APISIX 选举新的 committer 的投票而言,孵化器主席的票和我的票是一样的。Title 在 Apache 里面更多的是一种荣誉,因为 Apache 基金会是一个非营利组织,它强调的是贡献,这就是文化上的冲突。
\\n版权是一个非常重要的问题。一个项目在正式加入 Apache 孵化器之前,所有 committer 和公司都要签署 CLA,说明将这个项目的版权,全部捐给 Apache 基金会。加入 Apache 孵化器之后,最重要的里程碑就是发布第一个 Apache 的 Release,这个版本就是要理清 license 上的风险,让用户可以放心的使用。所以,商业公司使用 Apache 的项目是有保障的,不会涉及到版权不清晰的问题。
\\n最后,Apache APISIX 是一个正在快速发展的开源项目,希望大家多多参与和贡献。
\\n","description":"Apache APISIX 是一个很年轻的项目,2019 年 6 月份开源,7 月份加入到 CNCF 全景图,10 月份进入 Apache 孵化器,所以我会和大家分享一下 APISIX 是如何从 0 到 1,进入 Apache 孵化器的。 Apache APISIX 现在有 17 个 committer,分别来自 16 家不同的公司,是一个非常社区化的项目。每个 committer 有一票,决定版本的发布、选举新的 committer 和 PPMC 等比较重大的事情。\\n\\nApache Way\\n\\nApache Way 是大家都比较熟悉的概念:社区大于代码…","guid":"https://www.apiseven.com/blog/from-0-to-1-the-apache-way-of-apache-apisix","author":"温铭","authorUrl":null,"authorAvatar":null,"publishedAt":"2019-12-25T16:00:00.466Z","media":null,"categories":null,"attachments":null,"extra":null,"language":null},{"title":"对 wrk 延迟分布不准确的分析","url":"https://www.apiseven.com/blog/analysis-of-inaccurate-distribution-of-wrk-latency","content":"题图:Photo by Snapwire from Pexels
\\nwrk 是一个非常棒的 HTTP 压力测试工具,构建在 Redis、NGINX、Node.js 和 LuaJIT 这几个开源项目的基础之上,充分利用了他们在事件驱动、HTTP 解析、高性能和灵活性方面的优点,并且可以自己写 Lua 脚本来生成测试请求。
\\n虽然 wrk 没有测试案例,并且作者大概一年现身一次来合并代码,但这些并不妨碍我们把 wrk 作为性能测试和 fuzz 测试的首选工具。如果你还在使用多线程的 ab,那么非常值得尝试下 wrk。
\\n下面是 wrk 结果中的延时分布统计部分:
\\nLatency Distribution\\n 50% 1.20ms\\n 75% 595.78ms\\n 90% 899.11ms\\n 99% 1.00s\\n
\\n这个示例是指,50% 的请求在 1.2ms 内完成,90% 的请求在 899 ms 内完成,99% 的请求在 1s 内完成。
\\n我们在使用 wrk 压力测试自己产品的时候,发现 wrk 统计的延时结果中,大部分请求都是几毫秒内完成,但有一小部分请求的延时会超过 100 毫秒。 对于用 OpenResty 构建的系统,出现这么大的延时是不太科学的事情。
\\n虽然这个问题最终解决方法非常简单,但具体的分析和定位有些曲折,花了好几天的时间。最终的解决方法并不重要,过程和思考问题的方式才是值得关注的。
\\n遇到延迟问题,我们的第一反应是代码或者系统某个地方有阻塞。 由于系统比较复杂,所以我们祭出了火焰图。
\\n没有现成的 systemtap 脚本来分析这类问题,所以花了点时间写脚本。但调整了几次 systemtap 脚本,都没有捕获到明显的延时,这个和 wrk 的结果明显不符。我们猜测这个脚本可能不够完善,可能遗漏了某些函数没有 hook 住。但同时也对 wrk 的结果是否正确产生了怀疑。
\\n我们调转方向,先来定位到底是 wrk 统计错了,还是确实是 server 的问题。我们在 wrk 所在的服务器上,把压测期间的包都 dump 出来,按照耗时进行排序,惊奇的发现结果和 wrk 的延时统计大相径庭,没有发现超过 100 毫秒的请求。重复了几次以上测试,结果都一致。
\\n这下目标就很明确了,只要把 wrk 关于延迟统计的代码捋顺就可以了。最担心的就是 wrk 内部统计时候有 bug,这就不好修复了,毕竟是一个没有任何测试案例的项目。
\\n我们仔细过了一遍 wrk 的统计逻辑,并在开始和结束的地方加了日志,发现关于延时的统计都是正确的,这也让我们松了一口气。但是在打印最终结果之前,有一段统计数据校正
的代码:
if (complete / cfg.connections > 0) {\\n int64_t interval = runtime_us / (complete / cfg.connections);\\n stats_correct(statistics.latency, interval);\\n}\\n
\\n按照这个 if 判断,只要有压测数据产生,就会进行校正。有兴趣的同学,可以去看看 stats_correct
函数的代码,只有 10 行,我看了几遍也没看懂。
再去查代码的提交记录,说不定有什么收获,但只有下面这一行,又没看懂:
\\nremove calibration & improve CO correction\\n
\\n吐槽下,如果提交记录稍微详细一点儿,不用缩写,或者加个代码注释,就能省不少事儿。
\\n问题查到这里,已经可以证实不是产品的问题,而且解决方法已经有了,就是注释掉上面这段校正的代码。但 wrk 作者特意加上肯定是有原因的,不明白这个原因始终是个隐患。自然的,要开一个 issue 来请教下作者,一年现身一次的 wg 在 15 天后给了答复,原来上面 commit info 里面的缩写 CO
是指 Coordinated Omission
,并且给了一篇专门讲这个问题的文章,感兴趣的同学可以用这个关键字自行搜索。
简单的说,Coordinated Omission
是指在做压力测试的时候,只统计发送和收到回复之间的时间是不够的,这个是指服务时间
,会遗漏掉很多潜在的问题,还需要把测试请求的等待时间也计算在内,才算是用户关心的响应时间
。
提出 CO 这个问题的 Gil Tene,还对 wrk 做了修改,专门解决 CO 的问题: https://github.com/giltene/wrk2,在这个项目的 README 里面也有一些对此的解释,有兴趣的可以看看,这里就不多提及了。
\\n对于我们自己的产品来说,代码中肯定不会有任何阻塞,在做压力测试的时候,是会把 CPU 跑满。即使出现阻塞,也是有火焰图来采样分析的。所以 wrk 这里针对 Coordinated Omission 做的简单粗暴的校正,反而会产生误导。
\\n","description":"题图:Photo by Snapwire from Pexels wrk 是一个非常棒的 HTTP 压力测试工具,构建在 Redis、NGINX、Node.js 和 LuaJIT 这几个开源项目的基础之上,充分利用了他们在事件驱动、HTTP 解析、高性能和灵活性方面的优点,并且可以自己写 Lua 脚本来生成测试请求。\\n\\n虽然 wrk 没有测试案例,并且作者大概一年现身一次来合并代码,但这些并不妨碍我们把 wrk 作为性能测试和 fuzz 测试的首选工具。如果你还在使用多线程的 ab,那么非常值得尝试下 wrk。\\n\\n下面是 wrk 结果中的延时分布统计部分…","guid":"https://www.apiseven.com/blog/analysis-of-inaccurate-distribution-of-wrk-latency","author":"温铭","authorUrl":null,"authorAvatar":null,"publishedAt":"2018-09-02T16:00:00.973Z","media":[{"url":"https://static.apiseven.com/202108/v2-596a56dceaf120f846ce07484e4c091b_1440w_2.jpg","type":"photo"}],"categories":null,"attachments":null,"extra":null,"language":null}],"readCount":2,"subscriptionCount":4,"analytics":{"feedId":"62295715074255930","updatesPerWeek":0,"subscriptionCount":4,"latestEntryPublishedAt":null,"view":0}}')