php面试题九 -- 常见问题

臭大佬 2021-02-26 22:29:27 400
php 
简介 php面试题九

你用什么方法检查 PHP 脚本的执行效率(通常是脚本执行时间)和数据库 SQL 的效率(通常是数据库 Query 时间), 并定位和分析脚本执行和数据库查询的瓶颈所在?

数据库SQL的效率

sqlexplain(sql),启用slow_query_log记录慢查询。通常还要看数据库设计是否合理,需求是否合理等。
慢查询相关文章MYSQL 慢查询 | 臭大佬

PHP一般是在要检查的代码开头记录一个时间,结尾记录一个时间。取差值。

但这个时间一般来说都很快,在一秒以内,所以不能直接用mktime()

<?php

/**
 * 返回当前 Unix 时间戳的微秒数
 */
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$time_start = microtime_float();
// 这里放你要检查的代码 --开始
$product = 1;
foreach (range(1, 5) as $val) {
    sleep(1);
    $product = $product * $val;
}
// 这里放你要检查的代码 -- 结束
$time_end = microtime_float();
$time = $time_end - $time_start;
echo "以上代码块执行时间是: $time 秒\n";

前后端分离情况下,前端在a.com下向b.com请求接口,后端如何解决前端跨域问题

跨域请求

当一台服务器资源从另一台服务器(不同 的域名或者端口)请求一个资源或者接口,就会发起一个跨域 HTTP 请求。举个简单的例子,从http://a.com/index.html, 发送一个 Ajax 请求,请求地址是 http://b.com/ 下面的一个接口,这就是发起了一个跨域请求。在不做任何处理的情况下,这个跨域请求是无法被成功请求的,因为浏览器基于同源策略 会对跨域请求做一定的限制。

同源策略

一个域名请求地址的组成是:协议+域名+端口号+请求资源地址 , 当协议、域名、端口号中任意一个不相同时 , 都算作不同源(必须是域名完全相同,比如说 a.example.comb.example.com 这两个域名。虽然它们的顶级域名和二级域名(均为 example.com)都相同,但是三级域名(a 和 b)不相同,所以也不能算作域名相同)。如果不同时满足这上面三个条件,那就不符合浏览器的同源策略。

解决方式一:php代码加header头
<?php
header('Access-Control-Allow-Origin:http://www.a.com');
解决方式二:nginx反向代理

通过nginx配置一个代理服务器(域名与a.com相同,端口不同)做跳板机,反向代理访问b.com接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

// proxy服务器
server {
    listen       81;
    server_name  www.a.com;
    location / {
        proxy_pass   http://www.b.com:8080;  #反向代理
        proxy_cookie_domain www.b.com www.a.com; #修改cookie里域名
        index  index.html index.htm;

        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.a.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}

多个网站域名,(www.a.com,www.b.com,www.c.com),在www.a.com登录,如何保证www.b.com和www.c.com也能同时登录,你的方案是什么

方案一:单点登录

具体流程如下:

用户访问app系统,app系统是需要登录的,但用户现在没有登录。
跳转到CAS server,即SSO登录系统,以后图中的CAS Server我们统一叫做SSO系统。 SSO系统也没有登录,弹出用户登录页。
用户填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器(Browser)中写入SSO域下的Cookie。
SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
验证通过后,app系统将登录状态写入session并设置app域下的Cookie。

至此,跨域单点登录就完成了。以后我们再访问app系统时,app就是登录的。接下来,我们再看看访问app2系统时的流程。

用户访问app2系统,app2系统没有登录,跳转到SSO。
由于SSO已经登录了,不需要重新登录认证。
SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
app2拿到ST,后台访问SSO,验证ST是否有效。
验证成功后,app2将登录状态写入session,并在app2域下写入Cookie。

方案二:nginx代理

用nginx代理,可以共用同一个cookie从而实现。
不同的端口所保存的cookie是不能通用的,只有通过nginx代理。原理就是当三个服务端口为8080,8081,8082,而配置nginx端口为88;看配置

server {
        listen       88;
        server_name  localhost;
        location /server2/{
            proxy_pass   http://127.0.0.1:8082/server2/;
        } 
        location /server1/ {
            proxy_pass   http://127.0.0.1:8081/server1/;
        }
         location /server/ {
            proxy_pass   http://127.0.0.1:8080/server/;
        }
    }

需要注意的是localhost后面需要固定服务的地址前缀,这样访问时可以直接访问:http://127.0.0.1:88/servce1/login.html, 这样就能直接访问到端口为8081的服务。
在附上nginx解决跨域问题的配置

http {
    include       mime.types;
    default_type  application/octet-stream;

    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Headers X-Requested-With;
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

    }
扩展 同域下的单点登录 — 共享session

说到单点登录,还有一种是同域名下的情况,这种情况下,抓住一个点,我们在设置Cookie时,只能设置顶域和自己的域,不能设置其他的域。,可以将Cookie的域设置为顶域,Cookie的问题解决了,

将用户信息,存储在redis中将key作为数据返回页面时,放到cookie中,只要cookie中有key,后续访问逻辑www.xxx.com系统时,都会携带这个key,从而可以处理获取redis的数据使用.