在代码同步下,将ip写入.env,实现动态服务注册

一、问题描述

在实际工作中,一个商品微服务下面可能挂着多个商品服务器,每个商品服务器里的商品服务代码是相同的。

但是这样一来,如果进行服务注册,那就意味着每一个商品服务器注册的都是同一个ip和端口号,因为代码是完全一致的。

这个问题在git、svn中都会存在。

 

二、解决思路

1、在.env文件中手动添加两个常量【不推荐】

在非共享目录手动创建.env文件,在里面创建一个标识IP和端口号的两个常量。

该方式的缺点在于没有实现自动化,如果水平扩容,还得每台服务器挨个修改.env

2、获取主机IP,然后把ip写入.env【推荐】

第二种方式是通过某种方式,获取到主机的ip,再把该ip写入.env,然后让swoft加载该.env文件

该方式的优点是实现了自动化,即使水平扩容,也不必再去挨个服务器的修改.env

 

三、解决方案

这里第一种解决方案不必多说,只说第二种方案如何实现。

1、获取到服务器IP值
# 执行命令即可获取
ifconfig | grep 172.22 | awk '{print $2}'
root@00f304bcbc83:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.22.22.110  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe16:166e  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ac:16:16:6e  txqueuelen 0  (Ethernet)
        RX packets 4136  bytes 724809 (707.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 62  bytes 6333 (6.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@00f304bcbc83:/# ifconfig | grep 172.22 | awk '{print $2}'
172.22.22.110
2、编写一个sh脚本,定时将获取到的值写入.env
docker exec -it swoft_110 bash
cd /var/www/swoft/
vi generate_ip.sh

#! /bin/sh
host=`ifconfig | grep 172.22 | awk '{print $2}'`

content="HOST="$host

echo $content >> /var/www/.env

因为我们设置了三个swoft的代码都在/var/www/swoft下,所以我们为了避免每一个swoft下的ip一样,应该把.env放在上一层目录。

当然,在生产环境不用如此,因为生产环境是通过同步代码的方式保证业务代码的相同,但.env不在同步代码的范畴内,所以在生产环境中不用将.env放到其他目录,直接放到根目录即可。

注:一个>时,内容是会覆盖原文件的,而两个>时,内容会在原文件内容基础上进行追加,这里采用的是追加

3、执行该脚本,在该容器内生成一个.env
cd /var/www/swoft/
sh ./generate_ip.sh

注:该操作在其他两个swoft容器内也要执行

4、让swoft加载该.env

修改bin/swoft文件,将(new \App\Application())->run(); 修改为

$app = new \App\Application();
$app->setEnvFile('/var/www/.env');
$app->run();
5、验证是否加载成功

在app/Listener/RegisterServiceListener.php文件中的handle方法中添加一行代码:

echo env('HOST').PHP_EOL;

然后执行 ./bin/swoft rpc:start 启动rpc服务,正常应该有输出IP地址,说明成功。

     ____            _____    ____                                   __     ___   ___
    / __/    _____  / _/ /_  / __/______ ___ _  ___ _    _____  ____/ /__  |_  | / _ \
   _\ \| |/|/ / _ \/ _/ __/ / _// __/ _ `/  ' \/ -_) |/|/ / _ \/ __/  '_/ / __/_/ // /
  /___/|__,__/\___/_/ \__/ /_/ /_/  \_,_/_/_/_/\__/|__,__/\___/_/ /_/\_\ /____(_)___/

                 SERVER INFORMATION(v2.0.10)
  **************************************************************
  * RPC      | Listen: 0.0.0.0:18308, Mode: Process, Worker: 2
  **************************************************************

RPC Server Start Success!
2021/09/09-19:41:35 [INFO] Swoft\Server\Server:startSwoole(499) Swoole\Runtime::enableCoroutine
2021/09/09-19:41:35 [INFO] Swoft\Listener\BeforeStartListener:handle(35) Server extra info: pidFile @runtime/swoft-rpc.pid
2021/09/09-19:41:35 [INFO] Swoft\Listener\BeforeStartListener:handle(36) Registered swoole events:
 start, shutdown, managerStart, managerStop, workerStart, workerStop, workerError, connect, close, receive
哈哈哈Swoft rpc register service success by consul哈哈哈!
172.22.22.110
Server start success (Master PID: 200, Manager PID: 207)

可以看到,已经成功输出了172.22.22.110,说明我们加载.env文件成功了。

6、温馨提示

不要忘记把我们临时校验的代码删除了哦( ̄3 ̄)a

# app/Listener/RegisterServiceListener.php中的handle方法
echo env('HOST').PHP_EOL;