diff options
Diffstat (limited to 'seaweedfs-rdma-sidecar/CORRECT-SIDECAR-APPROACH.md')
| -rw-r--r-- | seaweedfs-rdma-sidecar/CORRECT-SIDECAR-APPROACH.md | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/seaweedfs-rdma-sidecar/CORRECT-SIDECAR-APPROACH.md b/seaweedfs-rdma-sidecar/CORRECT-SIDECAR-APPROACH.md new file mode 100644 index 000000000..743128ba8 --- /dev/null +++ b/seaweedfs-rdma-sidecar/CORRECT-SIDECAR-APPROACH.md @@ -0,0 +1,196 @@ +# ✅ Correct RDMA Sidecar Approach - Simple Parameter-Based + +## 🎯 **You're Right - Simplified Architecture** + +The RDMA sidecar should be **simple** and just take the volume server address as a parameter. The volume lookup complexity should stay in `weed mount`, not in the sidecar. + +## 🏗️ **Correct Architecture** + +### **1. weed mount (Client Side) - Does Volume Lookup** +```go +// File: weed/mount/filehandle_read.go (integration point) +func (fh *FileHandle) tryRDMARead(ctx context.Context, buff []byte, offset int64) (int64, int64, error) { + entry := fh.GetEntry() + + for _, chunk := range entry.GetEntry().Chunks { + if offset >= chunk.Offset && offset < chunk.Offset+int64(chunk.Size) { + // Parse chunk info + volumeID, needleID, cookie, err := ParseFileId(chunk.FileId) + if err != nil { + return 0, 0, err + } + + // 🔍 VOLUME LOOKUP (in weed mount, not sidecar) + volumeServerAddr, err := fh.wfs.lookupVolumeServer(ctx, volumeID) + if err != nil { + return 0, 0, err + } + + // 🚀 SIMPLE RDMA REQUEST WITH VOLUME SERVER PARAMETER + data, isRDMA, err := fh.wfs.rdmaClient.ReadNeedleFromServer( + ctx, volumeServerAddr, volumeID, needleID, cookie, chunkOffset, readSize) + + return int64(copy(buff, data)), time.Now().UnixNano(), nil + } + } +} +``` + +### **2. RDMA Mount Client - Passes Volume Server Address** +```go +// File: weed/mount/rdma_client.go (modify existing) +func (c *RDMAMountClient) ReadNeedleFromServer(ctx context.Context, volumeServerAddr string, volumeID uint32, needleID uint64, cookie uint32, offset, size uint64) ([]byte, bool, error) { + // Simple HTTP request with volume server as parameter + reqURL := fmt.Sprintf("http://%s/rdma/read", c.sidecarAddr) + + requestBody := map[string]interface{}{ + "volume_server": volumeServerAddr, // ← KEY: Pass volume server address + "volume_id": volumeID, + "needle_id": needleID, + "cookie": cookie, + "offset": offset, + "size": size, + } + + // POST request with volume server parameter + jsonBody, err := json.Marshal(requestBody) + if err != nil { + return nil, false, fmt.Errorf("failed to marshal request body: %w", err) + } + resp, err := c.httpClient.Post(reqURL, "application/json", bytes.NewBuffer(jsonBody)) + if err != nil { + return nil, false, fmt.Errorf("http post to sidecar: %w", err) + } +} +``` + +### **3. RDMA Sidecar - Simple, No Lookup Logic** +```go +// File: seaweedfs-rdma-sidecar/cmd/demo-server/main.go +func (s *DemoServer) rdmaReadHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + // Parse request body + var req struct { + VolumeServer string `json:"volume_server"` // ← Receive volume server address + VolumeID uint32 `json:"volume_id"` + NeedleID uint64 `json:"needle_id"` + Cookie uint32 `json:"cookie"` + Offset uint64 `json:"offset"` + Size uint64 `json:"size"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Invalid request", http.StatusBadRequest) + return + } + + s.logger.WithFields(logrus.Fields{ + "volume_server": req.VolumeServer, // ← Use provided volume server + "volume_id": req.VolumeID, + "needle_id": req.NeedleID, + }).Info("📖 Processing RDMA read with volume server parameter") + + // 🚀 SIMPLE: Use the provided volume server address + // No complex lookup logic needed! + resp, err := s.rdmaClient.ReadFromVolumeServer(r.Context(), req.VolumeServer, req.VolumeID, req.NeedleID, req.Cookie, req.Offset, req.Size) + + if err != nil { + http.Error(w, fmt.Sprintf("RDMA read failed: %v", err), http.StatusInternalServerError) + return + } + + // Return binary data + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("X-RDMA-Used", "true") + w.Write(resp.Data) +} +``` + +### **4. Volume Lookup in weed mount (Where it belongs)** +```go +// File: weed/mount/weedfs.go (add method) +func (wfs *WFS) lookupVolumeServer(ctx context.Context, volumeID uint32) (string, error) { + // Use existing SeaweedFS volume lookup logic + vid := fmt.Sprintf("%d", volumeID) + + // Query master server for volume location + locations, err := operation.LookupVolumeId(wfs.getMasterFn(), wfs.option.GrpcDialOption, vid) + if err != nil { + return "", fmt.Errorf("volume lookup failed: %w", err) + } + + if len(locations.Locations) == 0 { + return "", fmt.Errorf("no locations found for volume %d", volumeID) + } + + // Return first available location (or implement smart selection) + return locations.Locations[0].Url, nil +} +``` + +## 🎯 **Key Differences from Over-Complicated Approach** + +### **❌ Over-Complicated (What I Built Before):** +- ❌ Sidecar does volume lookup +- ❌ Sidecar has master client integration +- ❌ Sidecar has volume location caching +- ❌ Sidecar forwards requests to remote sidecars +- ❌ Complex distributed logic in sidecar + +### **✅ Correct Simple Approach:** +- ✅ **weed mount** does volume lookup (where it belongs) +- ✅ **weed mount** passes volume server address to sidecar +- ✅ **Sidecar** is simple and stateless +- ✅ **Sidecar** just does local RDMA read for given server +- ✅ **No complex distributed logic in sidecar** + +## 🚀 **Request Flow (Corrected)** + +1. **User Application** → `read()` system call +2. **FUSE** → `weed mount` WFS.Read() +3. **weed mount** → Volume lookup: "Where is volume 7?" +4. **SeaweedFS Master** → "Volume 7 is on server-B:8080" +5. **weed mount** → HTTP POST to sidecar: `{volume_server: "server-B:8080", volume: 7, needle: 12345}` +6. **RDMA Sidecar** → Connect to server-B:8080, do local RDMA read +7. **RDMA Engine** → Direct memory access to volume file +8. **Response** → Binary data back to weed mount → user + +## 📝 **Implementation Changes Needed** + +### **1. Simplify Sidecar (Remove Complex Logic)** +- Remove `DistributedRDMAClient` +- Remove volume lookup logic +- Remove master client integration +- Keep simple RDMA engine communication + +### **2. Add Volume Lookup to weed mount** +- Add `lookupVolumeServer()` method to WFS +- Modify `RDMAMountClient` to accept volume server parameter +- Integrate with existing SeaweedFS volume lookup + +### **3. Simple Sidecar API** +``` +POST /rdma/read +{ + "volume_server": "server-B:8080", + "volume_id": 7, + "needle_id": 12345, + "cookie": 0, + "offset": 0, + "size": 4096 +} +``` + +## ✅ **Benefits of Simple Approach** + +- **🎯 Single Responsibility**: Sidecar only does RDMA, weed mount does lookup +- **🔧 Maintainable**: Less complex logic in sidecar +- **⚡ Performance**: No extra network hops for volume lookup +- **🏗️ Clean Architecture**: Separation of concerns +- **🐛 Easier Debugging**: Clear responsibility boundaries + +You're absolutely right - this is much cleaner! The sidecar should be a simple RDMA accelerator, not a distributed system coordinator. |
