应用间内网调用

服务说明

新浪云提供了代理服务用于应用间彼此调用,默认情况下,应用可以从内网调用本账号下的其他应用或者访问授权的其他账户的应用。

从内网调用时需要构造特殊的应用URL,且需要按以下的规则在发送的header头中携带签名。

应用内网域名访问组成规则

访问内网的域名规则如下:

http://[appversion.]appname.intra.applinzi.com/URI

其中:

  • http://: 用于内网调用仅支持HTTP,不支持HTTPS,请注意
  • appversion: 待访问的应用的版本,可以不包含这部分,不包含表示访问默认的版本,例如1
  • appname: 待访问的应用的应用名,例如www
  • intra: 不能修改,固定在应用名部分后面
  • applinzi.com: 应用可用的二级域名后缀,可以修改为应用能使用的任意二级域名后缀,例如appchizi.com
  • URI: 访问的路径,例如/a/b.php

签名规则及认证头

需要拿当前访问应用的AccessKeySecretKey和当前的时间戳拼接后计算md5放到请求的header头中的Signature字段。

签名的伪代码如下:

timestamp = '1999-01-02 01:02:03';
待签名的串 = "ACCESSKEY" . 应用的AccessKey . "TIMESTAMP" . timestamp . 应用的SecretKey;
待发送签名 = md5(待签名的串)

需要发送的认证头如下:

  • TimeStamp: 时间戳,格式为:1999-01-02 01:02:03
  • AccessKey: 发起调用的应用的AccessKey
  • Signature: 上面计算得到的签名
  • Appname: 发起调用的应用名称

PHP计算的代码如下:

<?php
$appname = '当前应用名';
$ak = '当前应用的accesskey';
$sk = '当前应用的secretkey';
$timestamp = date('Y-m-d H:i:s');
$content = "ACCESSKEY" . $ak . "TIMESTAMP" . $timestamp . $sk;
$headers = array(
    "TimeStamp: $timestamp",
    "AccessKey: " . $ak,
    "Signature: " . md5($content),
    "Appname: " . $appname
);

PHP标准环境下调用示例

在应用death的版本1根目录下有一个json.php文件,内容如下:

<?php
$val = array(
    'a' => 1,
    'b' => 'hha'
);
echo(json_encode($val));

可以从同账户下的gequ应用下通过内部请求服务调用这个接口,调用代码如下:

<?php
$fetch_instance = new SaeFetchInternal();
// 设置需要抓取的应用
$fetch_instance->setAppname('death');;
// 设置使用的域名后缀,默认为applinzi.com
$fetch_instance->setDomain('sinaapp.com');
// 设置请求超时时间,单位秒
$fetch_instance->setTimeout(5);

// 发送GET请求
$ret = $fetch_instance->get("/json.php?a=1");
var_dump($ret);
var_dump($fetch_instance->errno(), $fetch_instance->errmsg(), $fetch_instance->curlInfo(), $fetch_instance->getOutHeaders());

返回结果如下:


string(17) "{"a":1,"b":"hha"}"
int(0)
string(2) "OK"
array(26) {
  ["url"]=>
  string(43) "http://death.intra.sinaapp.com/json.php?a=1"
  ["content_type"]=>
  string(24) "text/html; charset=UTF-8"
  ["http_code"]=>
  int(200)
  ["header_size"]=>
  int(171)
  ["request_size"]=>
  int(192)
  ["filetime"]=>
  int(-1)
  ["ssl_verify_result"]=>
  int(0)
  ["redirect_count"]=>
  int(0)
  ["total_time"]=>
  float(0.031909)
  ["namelookup_time"]=>
  float(0.005648)
  ["connect_time"]=>
  float(0.006063)
  ["pretransfer_time"]=>
  float(0.006066)
  ["size_upload"]=>
  float(0)
  ["size_download"]=>
  float(17)
  ["speed_download"]=>
  float(532)
  ["speed_upload"]=>
  float(0)
  ["download_content_length"]=>
  float(-1)
  ["upload_content_length"]=>
  float(0)
  ["starttransfer_time"]=>
  float(0.031864)
  ["redirect_time"]=>
  float(0)
  ["redirect_url"]=>
  string(0) ""
  ["primary_ip"]=>
  string(13) "172.16.100.17"
  ["certinfo"]=>
  array(0) {
  }
  ["primary_port"]=>
  int(81)
  ["local_ip"]=>
  string(12) "172.16.100.8"
  ["local_port"]=>
  int(40046)
}
array(6) {
  ["server"]=>
  string(5) "nginx"
  ["date"]=>
  string(29) "Wed, 19 Jun 2019 11:35:44 GMT"
  ["content-type"]=>
  string(24) "text/html; charset=UTF-8"
  ["transfer-encoding"]=>
  string(7) "chunked"
  ["connection"]=>
  string(5) "close"
  ["via"]=>
  string(6) "100142"
}

其中:

  • $fetch_instance->errno() 查看调用后返回的错误码,如果是非0表示出错了
  • $fetch_instance->errmsg() 查看调用后返回的具体错误信息
  • $fetch_instance->curlInfo() 查看curl_getinfo 获取的信息
  • $fetch_instance->getOutHeaders() 查看调用后接口返回的header信息

除了发起get请求外,还支持postdeleteheadput请求,具体请参考类的说明文档:http://apidoc.sinaapp.com/class-SaeFetchInternal.html

跨账户应用授权

当前,应用不支持跨应用调用,直接调用时会返回no access错误,错误码是701。如果需要从内网调用其他账户的应用,需要进行应用授权。

进入云应用的应用管理中心,选择左侧“应用设置”-“跨应用授权”,给发起调用的应用增加授权即可,如图:

跨应用授权

应用设置为仅限内网访问

以PHP标准环境为例,通过config.yaml中配置:

handle:
- hostaccess:  if(path ~ "/") allow "10.0.0.0/8 172.16.0.0/16 192.168.0.0/16"

配置所有的请求只允许内网CIDR即可,从浏览器直接访问应用的地址会出现403错误:

Forbidden
You don't have permission to access /json.php on this server.

从内部调用服务不受影响。

应用场景

通过设置应用只为内网服务,配合应用跨账户的天然隔离,可以将不同的组件拆分到不同的应用中,实现业务逻辑的解耦合,实现“微服务”化。