Categories
php

php artisan tinker

今天,我们将通过介绍 Laravel 中一个不太为人所知的功能,来展示如何快捷的调试数据库中的数据。通过使用 Laravel artisan 内建的 php artisan tinker, 我们可以很方便的看到数据库中的数据并且执行各种想要的操作。

Laravel artisan 的 tinker 是一个 REPL (read-eval-print-loop),REPL 是指交互式命令行界面,它可以让你输入一段代码去执行,并把执行结果直接打印到命令行界面里。

// see the count of all users
App\User::count();

// find a specific user and see their attributes
App\User::where('username', 'samuel')->first();

// find the relationships of a user
$user = App\User::with('posts')->first();
$user->posts;
factory(App\User::class, 10)->create();
App\User::all();
App\User::count();
$user = new App\User;
$user->name = "Wruce Bayne";
$user->email = "iambatman@savegotham.com";
$user->save();
doc XXX

查阅某个方法的文档

show XXX

显示某个方法的代码

Categories
php

laravel Form magic 方法

laravel 的form 对象 有magic方法 可以快速添加表单项

/**
 * Class Form.
 *
 * @method Field\Text           text($name, $label = '')
 * @method Field\Password       password($name, $label = '')
 * @method Field\Checkbox       checkbox($name, $label = '')
 * @method Field\CheckboxButton checkboxButton($name, $label = '')
 * @method Field\CheckboxCard   checkboxCard($name, $label = '')
 * @method Field\Radio          radio($name, $label = '')
 * @method Field\RadioButton    radioButton($name, $label = '')
 * @method Field\RadioCard      radioCard($name, $label = '')
 * @method Field\Select         select($name, $label = '')
 * @method Field\MultipleSelect multipleSelect($name, $label = '')
 * @method Field\Textarea       textarea($name, $label = '')
 * @method Field\Hidden         hidden($name, $label = '')
 * @method Field\Id             id($name, $label = '')
 * @method Field\Ip             ip($name, $label = '')
 * @method Field\Url            url($name, $label = '')
 * @method Field\Color          color($name, $label = '')
 * @method Field\Email          email($name, $label = '')
 * @method Field\Mobile         mobile($name, $label = '')
 * @method Field\Slider         slider($name, $label = '')
 * @method Field\File           file($name, $label = '')
 * @method Field\Image          image($name, $label = '')
 * @method Field\Date           date($name, $label = '')
 * @method Field\Datetime       datetime($name, $label = '')
 * @method Field\Time           time($name, $label = '')
 * @method Field\Year           year($column, $label = '')
 * @method Field\Month          month($column, $label = '')
 * @method Field\DateRange      dateRange($start, $end, $label = '')
 * @method Field\DateTimeRange  dateTimeRange($start, $end, $label = '')
 * @method Field\TimeRange      timeRange($start, $end, $label = '')
 * @method Field\Number         number($name, $label = '')
 * @method Field\Currency       currency($name, $label = '')
 * @method Field\SwitchField    switch($name, $label = '')
 * @method Field\Display        display($name, $label = '')
 * @method Field\Rate           rate($name, $label = '')
 * @method Field\Divider        divider($title = '')
 * @method Field\Decimal        decimal($column, $label = '')
 * @method Field\Html           html($html)
 * @method Field\Tags           tags($column, $label = '')
 * @method Field\Icon           icon($column, $label = '')
 * @method Field\Captcha        captcha($column, $label = '')
 * @method Field\Listbox        listbox($column, $label = '')
 * @method Field\Table          table($column, $label, $builder)
 * @method Field\Timezone       timezone($column, $label = '')
 * @method Field\KeyValue       keyValue($column, $label = '')
 * @method Field\ListField      list($column, $label = '')
 * @method mixed                handle(Request $request)
 */

真实调用的方法

 /**
     * Generate a Field object and add to form builder if Field exists.
     *
     * @param string $method
     * @param array  $arguments
     *
     * @return Field|$this
     */
    public function __call($method, $arguments)
    {
        if (!$this->hasField($method)) {
            return $this;
        }

        $class = BaseForm::$availableFields[$method];

        $field = new $class(Arr::get($arguments, 0), array_slice($arguments, 1));

        return tap($field, function ($field) {
            $this->pushField($field);
        });
    }
Categories
php

php __call

__call 属于php 类对象的magic 方法

当调用一个不存在与类定义的方法 就会 在call中调用

 function __call($name,$arguments) {  

 }

$name 为方法名字

$argument 为方法参数

Categories
java

DiscoverClient ribbon Feign 服务发现与调用

服务发现是 服务治理的一个很重要的点

所有注册在服务平台的微服务 必须要能被发现 然后调用

而我们调用其他服务一般有三种方法

DiscoverClient ribbon Feign

DiscoverClient 是更加低层的方法 当DiscoverClient 需要寻找服务时 其实是向服务注册器(例如 eureka) 发送 http 请求获取躯体服务信息 包括 ip port 等

@SpringBootApplication
@EnableDiscoveryClient
class Application {

    @Autowired
    DiscoveryClient discoveryClient
}

添加了注解@EnableDiscoveryClient

然后就能自动 注入 discoverClient

 @Autowired
 DiscoveryClient discoveryClient


 def restTemplate = new RestTemplate()
 def serverList = discoveryClient.getInstances("ROBIN-ADMIN")
 println(serverList)
        restTemplate.getForObject("${serverList[0].getUri()}/api/ribbon",Map.class)

获取到discoverClient 就能通过 服务名字 查找服务实例 并且通过RestTemplate 调用服务接口了

Ribbon是调用了 discoverClient 调用服务的 但是他提供了 负载均衡功能,不显式调用某个服务实例 而是通过策略调用某类服务的其中一个 达到负载均衡效果


@SpringBootApplication
class RibbonApplication {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate()
    }
}

在注册RestTemplate对象时 添加LoadBalanced 注解

LoadBalanced 会自动实例化restTemplate 的服务均衡策略 具体查看LoadBalance接口 会定时ping各个服务实例 也会用譬如 回环轮询策略 寻找服务实例

当restTemplate 调用服务时 通过策略调用服务实例

restTemplate.getForObject("http://ROBIN-ADMIN/api/health",Map.class)

ROBIN-ADMIN 为某类服务的服务ID

Feign 是更加接近业务的服务调用方式

maven 添加依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

添加Feign注解

@EnableFeignClients
class RibbonApplication {

}

新建接口对象

package org.robin.ribbon.feign

import org.springframework.cloud.openfeign.FeignClient
import org.springframework.web.bind.annotation.RequestMapping

@FeignClient("ROBIN-ADMIN")
interface RobinAdminService {

    @RequestMapping("/api/ribbon")
    Map ribbon()


    @RequestMapping("/api/health")
    Map health()

}

spring会自动生成 RobinAdminService

调用该对象的方法 可以 调用对应微服务的接口

Categories
php

DB Facade

使用laravel 的数据库Facade 可以比较好的 执行数据库sql

$array = DB::select("select * from admin_users");
//raw 执行sql      

$object = DB::table("admin_users")->where("id","=","1")->first();
//获取查询第一条

$array = DB::table("admin_users")->where("id","=","1")->get();
//
get获取数据列表
       
$array = DB::table("admin_users")->where("id","=","1")->skip(0)->take(1)->get();
//分页查询

$array = DB::table("admin_users")->where("id","=","1")->skip(0)->limit(1)->get();
//分页查询

DB::transaction(function (){
           //内部执行开启事务
});

//手动控制事务
DB::beginTransaction();
DB::commit();
DB::rollBack();
Categories
java

eureka

作为微服务服务注册供应方

默认在本机 http://localhost:8761/eureka/提供服务

注册请求地址在 apps/{service-name} POST 发送本机服务信息

注销请求地址在 apps/{service-name}/{id} DELETE 发送请求

心跳请求地址在 apps/{service-name}/{id} PUT 发送请求

状态请求地址在 apps/{service-name}/{id}/status PUT 发送请求

删除状态请求地址在 apps/{service-name}/{id}/status DELETE 发送请求

Categories
php

php reactive socket

php socket 第三方库 composer require react/socket

该库针对 socket / 流 做事件监听(应该是epoll )主线程做事件循环 (reactive)所以该reactive 框架貌似只能在 linux下使用

server

<?php

require '../vendor/autoload.php';

echo "enter script\n";

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server('127.0.0.1:8080', $loop);

$socket->on('connection', function (React\Socket\ConnectionInterface $connection) {
    echo "" . $connection->getRemoteAddress() . "client connected\n";
    $connection->write("Hello " . $connection->getRemoteAddress() . "!\n");
    $connection->write("Welcome to this amazing server!\n");
    $connection->write("Here's a tip: don't say anything.\n");

    $connection->on('data', function ($data) use ($connection) {
        echo "" . $data . "\n";
        //$connection->close();
    });
});

echo "server started at 8080\n";

$loop->run();

其中$loop 就是事件循环对象

client

<?php

require '../vendor/autoload.php';


$loop = React\EventLoop\Factory::create();
$connector = new React\Socket\Connector($loop);

$connector->connect('127.0.0.1:8080')->then(function (React\Socket\ConnectionInterface $connection) use ($loop) {
    echo "client connected\n";
    $connection->write("Hello World!\n");
    $connection->on('data', function ($data) use ($loop, $connection) {
        echo "" . $data . "\n";
        //$connection->close();
        //$output = new React\Stream\WritableResourceStream(fopen("./client.txt", "w"),$loop);
        //$output = fopen("./client.txt", "w");
        //fwrite($output,$data);
        //$output->write("" . $data . "\n");
        while($input = fgets(STDIN, 10))
        {
            echo $input."\n";
            $connection->write($input);

        }
    });
    /*
    $input = new React\Stream\ReadableResourceStream(STDIN,$loop);
    $input->on("data",function ($data) use ($connection) {
       $connection->write($data);
    });*/
    //$output = fopen("./client.txt", "w");
    //$steam = new React\Stream\WritableResourceStream($output,$loop);
    //$connection->pipe($steam);



});

$loop->run();

最亮眼的是 将文件描述符(标准输出流 文件输出流)fd 包装成一个响应式流对象 通过pipe实现管道功能 而且生命周期相同 会同时关闭。

Categories
php

composer 设置aliyun源

composer设置阿里云镜像源

  1. 首先把默认的源给禁用掉

composer config -g secure-http false
 

  1. 再修改镜像源 这里我使用阿里的源

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

  1. 修改成功后可以先查看一下配置

composer config -g -l
 

  1. 第二行repositories.packagist.org.url 如果是阿里的就代表成功

composer config -g -l
[repositories.packagist.org.type] composer
[repositories.packagist.org.url] https://mirrors.aliyun.com/composer/

Categories
java

hytrix

断路器 用作监控请求 是否合理 当出现异常流量 可以短路保护

具体使用方式通过切面编程 将需要监控的方法 包括controller service dao 的方法添加注解方式

然后当执行该方法时 会先进去hystrix定义的监控线程上

异步执行需监控的方法 并注册一个超时事件在 监控线程上

所以被HystrixCommand 注解的方法其实是异步执行的

思考 是否应该在网关应用上 添加hystrix 做断路器限流

的确是应该如此这样做

Categories
php

laravel 入口

php 通过 symfony/http-foundation(http请求响应封装) 框架捕获http请求

laravel kernel 类 为laravel http 入口

middleware 类似于 过滤器 可以执行请求处理 然后next 执行处理链 必定有 handle 方法 当需要处理请求前操作 在调用 $next 前修改请求信息 当需要处理请求后 或者 在响应上操作 则 在$next后 修改信息 且返回结果必定为 $response对象

public function handle($request, Closure $next)
    {
        // Check if we're dealing with CORS and if we should handle it
        if (! $this->shouldRun($request)) {
            return $next($request);
        }

        // For Preflight, return the Preflight response
        if ($this->cors->isPreflightRequest($request)) {
            $response = $this->cors->handlePreflightRequest($request);

            $this->cors->varyHeader($response, 'Access-Control-Request-Method');

            return $response;
        }

        // Add the headers on the Request Handled event as fallback in case of exceptions
        if (class_exists(RequestHandled::class) && $this->container->bound('events')) {
            $this->container->make('events')->listen(RequestHandled::class, function (RequestHandled $event) {
                $this->addHeaders($event->request, $event->response);
            });
        }

        // Handle the request
        $response = $next($request);

        if ($request->getMethod() === 'OPTIONS') {
            $this->cors->varyHeader($response, 'Access-Control-Request-Method');
        }

        return $this->addHeaders($request, $response);
    }