首页
在线工具
搜索
1
使用Metrics指标度量工具监控Java应用程序性能(Gauges, Counters, Histograms, Meters和 Timers实例)
2
如何将Virtualbox和VMware虚拟机相互转换
3
Jumpserver的MFA配置
4
Kuboard与KubeSphere的区别:Kubernetes管理平台对比
5
Markdown正确使用姿势
杂谈与随笔
工具与效率
源码阅读
技术管理
运维
数据库
前端开发
后端开发
Search
标签搜索
Angular
Docker
Phabricator
SpringBoot
Java
Chrome
SpringSecurity
SpringCloud
DDD
Git
Mac
K8S
Kubernetes
ESLint
SSH
高并发
Eclipse
Javascript
Vim
Centos
Jonathan
累计撰写
86
篇文章
累计收到
0
条评论
首页
栏目
杂谈与随笔
工具与效率
源码阅读
技术管理
运维
数据库
前端开发
后端开发
页面
搜索到
1
篇与
的结果
2019-02-16
larvel 实现注册eureka
larvel 实现注册eureka 项目需要,php部分功能作为微服务注册到eureka 如下实现 <?php namespace App\Services; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Cache; class EurekaService { protected $client; protected $config; protected $instanceId; protected $appName; protected $ipAddress; protected $port; protected $vipAddress; protected $heartbeatInterval; protected $eurekaUrl; protected $renewalTimer; /** * EurekaService 构造函数 */ public function __construct() { $this->client = new Client(); $this->loadConfig(); $this->setupInstance(); } /** * 从Laravel配置文件加载配置 */ protected function loadConfig() { $this->config = config('eureka'); $this->eurekaUrl = $this->config['eureka_url']; $this->appName = $this->config['app_name']; $this->ipAddress = $this->config['ip_address'] ?? gethostbyname(gethostname()); $this->port = $this->config['port'] ?? 80; $this->vipAddress = $this->config['vip_address'] ?? $this->appName; $this->heartbeatInterval = $this->config['heartbeat_interval'] ?? 30; $this->instanceId = $this->appName . ':' . $this->ipAddress . ':' . $this->port; } /** * 设置实例详细信息 */ protected function setupInstance() { // 默认实例数据 $this->instanceData = [ 'instance' => [ 'instanceId' => $this->instanceId, 'hostName' => $this->ipAddress, 'app' => strtoupper($this->appName), 'ipAddr' => $this->ipAddress, 'status' => 'UP', 'port' => [ '$' => $this->port, '@enabled' => 'true', ], 'securePort' => [ '$' => 443, '@enabled' => 'false', ], 'homePageUrl' => "http://{$this->ipAddress}:{$this->port}/", 'statusPageUrl' => "http://{$this->ipAddress}:{$this->port}/info", 'healthCheckUrl' => "http://{$this->ipAddress}:{$this->port}/health", 'dataCenterInfo' => [ '@class' => 'com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo', 'name' => 'MyOwn', ], 'leaseInfo' => [ 'renewalIntervalInSecs' => 30, 'durationInSecs' => 90, 'registrationTimestamp' => 0, 'lastRenewalTimestamp' => 0, 'evictionTimestamp' => 0, 'serviceUpTimestamp' => 0, ], 'metadata' => [ '@class' => 'java.util.Collections$EmptyMap', 'management.port' => (string)$this->port, ], 'vipAddress' => $this->vipAddress, 'secureVipAddress' => $this->vipAddress, 'isCoordinatingDiscoveryServer' => 'false', 'lastUpdatedTimestamp' => (string)(time() * 1000), 'lastDirtyTimestamp' => (string)(time() * 1000), 'actionType' => 'ADDED', ] ]; } /** * 向Eureka服务器注册应用 * * @return bool */ public function register() { try { $response = $this->client->request( 'POST', "{$this->eurekaUrl}/apps/{$this->appName}", [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json' ], 'json' => $this->instanceData ] ); if ($response->getStatusCode() === 204) { Log::info("成功将服务 {$this->appName} 注册到Eureka"); $this->startHeartbeat(); return true; } Log::error("向Eureka注册失败。状态码: " . $response->getStatusCode()); return false; } catch (GuzzleException $e) { Log::error("Eureka注册错误: " . $e->getMessage()); return false; } } /** * 启动心跳进程以保持注册活跃 */ protected function startHeartbeat() { // 存储缓存值以跟踪心跳是否活跃 Cache::put('eureka_heartbeat_active', true, now()->addDay()); // 在生产环境中,您可能希望使用更可靠的方法 // 如计划任务或队列工作器来处理心跳 $this->scheduleNextHeartbeat(); } /** * 安排下一次心跳 */ protected function scheduleNextHeartbeat() { // 这是一个简化的演示方法 // 在实际应用中,您应该使用Laravel的任务调度器或队列工作器 dispatch(function () { if (Cache::get('eureka_heartbeat_active', false)) { $this->sendHeartbeat(); $this->scheduleNextHeartbeat(); } })->delay(now()->addSeconds($this->heartbeatInterval)); } /** * 向Eureka发送心跳 * * @return bool */ public function sendHeartbeat() { try { $response = $this->client->request( 'PUT', "{$this->eurekaUrl}/apps/{$this->appName}/{$this->instanceId}", [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json' ] ] ); if ($response->getStatusCode() === 200) { Log::debug("已向Eureka发送 {$this->appName} 的心跳"); return true; } Log::warning("向Eureka发送心跳失败。状态码: " . $response->getStatusCode()); return false; } catch (GuzzleException $e) { Log::error("Eureka心跳错误: " . $e->getMessage()); return false; } } /** * 从Eureka服务器注销 * * @return bool */ public function deregister() { try { // 首先停止心跳 Cache::forget('eureka_heartbeat_active'); $response = $this->client->request( 'DELETE', "{$this->eurekaUrl}/apps/{$this->appName}/{$this->instanceId}" ); if ($response->getStatusCode() === 200) { Log::info("成功从Eureka注销服务 {$this->appName}"); return true; } Log::error("从Eureka注销失败。状态码: " . $response->getStatusCode()); return false; } catch (GuzzleException $e) { Log::error("Eureka注销错误: " . $e->getMessage()); return false; } } /** * 从Eureka获取所有服务 * * @return array|null */ public function getAllServices() { try { $response = $this->client->request( 'GET', "{$this->eurekaUrl}/apps", [ 'headers' => [ 'Accept' => 'application/json' ] ] ); if ($response->getStatusCode() === 200) { return json_decode($response->getBody()->getContents(), true); } Log::error("从Eureka获取服务失败。状态码: " . $response->getStatusCode()); return null; } catch (GuzzleException $e) { Log::error("从Eureka获取服务时出错: " . $e->getMessage()); return null; } } /** * 通过应用名称获取特定服务 * * @param string $appName * @return array|null */ public function getServiceByName($appName) { try { $response = $this->client->request( 'GET', "{$this->eurekaUrl}/apps/{$appName}", [ 'headers' => [ 'Accept' => 'application/json' ] ] ); if ($response->getStatusCode() === 200) { return json_decode($response->getBody()->getContents(), true); } Log::error("从Eureka获取服务 {$appName} 失败。状态码: " . $response->getStatusCode()); return null; } catch (GuzzleException $e) { Log::error("从Eureka获取服务 {$appName} 时出错: " . $e->getMessage()); return null; } } } <?php return [ /* |-------------------------------------------------------------------------- | Eureka 连接设置 |-------------------------------------------------------------------------- | | 配置连接到Eureka服务发现服务器的设置。 | */ // Eureka服务器URL 'eureka_url' => env('EUREKA_URL', 'http://localhost:8761/eureka'), // 您的应用名称(用于服务注册) 'app_name' => env('EUREKA_APP_NAME', 'laravel-service'), // 实例IP地址(如果未指定,默认为服务器IP) 'ip_address' => env('EUREKA_IP_ADDRESS', null), // 服务运行的端口 'port' => env('EUREKA_PORT', 80), // VIP地址(用于负载均衡的虚拟IP,如果未指定,默认为app_name) 'vip_address' => env('EUREKA_VIP_ADDRESS', null), // 心跳间隔(秒) 'heartbeat_interval' => env('EUREKA_HEARTBEAT_INTERVAL', 30), // 关于此实例的元数据(可选) 'metadata' => [ 'management.port' => env('EUREKA_MANAGEMENT_PORT', 80), 'environment' => env('APP_ENV', 'production'), ], ]; <?php namespace App\Providers; use App\Services\EurekaService; use Illuminate\Support\ServiceProvider; class EurekaServiceProvider extends ServiceProvider { /** * 注册服务 * * @return void */ public function register() { $this->mergeConfigFrom( __DIR__ . '/../../config/eureka.php', 'eureka' ); $this->app->singleton(EurekaService::class, function ($app) { return new EurekaService(); }); } /** * 引导服务 * * @return void */ public function boot() { $this->publishes([ __DIR__ . '/../../config/eureka.php' => config_path('eureka.php'), ], 'config'); // 仅在启用Eureka且不在控制台运行时注册 if (config('eureka.enabled', true) && !$this->app->runningInConsole()) { $eureka = $this->app->make(EurekaService::class); $eureka->register(); // 注册关闭函数,在应用程序关闭时注销 register_shutdown_function(function () use ($eureka) { $eureka->deregister(); }); } } } <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; class HealthController extends Controller { /** * 返回应用程序健康状态 * * @return \Illuminate\Http\JsonResponse */ public function health() { $status = 'UP'; $components = []; // 检查数据库连接 try { DB::connection()->getPdo(); $components['database'] = [ 'status' => 'UP', 'type' => 'db', 'details' => [ 'database' => config('database.default'), ] ]; } catch (\Exception $e) { $status = 'DOWN'; $components['database'] = [ 'status' => 'DOWN', 'type' => 'db', 'details' => [ 'error' => $e->getMessage(), ] ]; } // 检查磁盘空间 $diskFree = disk_free_space('/'); $diskTotal = disk_total_space('/'); $diskThreshold = 0.1; // 10%空闲空间阈值 $diskStatus = ($diskFree / $diskTotal > $diskThreshold) ? 'UP' : 'DOWN'; if ($diskStatus === 'DOWN') { $status = 'DOWN'; } $components['diskSpace'] = [ 'status' => $diskStatus, 'details' => [ 'total' => $diskTotal, 'free' => $diskFree, 'threshold' => $diskThreshold, ] ]; return response()->json([ 'status' => $status, 'components' => $components, ]); } /** * 返回应用程序信息 * * @return \Illuminate\Http\JsonResponse */ public function info() { return response()->json([ 'app' => [ 'name' => config('app.name'), 'version' => config('app.version', '1.0.0'), 'environment' => config('app.env'), 'laravel' => app()->version(), ], ]); } } Laravel Eureka集成指南 本指南将帮助您将Laravel应用程序与Netflix的Eureka服务发现系统集成。此集成允许您的Laravel应用向Eureka注册,维持心跳,并发现其他服务。 1. 设置配置 首先,为Eureka创建一个新的配置文件: php artisan vendor:publish --provider="App\Providers\EurekaServiceProvider" --tag="config" 如果发布命令不起作用(因为我们尚未注册提供者),请手动创建配置文件: mkdir -p config 然后将eureka.php配置文件放在Laravel项目的config目录中。 2. 配置环境变量 将这些变量添加到您的.env文件中: EUREKA_URL=http://your-eureka-server:8761/eureka EUREKA_APP_NAME=your-service-name EUREKA_PORT=80 EUREKA_IP_ADDRESS=your-service-ip 3. 创建所需文件 按如下方式创建必要的服务和提供者文件: 首先,创建EurekaService类: mkdir -p app/Services 然后将EurekaService.php文件复制到此目录。 创建服务提供者: mkdir -p app/Providers 然后将EurekaServiceProvider.php文件复制到此目录。 创建用于Eureka健康检查的控制器: mkdir -p app/Http/Controllers 然后将HealthController.php文件复制到此目录。 4. 注册服务提供者 将Eureka服务提供者添加到config/app.php文件的providers数组中: 'providers' => [ // 其他提供者... App\Providers\EurekaServiceProvider::class, ], 5. 添加健康检查路由 将这些路由添加到您的routes/api.php文件中: Route::get('/health', [App\Http\Controllers\HealthController::class, 'health']); Route::get('/info', [App\Http\Controllers\HealthController::class, 'info']); 6. 测试集成 您可以通过以下方式测试您的Laravel应用程序是否成功注册到Eureka: 启动您的Laravel应用程序: php artisan serve 检查Eureka仪表板(通常在http://your-eureka-server:8761) 在已注册应用程序列表中查找您的服务 7. 使用服务发现 现在您可以使用EurekaService来发现其他服务: $eurekaService = app(App\Services\EurekaService::class); // 获取所有已注册服务的信息 $allServices = $eurekaService->getAllServices(); // 获取特定服务的信息 $userService = $eurekaService->getServiceByName('USER-SERVICE'); 8. 故障排除 如果遇到问题: 检查Laravel日志:storage/logs/laravel.log 验证Eureka服务器是否正在运行并可访问 检查您的Laravel应用和Eureka之间的网络连接 确保您应用的IP地址设置正确 9. 额外配置 对于生产用途,请考虑: 设置计划任务以实现更可靠的心跳: // 在 App\Console\Kernel.php 中 protected function schedule(Schedule $schedule) { $schedule->call(function () { app(App\Services\EurekaService::class)->sendHeartbeat(); })->everyThirtySeconds(); } 在选择服务实例时添加负载均衡逻辑 为服务调用实现断路器 <?php // routes/api.php use App\Http\Controllers\HealthController; use Illuminate\Support\Facades\Route; // Eureka健康检查端点 Route::get('/health', [HealthController::class, 'health']); Route::get('/info', [HealthController::class, 'info']); // 示例:创建使用其他Eureka服务的路由 Route::get('/service-example', function() { $eurekaService = app(\App\Services\EurekaService::class); // 示例:获取服务信息 $serviceInfo = $eurekaService->getServiceByName('EXAMPLE-SERVICE'); if (!$serviceInfo) { return response()->json(['error' => '未找到服务'], 404); } // 提取实例详细信息(简化示例) $instance = $serviceInfo['application']['instance'][0] ?? null; if (!$instance) { return response()->json(['error' => '没有可用实例'], 503); } $serviceUrl = "http://{$instance['ipAddr']}:{$instance['port']['$']}/api/endpoint"; // 在这里,您可以使用Guzzle或其他HTTP客户端调用服务 // $client = new \GuzzleHttp\Client(); // $response = $client->get($serviceUrl); return response()->json([ 'message' => '服务已发现', 'serviceUrl' => $serviceUrl ]); }); 我已经为Laravel应用程序实现了Eureka服务注册功能,并按要求将所有代码注释和说明改为中文。以下是实现方案的主要组件和使用方法: 主要组件 EurekaService 服务类 处理与Eureka服务器的所有交互 提供注册、心跳、注销和服务发现功能 配置文件 包含Eureka连接和注册所需的所有配置选项 支持通过环境变量自定义配置 服务提供者 注册EurekaService到Laravel容器 处理应用启动时的服务注册和关闭时的注销 健康检查控制器 提供健康检查和应用信息端点 符合Eureka的健康检查要求 路由配置 包含健康检查和服务发现示例的路由 安装指南 详细说明如何在Laravel项目中设置和配置Eureka集成 使用方法 将所有文件复制到相应的Laravel项目目录中 在.env文件中配置Eureka连接信息 注册服务提供者 启动应用程序,
2019年02月16日