Repository: dragonflyoss/dragonfly

Issue:
✨ Set up Copilot instructions
Configure instructions for this repository as documented in [Best practices for Copilot coding agent in your repository](https://gh.io/copilot-coding-agent-tips).

<Onboard this repo>

Discussion:

Solution patch:
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 00000000..63e466f0
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,178 @@
+# Dragonfly P2P File Distribution System
+
+Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
+
+Dragonfly is a P2P file distribution and image acceleration system written in Go 1.23.8. It consists of multiple components: manager (cluster management and web portal), scheduler (download optimization), dfget (P2P download client), dfcache (P2P cache operations), and dfstore (object storage with P2P cache).
+
+## Working Effectively
+
+### Bootstrap and Build Process
+Install required dependencies and build the project:
+
+```bash
+# Install Go tools (required for linting and testing)
+curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
+go install github.com/onsi/ginkgo/v2/ginkgo@latest
+export PATH=$PATH:$(go env GOPATH)/bin
+
+# Build all components (takes ~1.5 minutes)
+make build-manager-server build-scheduler build-dfget build-dfcache build-dfstore
+# NEVER CANCEL: Build takes 2 minutes. Set timeout to 5+ minutes.
+
+# Verify build success
+ls -la bin/linux_amd64/
+./bin/linux_amd64/dfget version
+./bin/linux_amd64/scheduler version
+./bin/linux_amd64/manager version
+```
+
+**CRITICAL**: The full `make build` target will fail because `build-manager-console` requires a Node.js frontend that is not included in this repository. Always use the individual build targets listed above to build only the Go components.
+
+### Testing
+Run different test suites with appropriate timeouts:
+
+```bash
+# Format and vet code (takes ~20 seconds)
+make fmt vet
+# NEVER CANCEL: Set timeout to 2+ minutes.
+
+# Run linting (takes ~1.5 minutes)
+make markdownlint  # Takes ~5 seconds
+golangci-lint run --timeout=10m  # Takes ~1.5 minutes
+# NEVER CANCEL: Linting takes 2 minutes total. Set timeout to 5+ minutes.
+
+# Run unit tests (takes ~3.5 minutes, may have some failures in fresh environment)
+make test
+# NEVER CANCEL: Unit tests take 4 minutes. Set timeout to 10+ minutes.
+# Note: Some tests may fail in sandboxed environments, this is expected.
+
+# Run E2E tests (requires Docker and longer setup)
+make e2e-test
+# NEVER CANCEL: E2E tests take 10+ minutes. Set timeout to 30+ minutes.
+```
+
+### Running Applications
+Test the built applications:
+
+```bash
+# Test CLI help (validates binaries work correctly)
+./bin/linux_amd64/dfget --help
+./bin/linux_amd64/dfcache --help
+./bin/linux_amd64/dfstore --help
+./bin/linux_amd64/scheduler --help
+./bin/linux_amd64/manager --help
+
+# Test version commands (validates build was successful)
+./bin/linux_amd64/dfget version
+./bin/linux_amd64/scheduler version
+./bin/linux_amd64/manager version
+```
+
+**Important**: You cannot run the full Dragonfly system in a sandboxed environment without proper network configuration, certificates, and storage backends. The components require complex setup with Redis, databases, and network connectivity between peers.
+
+## Validation Requirements
+
+### Pre-commit Validation
+Always run these commands before committing changes:
+
+```bash
+# NEVER CANCEL: Full precheck takes 8 minutes. Set timeout to 15+ minutes.
+make fmt vet
+golangci-lint run --timeout=10m
+make build-manager-server build-scheduler build-dfget build-dfcache build-dfstore
+
+# Test that binaries still work
+./bin/linux_amd64/dfget version
+./bin/linux_amd64/scheduler version
+./bin/linux_amd64/manager version
+```
+
+### Scenario Testing
+After making changes, always validate:
+
+1. **Build Success**: All Go components build without errors
+2. **Binary Functionality**: Version commands execute successfully
+3. **Help Commands**: All help text displays correctly
+4. **Linting**: No linting errors introduced
+
+## Repository Structure
+
+### Key Directories
+- `cmd/`: Main entry points for each component (dfget, scheduler, manager, dfcache, dfstore)
+- `pkg/`: Shared libraries and utilities
+- `scheduler/`: Scheduler service implementation
+- `manager/`: Manager service implementation
+- `client/`: Client-side P2P logic
+- `test/`: Unit and E2E test suites
+- `hack/`: Build scripts and utilities
+- `api/`: API definitions and generated code
+
+### Build Artifacts
+- `bin/linux_amd64/`: Built binaries (created by build process)
+- `coverage.txt`: Test coverage reports
+
+### Important Files
+- `Makefile`: All build, test, and lint targets
+- `go.mod`: Go 1.23.8 dependencies
+- `.golangci.yml`: Linting configuration
+- `.markdownlint.yml`: Markdown linting rules
+
+## Timing Expectations
+
+| Command | Duration | Timeout Recommendation |
+|---------|----------|------------------------|
+| `make fmt vet` | 20 seconds | 2 minutes |
+| `make markdownlint` | 5 seconds | 1 minute |
+| `golangci-lint run` | 1.5 minutes | 5 minutes |
+| Build (Go only) | 1.5 minutes | 5 minutes |
+| `make test` | 3.5 minutes | 10 minutes |
+| `make e2e-test` | 10+ minutes | 30 minutes |
+| Full precheck | 8 minutes | 15 minutes |
+
+**CRITICAL**: NEVER CANCEL long-running commands. Builds and tests are CPU-intensive and require time to complete.
+
+## Common Tasks
+
+### Viewing Build Targets
+```bash
+make help
+```
+
+### Clean Build
+```bash
+make clean
+rm -rf bin/
+```
+
+### Adding Dependencies
+```bash
+go mod tidy
+go mod download
+```
+
+## Troubleshooting
+
+### Build Issues
+- **"build-manager-console" fails**: This is expected. The console frontend is not included. Use individual component build targets.
+- **Missing tools**: Install golangci-lint and ginkgo as shown in bootstrap section.
+- **Go version**: Requires Go 1.23.8 as specified in go.mod.
+
+### Test Issues
+- **Unit test failures**: Some tests may fail in sandboxed environments due to network/permission restrictions. This is expected.
+- **E2E test failures**: Require Docker and complex setup. May not work in all environments.
+
+### Runtime Issues
+- **"command not found"**: Add `$(go env GOPATH)/bin` to PATH for installed Go tools.
+- **Binary execution**: Built binaries are in `bin/linux_amd64/` directory.
+
+## Development Workflow
+
+1. **Make changes** to Go source files
+2. **Format and vet**: `make fmt vet`
+3. **Build**: Individual component build targets
+4. **Test**: `./bin/linux_amd64/[component] version` to verify
+5. **Lint**: `golangci-lint run --timeout=10m`
+6. **Unit test**: `make test` (optional, may fail in sandbox)
+7. **Commit** changes
+
+Always build and validate binary functionality after code changes to ensure nothing is broken.
\ No newline at end of file
diff --git a/.github/workflows/auto-assign.yml b/.github/workflows/auto-assign.yml
index 6538f10e..8f9e235c 100644
--- a/.github/workflows/auto-assign.yml
+++ b/.github/workflows/auto-assign.yml
@@ -11,4 +11,4 @@ jobs:
   add-assignee:
     runs-on: ubuntu-latest
     steps:
-      - uses: kentaro-m/auto-assign-action@9f6dbe84a80c6e7639d1b9698048b201052a2a94
+      - uses: kentaro-m/auto-assign-action@1a583dfb5dd75d0df34ecc781081e5a6a73d2dce
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4f5fe724..7a997d34 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -44,7 +44,7 @@ jobs:
           sudo make test-coverage
 
       - name: Upload coverage to Codecov
-        uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24
+        uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           files: ./coverage.txt
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index fc8aa8f0..065cea9b 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -31,12 +31,12 @@ jobs:
         uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
 
       - name: Initialize CodeQL
-        uses: github/codeql-action/init@76621b61decf072c1cee8dd1ce2d2a82d33c17ed
+        uses: github/codeql-action/init@f1f6e5f6af878fb37288ce1c627459e94dbf7d01
         with:
           languages: ${{ matrix.language }}
 
       - name: Autobuild
-        uses: github/codeql-action/autobuild@76621b61decf072c1cee8dd1ce2d2a82d33c17ed
+        uses: github/codeql-action/autobuild@f1f6e5f6af878fb37288ce1c627459e94dbf7d01
 
       - name: Perform CodeQL Analysis
-        uses: github/codeql-action/analyze@76621b61decf072c1cee8dd1ce2d2a82d33c17ed
+        uses: github/codeql-action/analyze@f1f6e5f6af878fb37288ce1c627459e94dbf7d01
diff --git a/.github/workflows/compatibility-e2e.yml b/.github/workflows/compatibility-e2e.yml
index 097a7a67..b80bf18f 100644
--- a/.github/workflows/compatibility-e2e.yml
+++ b/.github/workflows/compatibility-e2e.yml
@@ -41,12 +41,12 @@ jobs:
             skip: "Rate Limit | preheat files in cache"
           - module: client
             image: client
-            image-tag: v1.0.12
+            image-tag: v1.0.15
             chart-name: client
             skip: "Rate Limit"
           - module: seed-client
             image: client
-            image-tag: v1.0.12
+            image-tag: v1.0.15
             chart-name: seed-client
             skip: "Rate Limit"
 
@@ -155,7 +155,7 @@ jobs:
           mv /tmp/.buildx-cache-new /tmp/.buildx-cache
 
       - name: Upload coverage to Codecov
-        uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24
+        uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           files: ./coverage.txt
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 23043b48..872ba42a 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -116,7 +116,7 @@ jobs:
           output: 'trivy-results.sarif'
 
       - name: Upload Trivy scan results to GitHub Security tab
-        uses: github/codeql-action/upload-sarif@76621b61decf072c1cee8dd1ce2d2a82d33c17ed
+        uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01
         with:
           sarif_file: 'trivy-results.sarif'
 
diff --git a/.github/workflows/e2e-rate-limit.yml b/.github/workflows/e2e-rate-limit.yml
index 0725869a..3af95e42 100644
--- a/.github/workflows/e2e-rate-limit.yml
+++ b/.github/workflows/e2e-rate-limit.yml
@@ -138,7 +138,7 @@ jobs:
           mv /tmp/.buildx-cache-new /tmp/.buildx-cache
 
       - name: Upload coverage to Codecov
-        uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24
+        uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           files: ./coverage.txt
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 6cf447ee..7a465e4d 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -139,7 +139,7 @@ jobs:
           mv /tmp/.buildx-cache-new /tmp/.buildx-cache
 
       - name: Upload coverage to Codecov
-        uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24
+        uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           files: ./coverage.txt
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index bcec5a9a..7215adde 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -30,13 +30,13 @@ jobs:
           go-version-file: go.mod
 
       - name: Check GoReleaser config
-        uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552
+        uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a
         with:
           version: latest
           args: check
 
       - name: Run GoReleaser
-        uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552
+        uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a
         id: run-goreleaser
         with:
           version: latest
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 49411ea2..dd195e17 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -64,6 +64,6 @@ jobs:
       # Upload the results to GitHub's code scanning dashboard (optional).
       # Commenting out will disable upload of results to your repo's Code Scanning dashboard
       - name: "Upload to code-scanning"
-        uses: github/codeql-action/upload-sarif@76621b61decf072c1cee8dd1ce2d2a82d33c17ed
+        uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01
         with:
           sarif_file: results.sarif
diff --git a/.gitignore b/.gitignore
index 4b4768f4..f22dc5ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,3 +65,5 @@ deploy/docker-compose/log
 deploy/docker-compose/config
 test/e2e/v1/*.log
 test/e2e/*.log
+# Exclude build artifacts
+bin/
diff --git a/README.md b/README.md
index 8614b7ee..f9ab48ec 100644
--- a/README.md
+++ b/README.md
@@ -77,7 +77,7 @@ Join the conversation and help the community. We have a number of ways for you t
 - **Developer Group**: <dragonfly-developers@googlegroups.com>
 - **Maintainer Group**: <dragonfly-maintainers@googlegroups.com>
 - **Twitter**: [@dragonfly_oss](https://twitter.com/dragonfly_oss)
-- **DingTalk**: [22880028764](https://qr.dingtalk.com/action/joingroup?code=v1,k1,pkV9IbsSyDusFQdByPSK3HfCG61ZCLeb8b/lpQ3uUqI=&_dt_no_comment=1&origin=11)
+- **DingTalk Group**: `22880028764`
 
 and you can also seek the main community information in the [community repository](https://github.com/dragonflyoss/community).
 In this repository, you can find the [community meeting minutes, community meeting notes, and more](https://github.com/dragonflyoss/community/tree/master/meetings).
diff --git a/api/manager/docs.go b/api/manager/docs.go
index 340d9d70..8c9cdcce 100644
--- a/api/manager/docs.go
+++ b/api/manager/docs.go
@@ -4430,6 +4430,9 @@ const docTemplate = `{
                 "port": {
                     "type": "integer"
                 },
+                "proxy_port": {
+                    "type": "integer"
+                },
                 "scheduler_cluster": {
                     "$ref": "#/definitions/d7y_io_dragonfly_v2_manager_models.SchedulerCluster"
                 },
@@ -4494,6 +4497,9 @@ const docTemplate = `{
         "d7y_io_dragonfly_v2_manager_models.Scheduler": {
             "type": "object",
             "properties": {
+                "config": {
+                    "$ref": "#/definitions/d7y_io_dragonfly_v2_manager_models.JSONMap"
+                },
                 "created_at": {
                     "type": "string"
                 },
@@ -4518,6 +4524,9 @@ const docTemplate = `{
                 "is_del": {
                     "type": "integer"
                 },
+                "last_keep_alive_at": {
+                    "type": "string"
+                },
                 "location": {
                     "type": "string"
                 },
@@ -4980,6 +4989,7 @@ const docTemplate = `{
                 "host_name",
                 "ip",
                 "port",
+                "proxy_port",
                 "scheduler_cluster_id",
                 "type"
             ],
@@ -5029,6 +5039,9 @@ const docTemplate = `{
                 "port": {
                     "type": "integer"
                 },
+                "proxy_port": {
+                    "type": "integer"
+                },
                 "scheduler_cluster_id": {
                     "type": "integer"
                 },
@@ -5136,6 +5149,9 @@ const docTemplate = `{
                 "scheduler_cluster_id"
             ],
             "properties": {
+                "config": {
+                    "$ref": "#/definitions/d7y_io_dragonfly_v2_manager_types.SchedulerConfig"
+                },
                 "features": {
                     "type": "array",
                     "items": {
@@ -5547,14 +5563,6 @@ const docTemplate = `{
                     "description": "Network contains network information.",
                     "type": "object",
                     "properties": {
-                        "download_rate": {
-                            "description": "DownloadRate is download rate.",
-                            "type": "integer"
-                        },
-                        "download_rate_limit": {
-                            "description": "DownloadRateLimit is download rate limit.",
-                            "type": "integer"
-                        },
                         "idc": {
                             "description": "IDC is network idc.",
                             "type": "string"
@@ -5563,16 +5571,24 @@ const docTemplate = `{
                             "description": "Location is network location.",
                             "type": "string"
                         },
-                        "tcp_connection_count": {
-                            "description": "TCPConnectionCount is tcp connection count.",
+                        "max_rx_bandwidth": {
+                            "description": "MaxRxBandwidth is download rate limit.",
+                            "type": "integer"
+                        },
+                        "max_tx_bandwidth": {
+                            "description": "MaxTxBandwidth is upload rate limit.",
+                            "type": "integer"
+                        },
+                        "rx_bandwidth": {
+                            "description": "RxBandwidth is download rate.",
                             "type": "integer"
                         },
-                        "upload_rate": {
-                            "description": "UploadRate is upload rate.",
+                        "tcp_connection_count": {
+                            "description": "TCPConnectionCount is tcp connection count.",
                             "type": "integer"
                         },
-                        "upload_rate_limit": {
-                            "description": "UploadRateLimit is upload rate limit.",
+                        "tx_bandwidth": {
+                            "description": "TxBandwidth is upload rate.",
                             "type": "integer"
                         },
                         "upload_tcp_connection_count": {
@@ -5822,6 +5838,17 @@ const docTemplate = `{
                 }
             }
         },
+        "d7y_io_dragonfly_v2_manager_types.SchedulerConfig": {
+            "type": "object",
+            "required": [
+                "manager_keep_alive_interval"
+            ],
+            "properties": {
+                "manager_keep_alive_interval": {
+                    "$ref": "#/definitions/time.Duration"
+                }
+            }
+        },
         "d7y_io_dragonfly_v2_manager_types.SeedPeerClusterConfig": {
             "type": "object",
             "properties": {
@@ -6084,6 +6111,9 @@ const docTemplate = `{
         "d7y_io_dragonfly_v2_manager_types.UpdateSchedulerRequest": {
             "type": "object",
             "properties": {
+                "config": {
+                    "$ref": "#/definitions/d7y_io_dragonfly_v2_manager_types.SchedulerConfig"
+                },
                 "features": {
                     "type": "array",
                     "items": {
diff --git a/api/manager/swagger.json b/api/manager/swagger.json
index 3679f415..a943bf2f 100644
--- a/api/manager/swagger.json
+++ b/api/manager/swagger.json
@@ -4424,6 +4424,9 @@
                 "port": {
                     "type": "integer"
                 },
+                "proxy_port": {
+                    "type": "integer"
+                },
                 "scheduler_cluster": {
                     "$ref": "#/definitions/d7y_io_dragonfly_v2_manager_models.SchedulerCluster"
                 },
@@ -4488,6 +4491,9 @@
         "d7y_io_dragonfly_v2_manager_models.Scheduler": {
             "type": "object",
             "properties": {
+                "config": {
+                    "$ref": "#/definitions/d7y_io_dragonfly_v2_manager_models.JSONMap"
+                },
                 "created_at": {
                     "type": "string"
                 },
@@ -4512,6 +4518,9 @@
                 "is_del": {
                     "type": "integer"
                 },
+                "last_keep_alive_at": {
+                    "type": "string"
+                },
                 "location": {
                     "type": "string"
                 },
@@ -4974,6 +4983,7 @@
                 "host_name",
                 "ip",
                 "port",
+                "proxy_port",
                 "scheduler_cluster_id",
                 "type"
             ],
@@ -5023,6 +5033,9 @@
                 "port": {
                     "type": "integer"
                 },
+                "proxy_port": {
+                    "type": "integer"
+                },
                 "scheduler_cluster_id": {
                     "type": "integer"
                 },
@@ -5130,6 +5143,9 @@
                 "scheduler_cluster_id"
             ],
             "properties": {
+                "config": {
+                    "$ref": "#/definitions/d7y_io_dragonfly_v2_manager_types.SchedulerConfig"
+                },
                 "features": {
                     "type": "array",
                     "items": {
@@ -5541,14 +5557,6 @@
                     "description": "Network contains network information.",
                     "type": "object",
                     "properties": {
-                        "download_rate": {
-                            "description": "DownloadRate is download rate.",
-                            "type": "integer"
-                        },
-                        "download_rate_limit": {
-                            "description": "DownloadRateLimit is download rate limit.",
-                            "type": "integer"
-                        },
                         "idc": {
                             "description": "IDC is network idc.",
                             "type": "string"
@@ -5557,16 +5565,24 @@
                             "description": "Location is network location.",
                             "type": "string"
                         },
-                        "tcp_connection_count": {
-                            "description": "TCPConnectionCount is tcp connection count.",
+                        "max_rx_bandwidth": {
+                            "description": "MaxRxBandwidth is download rate limit.",
+                            "type": "integer"
+                        },
+                        "max_tx_bandwidth": {
+                            "description": "MaxTxBandwidth is upload rate limit.",
+                            "type": "integer"
+                        },
+                        "rx_bandwidth": {
+                            "description": "RxBandwidth is download rate.",
                             "type": "integer"
                         },
-                        "upload_rate": {
-                            "description": "UploadRate is upload rate.",
+                        "tcp_connection_count": {
+                            "description": "TCPConnectionCount is tcp connection count.",
                             "type": "integer"
                         },
-                        "upload_rate_limit": {
-                            "description": "UploadRateLimit is upload rate limit.",
+                        "tx_bandwidth": {
+                            "description": "TxBandwidth is upload rate.",
                             "type": "integer"
                         },
                         "upload_tcp_connection_count": {
@@ -5816,6 +5832,17 @@
                 }
             }
         },
+        "d7y_io_dragonfly_v2_manager_types.SchedulerConfig": {
+            "type": "object",
+            "required": [
+                "manager_keep_alive_interval"
+            ],
+            "properties": {
+                "manager_keep_alive_interval": {
+                    "$ref": "#/definitions/time.Duration"
+                }
+            }
+        },
         "d7y_io_dragonfly_v2_manager_types.SeedPeerClusterConfig": {
             "type": "object",
             "properties": {
@@ -6078,6 +6105,9 @@
         "d7y_io_dragonfly_v2_manager_types.UpdateSchedulerRequest": {
             "type": "object",
             "properties": {
+                "config": {
+                    "$ref": "#/definitions/d7y_io_dragonfly_v2_manager_types.SchedulerConfig"
+                },
                 "features": {
                     "type": "array",
                     "items": {
diff --git a/api/manager/swagger.yaml b/api/manager/swagger.yaml
index 4bc489d8..24941602 100644
--- a/api/manager/swagger.yaml
+++ b/api/manager/swagger.yaml
@@ -194,6 +194,8 @@ definitions:
         type: string
       port:
         type: integer
+      proxy_port:
+        type: integer
       scheduler_cluster:
         $ref: '#/definitions/d7y_io_dragonfly_v2_manager_models.SchedulerCluster'
       scheduler_cluster_id:
@@ -236,6 +238,8 @@ definitions:
     type: object
   d7y_io_dragonfly_v2_manager_models.Scheduler:
     properties:
+      config:
+        $ref: '#/definitions/d7y_io_dragonfly_v2_manager_models.JSONMap'
       created_at:
         type: string
       features:
@@ -252,6 +256,8 @@ definitions:
         type: string
       is_del:
         type: integer
+      last_keep_alive_at:
+        type: string
       location:
         type: string
       port:
@@ -590,6 +596,8 @@ definitions:
         type: string
       port:
         type: integer
+      proxy_port:
+        type: integer
       scheduler_cluster_id:
         type: integer
       state:
@@ -609,6 +617,7 @@ definitions:
     - host_name
     - ip
     - port
+    - proxy_port
     - scheduler_cluster_id
     - type
     type: object
@@ -666,6 +675,8 @@ definitions:
     type: object
   d7y_io_dragonfly_v2_manager_types.CreateSchedulerRequest:
     properties:
+      config:
+        $ref: '#/definitions/d7y_io_dragonfly_v2_manager_types.SchedulerConfig'
       features:
         items:
           type: string
@@ -960,26 +971,26 @@ definitions:
       network:
         description: Network contains network information.
         properties:
-          download_rate:
-            description: DownloadRate is download rate.
-            type: integer
-          download_rate_limit:
-            description: DownloadRateLimit is download rate limit.
-            type: integer
           idc:
             description: IDC is network idc.
             type: string
           location:
             description: Location is network location.
             type: string
+          max_rx_bandwidth:
+            description: MaxRxBandwidth is download rate limit.
+            type: integer
+          max_tx_bandwidth:
+            description: MaxTxBandwidth is upload rate limit.
+            type: integer
+          rx_bandwidth:
+            description: RxBandwidth is download rate.
+            type: integer
           tcp_connection_count:
             description: TCPConnectionCount is tcp connection count.
             type: integer
-          upload_rate:
-            description: UploadRate is upload rate.
-            type: integer
-          upload_rate_limit:
-            description: UploadRateLimit is upload rate limit.
+          tx_bandwidth:
+            description: TxBandwidth is upload rate.
             type: integer
           upload_tcp_connection_count:
             description: UploadTCPConnectionCount is upload tcp connection count.
@@ -1152,6 +1163,13 @@ definitions:
       location:
         type: string
     type: object
+  d7y_io_dragonfly_v2_manager_types.SchedulerConfig:
+    properties:
+      manager_keep_alive_interval:
+        $ref: '#/definitions/time.Duration'
+    required:
+    - manager_keep_alive_interval
+    type: object
   d7y_io_dragonfly_v2_manager_types.SeedPeerClusterConfig:
     properties:
       load_limit:
@@ -1328,6 +1346,8 @@ definitions:
     type: object
   d7y_io_dragonfly_v2_manager_types.UpdateSchedulerRequest:
     properties:
+      config:
+        $ref: '#/definitions/d7y_io_dragonfly_v2_manager_types.SchedulerConfig'
       features:
         items:
           type: string
diff --git a/build/images/dfdaemon/Dockerfile b/build/images/dfdaemon/Dockerfile
index 08ebfb39..515a5705 100644
--- a/build/images/dfdaemon/Dockerfile
+++ b/build/images/dfdaemon/Dockerfile
@@ -1,6 +1,6 @@
-ARG BASE_IMAGE=alpine:3.20
+ARG BASE_IMAGE=alpine:3.21
 
-FROM golang:1.23.8-alpine3.20 AS builder
+FROM golang:1.23.8-alpine3.21 AS builder
 
 ARG GOPROXY
 ARG GOTAGS
diff --git a/build/images/manager/Dockerfile b/build/images/manager/Dockerfile
index 524b83be..b5368e09 100644
--- a/build/images/manager/Dockerfile
+++ b/build/images/manager/Dockerfile
@@ -1,4 +1,4 @@
-ARG BASE_IMAGE=alpine:3.20
+ARG BASE_IMAGE=alpine:3.21
 
 FROM node:20-alpine AS console-builder
 
@@ -12,7 +12,7 @@ COPY ./manager/console /build
 
 RUN yarn build
 
-FROM golang:1.23.8-alpine3.20 AS server-builder
+FROM golang:1.23.8-alpine3.21 AS server-builder
 
 ARG GOPROXY
 ARG GOTAGS
diff --git a/build/images/scheduler/Dockerfile b/build/images/scheduler/Dockerfile
index 5ce03f3a..6411fa24 100644
--- a/build/images/scheduler/Dockerfile
+++ b/build/images/scheduler/Dockerfile
@@ -1,6 +1,6 @@
-ARG BASE_IMAGE=alpine:3.20
+ARG BASE_IMAGE=alpine:3.21
 
-FROM golang:1.23.8-alpine3.20 AS builder
+FROM golang:1.23.8-alpine3.21 AS builder
 
 ARG GOPROXY
 ARG GOTAGS
diff --git a/build/plugin-builder/Dockerfile b/build/plugin-builder/Dockerfile
index 791775af..2c516de6 100644
--- a/build/plugin-builder/Dockerfile
+++ b/build/plugin-builder/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.23.8-alpine3.20
+FROM golang:1.23.8-alpine3.21
 
 ARG GOPROXY
 ARG GOTAGS
diff --git a/client-rs b/client-rs
index bb94a4f3..33375f0f 160000
--- a/client-rs
+++ b/client-rs
@@ -1 +1 @@
-Subproject commit bb94a4f346098217accacf0c46520446e2884cc4
+Subproject commit 33375f0f5a104edbad9dd6eef19206b04a622478
diff --git a/client/daemon/announcer/announcer.go b/client/daemon/announcer/announcer.go
index 73353e28..f311b4fe 100644
--- a/client/daemon/announcer/announcer.go
+++ b/client/daemon/announcer/announcer.go
@@ -57,6 +57,7 @@ type announcer struct {
 	hostID                  string
 	daemonPort              int32
 	daemonDownloadPort      int32
+	daemonProxyPort         int32
 	daemonObjectStoragePort int32
 	schedulerClient         schedulerclient.V1
 	managerClient           managerclient.V1
@@ -81,13 +82,14 @@ func WithObjectStoragePort(port int32) Option {
 }
 
 // New returns a new Announcer interface.
-func New(cfg *config.DaemonOption, dynconfig config.Dynconfig, hostID string, daemonPort int32, daemonDownloadPort int32, schedulerClient schedulerclient.V1, options ...Option) Announcer {
+func New(cfg *config.DaemonOption, dynconfig config.Dynconfig, hostID string, daemonPort int32, daemonDownloadPort, daemonProxyPort int32, schedulerClient schedulerclient.V1, options ...Option) Announcer {
 	a := &announcer{
 		config:             cfg,
 		dynconfig:          dynconfig,
 		hostID:             hostID,
 		daemonPort:         daemonPort,
 		daemonDownloadPort: daemonDownloadPort,
+		daemonProxyPort:    daemonProxyPort,
 		schedulerClient:    schedulerClient,
 		done:               make(chan struct{}),
 	}
@@ -242,6 +244,7 @@ func (a *announcer) newAnnounceHostRequest() (*schedulerv1.AnnounceHostRequest,
 		Ip:                a.config.Host.AdvertiseIP.String(),
 		Port:              a.daemonPort,
 		DownloadPort:      a.daemonDownloadPort,
+		ProxyPort:         a.daemonProxyPort,
 		ObjectStoragePort: objectStoragePort,
 		Os:                h.OS,
 		Platform:          h.Platform,
diff --git a/client/daemon/daemon.go b/client/daemon/daemon.go
index 1075b3b4..8c25d56e 100644
--- a/client/daemon/daemon.go
+++ b/client/daemon/daemon.go
@@ -537,6 +537,7 @@ func (cd *clientDaemon) Serve() error {
 			cd.ProxyManager.Watch(daemon.Proxy)
 		})
 	}
+	cd.schedPeerHost.ProxyPort = int32(proxyPort)
 
 	if cd.Option.IsSupportPeerExchange() {
 		go func() {
@@ -599,7 +600,7 @@ func (cd *clientDaemon) Serve() error {
 	}
 
 	cd.announcer = announcer.New(&cd.Option, cd.dynconfig, cd.schedPeerHost.Id, cd.schedPeerHost.RpcPort,
-		cd.schedPeerHost.DownPort, cd.schedulerClient, announcerOptions...)
+		cd.schedPeerHost.DownPort, cd.schedPeerHost.ProxyPort, cd.schedulerClient, announcerOptions...)
 	go func() {
 		logger.Info("serve announcer")
 		if err := cd.announcer.Serve(); err != nil {
diff --git a/go.mod b/go.mod
index e1c822eb..8b972de3 100644
--- a/go.mod
+++ b/go.mod
@@ -4,14 +4,14 @@ go 1.23.8
 
 require (
 	cloud.google.com/go/storage v1.50.0
-	d7y.io/api/v2 v2.1.55
+	d7y.io/api/v2 v2.1.60
 	github.com/MysteriousPotato/go-lockable v1.0.0
 	github.com/Showmax/go-fqdn v1.0.0
 	github.com/VividCortex/mysqlerr v1.0.0
 	github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
 	github.com/appleboy/gin-jwt/v2 v2.10.3
 	github.com/aws/aws-sdk-go v1.55.8
-	github.com/bits-and-blooms/bitset v1.22.0
+	github.com/bits-and-blooms/bitset v1.24.0
 	github.com/casbin/casbin/v2 v2.81.0
 	github.com/casbin/gorm-adapter/v3 v3.5.0
 	github.com/cespare/xxhash/v2 v2.3.0
@@ -71,7 +71,7 @@ require (
 	github.com/soheilhy/cmux v0.1.5
 	github.com/spf13/cobra v1.9.1
 	github.com/spf13/viper v1.18.2
-	github.com/stretchr/testify v1.10.0
+	github.com/stretchr/testify v1.11.0
 	github.com/swaggo/files v1.0.1
 	github.com/swaggo/gin-swagger v1.6.0
 	github.com/swaggo/swag v1.16.6
@@ -86,7 +86,7 @@ require (
 	go.opentelemetry.io/otel/sdk v1.37.0
 	go.opentelemetry.io/otel/trace v1.37.0
 	go.uber.org/atomic v1.11.0
-	go.uber.org/mock v0.5.2
+	go.uber.org/mock v0.6.0
 	go.uber.org/zap v1.27.0
 	golang.org/x/crypto v0.41.0
 	golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
@@ -94,9 +94,9 @@ require (
 	golang.org/x/sync v0.16.0
 	golang.org/x/sys v0.35.0
 	golang.org/x/time v0.12.0
-	google.golang.org/api v0.244.0
-	google.golang.org/grpc v1.74.2
-	google.golang.org/protobuf v1.36.6
+	google.golang.org/api v0.248.0
+	google.golang.org/grpc v1.75.0
+	google.golang.org/protobuf v1.36.7
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0
 	gopkg.in/yaml.v3 v3.0.1
 	gorm.io/driver/mysql v1.4.7
@@ -110,14 +110,14 @@ require (
 require (
 	cel.dev/expr v0.24.0 // indirect
 	cloud.google.com/go v0.120.0 // indirect
-	cloud.google.com/go/auth v0.16.3 // indirect
+	cloud.google.com/go/auth v0.16.5 // indirect
 	cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
-	cloud.google.com/go/compute/metadata v0.7.0 // indirect
+	cloud.google.com/go/compute/metadata v0.8.0 // indirect
 	cloud.google.com/go/iam v1.5.2 // indirect
 	cloud.google.com/go/monitoring v1.24.2 // indirect
 	cloud.google.com/go/pubsub v1.49.0 // indirect
 	filippo.io/edwards25519 v1.1.0 // indirect
-	github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
+	github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect
 	github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0 // indirect
 	github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0 // indirect
 	github.com/KyleBanks/depth v1.2.1 // indirect
@@ -147,7 +147,7 @@ require (
 	github.com/gabriel-vasile/mimetype v1.4.9 // indirect
 	github.com/gin-contrib/sse v1.1.0 // indirect
 	github.com/go-echarts/go-echarts/v2 v2.2.4 // indirect
-	github.com/go-jose/go-jose/v4 v4.0.5 // indirect
+	github.com/go-jose/go-jose/v4 v4.1.1 // indirect
 	github.com/go-logr/logr v1.4.3 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
 	github.com/go-ole/go-ole v1.2.6 // indirect
@@ -267,14 +267,14 @@ require (
 	go.uber.org/automaxprocs v1.6.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	golang.org/x/arch v0.17.0 // indirect
-	golang.org/x/mod v0.26.0 // indirect
-	golang.org/x/net v0.42.0 // indirect
+	golang.org/x/mod v0.27.0 // indirect
+	golang.org/x/net v0.43.0 // indirect
 	golang.org/x/term v0.34.0 // indirect
 	golang.org/x/text v0.28.0 // indirect
-	golang.org/x/tools v0.35.0 // indirect
+	golang.org/x/tools v0.36.0 // indirect
 	google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
-	google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gorm.io/driver/sqlserver v1.4.1 // indirect
diff --git a/go.sum b/go.sum
index 19bd5766..bd674c69 100644
--- a/go.sum
+++ b/go.sum
@@ -23,8 +23,8 @@ cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPT
 cloud.google.com/go v0.76.0/go.mod h1:r9EvIAvLrunusnetGdQ50M/gKui1x3zdGW/VELGkdpw=
 cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA=
 cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q=
-cloud.google.com/go/auth v0.16.3 h1:kabzoQ9/bobUmnseYnBO6qQG7q4a/CffFRlJSxv2wCc=
-cloud.google.com/go/auth v0.16.3/go.mod h1:NucRGjaXfzP1ltpcQ7On/VTZ0H4kWB5Jy+Y9Dnm76fA=
+cloud.google.com/go/auth v0.16.5 h1:mFWNQ2FEVWAliEQWpAdH80omXFokmrnbDhUS9cBywsI=
+cloud.google.com/go/auth v0.16.5/go.mod h1:utzRfHMP+Vv0mpOkTRQoWD2q3BatTOoWbA7gCc2dUhQ=
 cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
 cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
 cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
@@ -33,8 +33,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
 cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
 cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
 cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
-cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
+cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA=
+cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw=
 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
 cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
@@ -63,8 +63,8 @@ cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6Q
 cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY=
 cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4=
 cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI=
-d7y.io/api/v2 v2.1.55 h1:MM0Zpk6KqWAhwwHsGXfaCNt5sgJta6J8u5ewLVH03pQ=
-d7y.io/api/v2 v2.1.55/go.mod h1:E3XBK7gLlGEGezrmQ328zYzd23js8Os3MESzaNvqrgw=
+d7y.io/api/v2 v2.1.60 h1:Imk1mw30wmTJNdqKFF5VO/eqI/t1H5PfIPPK4ryKX2U=
+d7y.io/api/v2 v2.1.60/go.mod h1:WzakPywEgs27gr/TwrlRarPRRK2o5nN0YrTzHDdFii8=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
@@ -90,8 +90,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
 github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
 github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
 github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
-github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc=
-github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw=
 github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0 h1:5IT7xOdq17MtcdtL/vtl6mGfzhaq4m4vpollPRmlsBQ=
 github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0/go.mod h1:ZV4VOm0/eHR06JLrXWe09068dHpr3TRpY9Uo7T+anuA=
 github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.50.0 h1:nNMpRpnkWDAaqcpxMJvxa/Ud98gjbYwayJY4/9bdjiU=
@@ -191,8 +191,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
 github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
-github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4=
-github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
+github.com/bits-and-blooms/bitset v1.24.0 h1:H4x4TuulnokZKvHLfzVRTHJfFfnHEeSYJizujEZvmAM=
+github.com/bits-and-blooms/bitset v1.24.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
 github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
@@ -527,8 +527,8 @@ github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I7
 github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
 github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
 github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
-github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
-github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
+github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
+github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
@@ -1433,8 +1433,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
-github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8=
+github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
 github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
 github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
 github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
@@ -1601,8 +1601,8 @@ go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ
 go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
-go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
-go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
+go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
+go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@@ -1700,8 +1700,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
-golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
+golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
+golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1772,8 +1772,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
 golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
 golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
-golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
-golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
+golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
+golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -2049,14 +2049,16 @@ golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
 golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
-golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
-golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
+golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
 golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
 google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
 google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@@ -2079,8 +2081,8 @@ google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ
 google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
 google.golang.org/api v0.38.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
 google.golang.org/api v0.39.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.244.0 h1:lpkP8wVibSKr++NCD36XzTk/IzeKJ3klj7vbj+XU5pE=
-google.golang.org/api v0.244.0/go.mod h1:dMVhVcylamkirHdzEBAIQWUCgqY885ivNeZYd7VAVr8=
+google.golang.org/api v0.248.0 h1:hUotakSkcwGdYUqzCRc5yGYsg4wXxpkKlW5ryVqvC1Y=
+google.golang.org/api v0.248.0/go.mod h1:yAFUAF56Li7IuIQbTFoLwXTCI6XCFKueOlS7S9e4F9k=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -2136,10 +2138,10 @@ google.golang.org/genproto v0.0.0-20210202153253-cf70463f6119/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
 google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
-google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 h1:MAKi5q709QWfnkkpNQ0M12hYJ1+e8qYVDyowc4U1XZM=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
+google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU=
+google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
 google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@@ -2168,8 +2170,8 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5
 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
-google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
+google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
+google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -2184,8 +2186,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
-google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
+google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
+google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/manager/console b/manager/console
index 49a3f9a6..2b3a3032 160000
--- a/manager/console
+++ b/manager/console
@@ -1 +1 @@
-Subproject commit 49a3f9a6f21728eb6bbf94c4e29bb98514a9c68a
+Subproject commit 2b3a3032ea32ddf4d2ed3e270c2d2c9ab2a9befd
diff --git a/manager/job/sync_peers.go b/manager/job/sync_peers.go
index ced33c90..b74f7bdd 100644
--- a/manager/job/sync_peers.go
+++ b/manager/job/sync_peers.go
@@ -223,6 +223,7 @@ func (s *syncPeers) mergePeers(ctx context.Context, scheduler models.Scheduler,
 					IP:                 syncPeer.IP,
 					Port:               syncPeer.Port,
 					DownloadPort:       syncPeer.DownloadPort,
+					ProxyPort:          syncPeer.ProxyPort,
 					ObjectStoragePort:  syncPeer.ObjectStoragePort,
 					State:              models.PeerStateActive,
 					OS:                 syncPeer.OS,
@@ -268,6 +269,7 @@ func (s *syncPeers) mergePeers(ctx context.Context, scheduler models.Scheduler,
 			IP:                 syncPeer.IP,
 			Port:               syncPeer.Port,
 			DownloadPort:       syncPeer.DownloadPort,
+			ProxyPort:          syncPeer.ProxyPort,
 			ObjectStoragePort:  syncPeer.ObjectStoragePort,
 			State:              models.PeerStateActive,
 			OS:                 syncPeer.OS,
diff --git a/manager/middlewares/personal_access_token.go b/manager/middlewares/personal_access_token.go
index eb9b40d8..2a40baa1 100644
--- a/manager/middlewares/personal_access_token.go
+++ b/manager/middlewares/personal_access_token.go
@@ -41,20 +41,28 @@ var (
 
 func PersonalAccessToken(gdb *gorm.DB) gin.HandlerFunc {
 	return func(c *gin.Context) {
-		// Get bearer token from Authorization header.
-		authorization := c.GetHeader(headers.Authorization)
-		tokenFields := strings.Fields(authorization)
-		if len(tokenFields) != 2 || tokenFields[0] != "Bearer" {
-			c.JSON(http.StatusUnauthorized, ErrorResponse{
-				Message: http.StatusText(http.StatusUnauthorized),
-			})
-
-			c.Abort()
-			return
+		// Extract personal access token from either query parameter or Authorization header.
+		// First, try to get the token from the "access_token" query parameter.
+		// If not found, extract it from the "Authorization" header using Bearer token format,
+		// return 401 Unauthorized if the Authorization header format is invalid.
+		var personalAccessToken string
+		if accessToken := strings.TrimSpace(c.Query("access_token")); accessToken != "" {
+			personalAccessToken = accessToken
+		} else {
+			authorization := c.GetHeader(headers.Authorization)
+			tokenFields := strings.Fields(authorization)
+			if len(tokenFields) != 2 || !strings.EqualFold(tokenFields[0], "Bearer") {
+				c.JSON(http.StatusUnauthorized, ErrorResponse{
+					Message: http.StatusText(http.StatusUnauthorized),
+				})
+
+				c.Abort()
+				return
+			}
+
+			personalAccessToken = tokenFields[1]
 		}
 
-		// Check if the personal access token is valid.
-		personalAccessToken := tokenFields[1]
 		var token models.PersonalAccessToken
 		if err := gdb.WithContext(c).Where("token = ?", personalAccessToken).First(&token).Error; err != nil {
 			logger.Errorf("invalid personal access token attempt: %s, error: %v", c.Request.URL.Path, err)
diff --git a/manager/models/peer.go b/manager/models/peer.go
index 852794ce..9fb11581 100644
--- a/manager/models/peer.go
+++ b/manager/models/peer.go
@@ -33,6 +33,7 @@ type Peer struct {
 	IP                 string           `gorm:"column:ip;type:varchar(256);index:uk_peer,unique;not null;comment:ip address" json:"ip"`
 	Port               int32            `gorm:"column:port;not null;comment:grpc service listening port" json:"port"`
 	DownloadPort       int32            `gorm:"column:download_port;not null;comment:download service listening port" json:"download_port"`
+	ProxyPort          int32            `gorm:"column:proxy_port;not null;comment:proxy service listening port" json:"proxy_port"`
 	ObjectStoragePort  int32            `gorm:"column:object_storage_port;comment:object storage service listening port" json:"object_storage_port"`
 	State              string           `gorm:"column:state;type:varchar(256);default:'inactive';comment:service state" json:"state"`
 	OS                 string           `gorm:"column:os;type:varchar(256);comment:os" json:"os"`
diff --git a/manager/rpcserver/manager_server_v2.go b/manager/rpcserver/manager_server_v2.go
index 4194d370..b169bd62 100644
--- a/manager/rpcserver/manager_server_v2.go
+++ b/manager/rpcserver/manager_server_v2.go
@@ -722,7 +722,7 @@ func (s *managerServerV2) listSchedulersByClusterID(ctx context.Context, req *ma
 
 	// Cache hit.
 	var pbListSchedulersResponse managerv2.ListSchedulersResponse
-	cacheKey := pkgredis.MakeSchedulersKeyForPeerInManager(req.Hostname, req.Ip, req.Version)
+	cacheKey := pkgredis.MakeSchedulersByClusterIDKeyForPeerInManager(uint(req.SchedulerClusterId))
 
 	if err := s.cache.Get(ctx, cacheKey, &pbListSchedulersResponse); err != nil {
 		log.Warnf("%s cache miss because of %s", cacheKey, err.Error())
diff --git a/manager/service/job.go b/manager/service/job.go
index f51517a6..47461998 100644
--- a/manager/service/job.go
+++ b/manager/service/job.go
@@ -352,6 +352,7 @@ func (s *service) createGetTaskJobsSync(ctx context.Context, layers []internaljo
 					Application:         file.Application,
 					FilteredQueryParams: file.FilteredQueryParams,
 					ConcurrentPeerCount: json.Args.ConcurrentPeerCount,
+					Timeout:             json.Args.Timeout,
 				},
 				SchedulerClusterIDs: json.SchedulerClusterIDs,
 			}, schedulers)
@@ -405,7 +406,7 @@ func (s *service) createGetTaskJobSync(ctx context.Context, json types.CreateGet
 		return nil, err
 	}
 
-	s.pollingJob(context.Background(), internaljob.GetTaskJob, job.ID, job.TaskID, 3, 5, 4)
+	s.pollingJob(context.Background(), internaljob.GetTaskJob, job.ID, job.TaskID, 3, 5, 60)
 	if err := s.db.WithContext(ctx).Preload("SeedPeerClusters").Preload("SchedulerClusters").First(&job, job.ID).Error; err != nil {
 		return nil, err
 	}
diff --git a/manager/service/peer.go b/manager/service/peer.go
index bdc3abac..92b85c82 100644
--- a/manager/service/peer.go
+++ b/manager/service/peer.go
@@ -32,6 +32,7 @@ func (s *service) CreatePeer(ctx context.Context, json types.CreatePeerRequest)
 		IP:                 json.IP,
 		Port:               json.Port,
 		DownloadPort:       json.DownloadPort,
+		ProxyPort:          json.ProxyPort,
 		ObjectStoragePort:  json.ObjectStoragePort,
 		State:              json.State,
 		OS:                 json.OS,
@@ -85,6 +86,7 @@ func (s *service) GetPeers(ctx context.Context, q types.GetPeersQuery) ([]models
 		IP:                 q.IP,
 		Port:               q.Port,
 		DownloadPort:       q.DownloadPort,
+		ProxyPort:          q.ProxyPort,
 		ObjectStoragePort:  q.ObjectStoragePort,
 		State:              q.State,
 		OS:                 q.OS,
diff --git a/manager/service/persistent_cache_task.go b/manager/service/persistent_cache_task.go
index f40d6bcd..9dcdd358 100644
--- a/manager/service/persistent_cache_task.go
+++ b/manager/service/persistent_cache_task.go
@@ -477,29 +477,29 @@ func (s *service) loadHost(ctx context.Context, schedulerClusterID uint, id stri
 	host.Network.Location = rawHost["location"]
 	host.Network.IDC = rawHost["idc"]
 
-	downloadRate, err := strconv.ParseUint(rawHost["download_rate"], 10, 64)
+	rxBandwidth, err := strconv.ParseUint(rawHost["rx_bandwidth"], 10, 64)
 	if err != nil {
 		return nil, err
 	}
-	host.Network.DownloadRate = downloadRate
+	host.Network.RxBandwidth = rxBandwidth
 
-	downloadRateLimit, err := strconv.ParseUint(rawHost["download_rate_limit"], 10, 64)
+	maxRxBandwidth, err := strconv.ParseUint(rawHost["max_rx_bandwidth"], 10, 64)
 	if err != nil {
 		return nil, err
 	}
-	host.Network.DownloadRateLimit = downloadRateLimit
+	host.Network.MaxRxBandwidth = maxRxBandwidth
 
-	uploadRate, err := strconv.ParseUint(rawHost["upload_rate"], 10, 64)
+	txBandwidth, err := strconv.ParseUint(rawHost["tx_bandwidth"], 10, 64)
 	if err != nil {
 		return nil, err
 	}
-	host.Network.UploadRate = uploadRate
+	host.Network.TxBandwidth = txBandwidth
 
-	uploadRateLimit, err := strconv.ParseUint(rawHost["upload_rate_limit"], 10, 64)
+	maxTxBandwidth, err := strconv.ParseUint(rawHost["max_tx_bandwidth"], 10, 64)
 	if err != nil {
 		return nil, err
 	}
-	host.Network.UploadRateLimit = uploadRateLimit
+	host.Network.MaxTxBandwidth = maxTxBandwidth
 
 	// Parse Disk information.
 	diskTotal, err := strconv.ParseUint(rawHost["disk_total"], 10, 64)
diff --git a/manager/types/peer.go b/manager/types/peer.go
index 265756e9..8f62f4aa 100644
--- a/manager/types/peer.go
+++ b/manager/types/peer.go
@@ -28,6 +28,7 @@ type CreatePeerRequest struct {
 	IP                 string `json:"ip" binding:"required"`
 	Port               int32  `json:"port" binding:"required"`
 	DownloadPort       int32  `json:"download_port" binding:"required"`
+	ProxyPort          int32  `json:"proxy_port" binding:"required"`
 	ObjectStoragePort  int32  `json:"object_storage_port" binding:"omitempty"`
 	State              string `json:"state" binding:"omitempty,oneof=active inactive"`
 	OS                 string `json:"os" binding:"omitempty"`
@@ -49,6 +50,7 @@ type GetPeersQuery struct {
 	IP                 string `form:"ip" binding:"omitempty"`
 	Port               int32  `form:"port" binding:"omitempty"`
 	DownloadPort       int32  `form:"download_port" binding:"omitempty"`
+	ProxyPort          int32  `form:"proxy_port" binding:"omitempty"`
 	ObjectStoragePort  int32  `form:"object_storage_port" binding:"omitempty"`
 	State              string `form:"state" binding:"omitempty,oneof=active inactive"`
 	OS                 string `form:"os" binding:"omitempty"`
diff --git a/manager/types/persistent_cache_task.go b/manager/types/persistent_cache_task.go
index 358fcb93..69b04594 100644
--- a/manager/types/persistent_cache_task.go
+++ b/manager/types/persistent_cache_task.go
@@ -235,17 +235,17 @@ type PersistentCacheHost struct {
 		// IDC is network idc.
 		IDC string `json:"idc" binding:"omitempty"`
 
-		// DownloadRate is download rate.
-		DownloadRate uint64 `json:"download_rate" binding:"omitempty"`
+		// RxBandwidth is download rate.
+		RxBandwidth uint64 `json:"rx_bandwidth" binding:"omitempty"`
 
-		// DownloadRateLimit is download rate limit.
-		DownloadRateLimit uint64 `json:"download_rate_limit" binding:"omitempty"`
+		// MaxRxBandwidth is download rate limit.
+		MaxRxBandwidth uint64 `json:"max_rx_bandwidth" binding:"omitempty"`
 
-		// UploadRate is upload rate.
-		UploadRate uint64 `json:"upload_rate" binding:"omitempty"`
+		// TxBandwidth is upload rate.
+		TxBandwidth uint64 `json:"tx_bandwidth" binding:"omitempty"`
 
-		// UploadRateLimit is upload rate limit.
-		UploadRateLimit uint64 `json:"upload_rate_limit" binding:"omitempty"`
+		// MaxTxBandwidth is upload rate limit.
+		MaxTxBandwidth uint64 `json:"max_tx_bandwidth" binding:"omitempty"`
 	} `json:"network" binding:"omitempty"`
 
 	// Disk contains disk information.
diff --git a/pkg/idgen/task_id.go b/pkg/idgen/task_id.go
index e61aac5a..f9877aee 100644
--- a/pkg/idgen/task_id.go
+++ b/pkg/idgen/task_id.go
@@ -189,5 +189,5 @@ func TaskIDV2ByContent(content string) string {
 
 // PersistentCacheTaskIDByContent generates persistent cache task id by content.
 func PersistentCacheTaskIDByContent(content string) string {
-	return pkgdigest.CRC32FromStrings(content)
+	return pkgdigest.SHA256FromStrings(content)
 }
diff --git a/pkg/redis/redis.go b/pkg/redis/redis.go
index 4113ab7b..9db9727e 100644
--- a/pkg/redis/redis.go
+++ b/pkg/redis/redis.go
@@ -126,6 +126,11 @@ func MakeSchedulersKeyForPeerInManager(hostname, ip, version string) string {
 	return MakeKeyInManager(PeersNamespace, fmt.Sprintf("%s-%s-%s:schedulers", hostname, ip, version))
 }
 
+// MakeSchedulersByClusterIDKeyForPeerInManager make schedulers by cluster ID key for peer in manager.
+func MakeSchedulersByClusterIDKeyForPeerInManager(schedulerClusterID uint) string {
+	return MakeKeyInManager(SchedulerClustersNamespace, fmt.Sprintf("%d:schedulers", schedulerClusterID))
+}
+
 // MakeSchedulerClusterKeyInManager make distributed rate limiter key in manager.
 func MakeDistributedRateLimiterKeyInManager(key string) string {
 	return MakeKeyInManager(RateLimitersNamespace, key)
diff --git a/scheduler/resource/persistentcache/host.go b/scheduler/resource/persistentcache/host.go
index 89af55b1..5a10aadb 100644
--- a/scheduler/resource/persistentcache/host.go
+++ b/scheduler/resource/persistentcache/host.go
@@ -43,6 +43,9 @@ type Host struct {
 	// DownloadPort is piece downloading port.
 	DownloadPort int32
 
+	// ProxyPort is the proxy server port.
+	ProxyPort int32
+
 	// DisableShared is whether the host is disabled for
 	// shared with other peers.
 	DisableShared bool
@@ -179,17 +182,17 @@ type Network struct {
 	// IDC where the peer host is located
 	IDC string
 
-	// Download rate of the host, unit is byte/s.
-	DownloadRate uint64
+	// RxBandwidth of the host, unit is byte/s.
+	RxBandwidth uint64
 
-	// Download rate limit of the host, unit is byte/s.
-	DownloadRateLimit uint64
+	// MaxRxBandwidth of the host, unit is byte/s.
+	MaxRxBandwidth uint64
 
-	// Upload rate of the host, unit is byte/s.
-	UploadRate uint64
+	// TxBandwidth of the host, unit is byte/s.
+	TxBandwidth uint64
 
-	// Upload rate limit of the host, unit is byte/s.
-	UploadRateLimit uint64
+	// MaxTxBandwidth of the host, unit is byte/s.
+	MaxTxBandwidth uint64
 }
 
 // Build contains content for build.
@@ -245,7 +248,7 @@ type Disk struct {
 
 // NewHost returns a new host.
 func NewHost(
-	id, hostname, ip, os, platform, platformFamily, platformVersion, kernelVersion string, port, downloadPort int32,
+	id, hostname, ip, os, platform, platformFamily, platformVersion, kernelVersion string, port, downloadPort, proxyPort int32,
 	schedulerClusterId uint64, disableShared bool, typ types.HostType, cpu CPU, memory Memory, network Network, disk Disk,
 	build Build, announceInterval time.Duration, createdAt, updatedAt time.Time, log *logger.SugaredLoggerOnWith,
 ) *Host {
@@ -256,6 +259,7 @@ func NewHost(
 		IP:                 ip,
 		Port:               port,
 		DownloadPort:       downloadPort,
+		ProxyPort:          proxyPort,
 		DisableShared:      disableShared,
 		OS:                 os,
 		Platform:           platform,
diff --git a/scheduler/resource/persistentcache/host_manager.go b/scheduler/resource/persistentcache/host_manager.go
index 637f5198..5fdd2528 100644
--- a/scheduler/resource/persistentcache/host_manager.go
+++ b/scheduler/resource/persistentcache/host_manager.go
@@ -111,6 +111,12 @@ func (h *hostManager) Load(ctx context.Context, hostID string) (*Host, bool) {
 		return nil, false
 	}
 
+	proxyPort, err := strconv.ParseInt(rawHost["proxy_port"], 10, 32)
+	if err != nil {
+		log.Errorf("parsing proxy port failed: %v", err)
+		return nil, false
+	}
+
 	// Set cpu fields from raw host.
 	schedulerClusterID, err := strconv.ParseUint(rawHost["scheduler_cluster_id"], 10, 64)
 	if err != nil {
@@ -288,25 +294,25 @@ func (h *hostManager) Load(ctx context.Context, hostID string) (*Host, bool) {
 		return nil, false
 	}
 
-	downloadRate, err := strconv.ParseUint(rawHost["network_download_rate"], 10, 64)
+	rxBandwidth, err := strconv.ParseUint(rawHost["network_rx_bandwidth"], 10, 64)
 	if err != nil {
 		log.Errorf("parsing download rate failed: %v", err)
 		return nil, false
 	}
 
-	downloadRateLimit, err := strconv.ParseUint(rawHost["network_download_rate_limit"], 10, 64)
+	maxRxBandwidth, err := strconv.ParseUint(rawHost["network_max_rx_bandwidth"], 10, 64)
 	if err != nil {
 		log.Errorf("parsing download rate limit failed: %v", err)
 		return nil, false
 	}
 
-	uploadRate, err := strconv.ParseUint(rawHost["network_upload_rate"], 10, 64)
+	txBandwidth, err := strconv.ParseUint(rawHost["network_tx_bandwidth"], 10, 64)
 	if err != nil {
 		log.Errorf("parsing upload rate failed: %v", err)
 		return nil, false
 	}
 
-	uploadRateLimit, err := strconv.ParseUint(rawHost["network_upload_rate_limit"], 10, 64)
+	maxTxBandwidth, err := strconv.ParseUint(rawHost["network_max_tx_bandwidth"], 10, 64)
 	if err != nil {
 		log.Errorf("parsing upload rate limit failed: %v", err)
 		return nil, false
@@ -317,10 +323,10 @@ func (h *hostManager) Load(ctx context.Context, hostID string) (*Host, bool) {
 		UploadTCPConnectionCount: uint32(networkUploadTCPConnectionCount),
 		Location:                 rawHost["network_location"],
 		IDC:                      rawHost["network_idc"],
-		DownloadRate:             downloadRate,
-		DownloadRateLimit:        downloadRateLimit,
-		UploadRate:               uploadRate,
-		UploadRateLimit:          uploadRateLimit,
+		RxBandwidth:              rxBandwidth,
+		MaxRxBandwidth:           maxRxBandwidth,
+		TxBandwidth:              txBandwidth,
+		MaxTxBandwidth:           maxTxBandwidth,
 	}
 
 	// Set disk fields from raw host.
@@ -434,6 +440,7 @@ func (h *hostManager) Load(ctx context.Context, hostID string) (*Host, bool) {
 		rawHost["kernel_version"],
 		int32(port),
 		int32(downloadPort),
+		int32(proxyPort),
 		uint64(schedulerClusterID),
 		disableShared,
 		pkgtypes.ParseHostType(rawHost["type"]),
@@ -464,58 +471,59 @@ local hostname = ARGV[3]
 local ip = ARGV[4]
 local port = ARGV[5]
 local download_port = ARGV[6]
-local disable_shared = tonumber(ARGV[7])
-local os = ARGV[8]
-local platform = ARGV[9]
-local platform_family = ARGV[10]
-local platform_version = ARGV[11]
-local kernel_version = ARGV[12]
-local cpu_logical_count = ARGV[13]
-local cpu_physical_count = ARGV[14]
-local cpu_percent = ARGV[15]
-local cpu_process_percent = ARGV[16]
-local cpu_times_user = ARGV[17]
-local cpu_times_system = ARGV[18]
-local cpu_times_idle = ARGV[19]
-local cpu_times_nice = ARGV[20]
-local cpu_times_iowait = ARGV[21]
-local cpu_times_irq = ARGV[22]
-local cpu_times_softirq = ARGV[23]
-local cpu_times_steal = ARGV[24]
-local cpu_times_guest = ARGV[25]
-local cpu_times_guest_nice = ARGV[26]
-local memory_total = ARGV[27]
-local memory_available = ARGV[28]
-local memory_used = ARGV[29]
-local memory_used_percent = ARGV[30]
-local memory_process_used_percent = ARGV[31]
-local memory_free = ARGV[32]
-local network_tcp_connection_count = ARGV[33]
-local network_upload_tcp_connection_count = ARGV[34]
-local network_location = ARGV[35]
-local network_idc = ARGV[36]
-local network_download_rate = ARGV[37]
-local network_download_rate_limit = ARGV[38]
-local network_upload_rate = ARGV[39]
-local network_upload_rate_limit = ARGV[40]
-local disk_total = ARGV[41]
-local disk_free = ARGV[42]
-local disk_used = ARGV[43]
-local disk_used_percent = ARGV[44]
-local disk_inodes_total = ARGV[45]
-local disk_inodes_used = ARGV[46]
-local disk_inodes_free = ARGV[47]
-local disk_inodes_used_percent = ARGV[48]
-local disk_write_bandwidth = ARGV[49]
-local disk_read_bandwidth = ARGV[50]
-local build_git_version = ARGV[51]
-local build_git_commit = ARGV[52]
-local build_go_version = ARGV[53]
-local build_platform = ARGV[54]
-local scheduler_cluster_id = ARGV[55]
-local announce_interval = ARGV[56]
-local created_at = ARGV[57]
-local updated_at = ARGV[58]
+local proxy_port = ARGV[7]
+local disable_shared = tonumber(ARGV[8])
+local os = ARGV[9]
+local platform = ARGV[10]
+local platform_family = ARGV[11]
+local platform_version = ARGV[12]
+local kernel_version = ARGV[13]
+local cpu_logical_count = ARGV[14]
+local cpu_physical_count = ARGV[15]
+local cpu_percent = ARGV[16]
+local cpu_process_percent = ARGV[17]
+local cpu_times_user = ARGV[18]
+local cpu_times_system = ARGV[19]
+local cpu_times_idle = ARGV[20]
+local cpu_times_nice = ARGV[21]
+local cpu_times_iowait = ARGV[22]
+local cpu_times_irq = ARGV[23]
+local cpu_times_softirq = ARGV[24]
+local cpu_times_steal = ARGV[25]
+local cpu_times_guest = ARGV[26]
+local cpu_times_guest_nice = ARGV[27]
+local memory_total = ARGV[28]
+local memory_available = ARGV[29]
+local memory_used = ARGV[30]
+local memory_used_percent = ARGV[31]
+local memory_process_used_percent = ARGV[32]
+local memory_free = ARGV[33]
+local network_tcp_connection_count = ARGV[34]
+local network_upload_tcp_connection_count = ARGV[35]
+local network_location = ARGV[36]
+local network_idc = ARGV[37]
+local network_rx_bandwidth = ARGV[38]
+local network_max_rx_bandwidth = ARGV[39]
+local network_tx_bandwidth = ARGV[40]
+local network_max_tx_bandwidth = ARGV[41]
+local disk_total = ARGV[42]
+local disk_free = ARGV[43]
+local disk_used = ARGV[44]
+local disk_used_percent = ARGV[45]
+local disk_inodes_total = ARGV[46]
+local disk_inodes_used = ARGV[47]
+local disk_inodes_free = ARGV[48]
+local disk_inodes_used_percent = ARGV[49]
+local disk_write_bandwidth = ARGV[50]
+local disk_read_bandwidth = ARGV[51]
+local build_git_version = ARGV[52]
+local build_git_commit = ARGV[53]
+local build_go_version = ARGV[54]
+local build_platform = ARGV[55]
+local scheduler_cluster_id = ARGV[56]
+local announce_interval = ARGV[57]
+local created_at = ARGV[58]
+local updated_at = ARGV[59]
 
 -- Perform HSET operation
 redis.call("HSET", host_key,
@@ -525,6 +533,7 @@ redis.call("HSET", host_key,
     "ip", ip,
     "port", port,
     "download_port", download_port,
+    "proxy_port", proxy_port,
     "disable_shared", disable_shared,
     "os", os,
     "platform", platform,
@@ -555,10 +564,10 @@ redis.call("HSET", host_key,
     "network_upload_tcp_connection_count", network_upload_tcp_connection_count,
     "network_location", network_location,
     "network_idc", network_idc,
-    "network_download_rate", network_download_rate,
-    "network_download_rate_limit", network_download_rate_limit,
-    "network_upload_rate", network_upload_rate,
-    "network_upload_rate_limit", network_upload_rate_limit,
+    "network_rx_bandwidth", network_rx_bandwidth,
+    "network_max_rx_bandwidth", network_max_rx_bandwidth,
+    "network_tx_bandwidth", network_tx_bandwidth,
+    "network_max_tx_bandwidth", network_max_tx_bandwidth,
     "disk_total", disk_total,
     "disk_free", disk_free,
     "disk_used", disk_used,
@@ -601,6 +610,7 @@ return true
 		host.IP,
 		host.Port,
 		host.DownloadPort,
+		host.ProxyPort,
 		host.DisableShared,
 		host.OS,
 		host.Platform,
@@ -631,10 +641,10 @@ return true
 		host.Network.UploadTCPConnectionCount,
 		host.Network.Location,
 		host.Network.IDC,
-		host.Network.DownloadRate,
-		host.Network.DownloadRateLimit,
-		host.Network.UploadRate,
-		host.Network.UploadRateLimit,
+		host.Network.RxBandwidth,
+		host.Network.MaxRxBandwidth,
+		host.Network.TxBandwidth,
+		host.Network.MaxTxBandwidth,
 		host.Disk.Total,
 		host.Disk.Free,
 		host.Disk.Used,
diff --git a/scheduler/resource/standard/host.go b/scheduler/resource/standard/host.go
index 09f02239..d9913bf7 100644
--- a/scheduler/resource/standard/host.go
+++ b/scheduler/resource/standard/host.go
@@ -156,6 +156,9 @@ type Host struct {
 	// DownloadPort is piece downloading port.
 	DownloadPort int32
 
+	// ProxyPort is proxy server port.
+	ProxyPort int32
+
 	// ObjectStoragePort is object storage port.
 	ObjectStoragePort int32
 
@@ -313,17 +316,17 @@ type Network struct {
 	// IDC where the peer host is located
 	IDC string
 
-	// Download rate of the host, unit is byte/s.
-	DownloadRate uint64
+	// RxBandwidth is download rate of the host, unit is byte/s.
+	RxBandwidth uint64
 
-	// Download rate limit of the host, unit is byte/s.
-	DownloadRateLimit uint64
+	// MaxRxBandwidth is max download rate of the host, unit is byte/s.
+	MaxRxBandwidth uint64
 
-	// Upload rate of the host, unit is byte/s.
-	UploadRate uint64
+	// TxBandwidth is upload rate of the host, unit is byte/s.
+	TxBandwidth uint64
 
-	// Upload rate limit of the host, unit is byte/s.
-	UploadRateLimit uint64
+	// MaxTxBandwidth is max upload rate of the host, unit is byte/s.
+	MaxTxBandwidth uint64
 }
 
 // Build contains content for build.
@@ -376,7 +379,7 @@ type Disk struct {
 
 // New host instance.
 func NewHost(
-	id, ip, hostname string, port, downloadPort int32,
+	id, ip, hostname string, port, downloadPort, proxyPort int32,
 	typ types.HostType, options ...HostOption,
 ) *Host {
 	// Calculate default of the concurrent upload limit by host type.
@@ -392,6 +395,7 @@ func NewHost(
 		Hostname:              hostname,
 		Port:                  port,
 		DownloadPort:          downloadPort,
+		ProxyPort:             proxyPort,
 		DisableShared:         false,
 		ConcurrentUploadLimit: atomic.NewInt32(int32(concurrentUploadLimit)),
 		ConcurrentUploadCount: atomic.NewInt32(0),
diff --git a/scheduler/scheduling/scheduling.go b/scheduler/scheduling/scheduling.go
index 5b47b1b6..55bc1bea 100644
--- a/scheduler/scheduling/scheduling.go
+++ b/scheduler/scheduling/scheduling.go
@@ -885,6 +885,7 @@ func constructSuccessNormalTaskResponse(candidateParents []*standard.Peer) *sche
 			Ip:              candidateParent.Host.IP,
 			Port:            candidateParent.Host.Port,
 			DownloadPort:    candidateParent.Host.DownloadPort,
+			ProxyPort:       candidateParent.Host.ProxyPort,
 			Os:              candidateParent.Host.OS,
 			Platform:        candidateParent.Host.Platform,
 			PlatformFamily:  candidateParent.Host.PlatformFamily,
@@ -921,10 +922,10 @@ func constructSuccessNormalTaskResponse(candidateParents []*standard.Peer) *sche
 				UploadTcpConnectionCount: candidateParent.Host.Network.UploadTCPConnectionCount,
 				Location:                 &candidateParent.Host.Network.Location,
 				Idc:                      &candidateParent.Host.Network.IDC,
-				DownloadRate:             candidateParent.Host.Network.DownloadRate,
-				DownloadRateLimit:        candidateParent.Host.Network.DownloadRateLimit,
-				UploadRate:               candidateParent.Host.Network.UploadRate,
-				UploadRateLimit:          candidateParent.Host.Network.UploadRateLimit,
+				RxBandwidth:              &candidateParent.Host.Network.RxBandwidth,
+				MaxRxBandwidth:           candidateParent.Host.Network.MaxRxBandwidth,
+				TxBandwidth:              &candidateParent.Host.Network.TxBandwidth,
+				MaxTxBandwidth:           candidateParent.Host.Network.MaxTxBandwidth,
 			},
 			Disk: &commonv2.Disk{
 				Total:             candidateParent.Host.Disk.Total,
diff --git a/scheduler/service/service_v1.go b/scheduler/service/service_v1.go
index 6ae9d28e..80c27bfe 100644
--- a/scheduler/service/service_v1.go
+++ b/scheduler/service/service_v1.go
@@ -547,7 +547,7 @@ func (v *V1) AnnounceHost(ctx context.Context, req *schedulerv1.AnnounceHostRequ
 		}
 
 		host = resource.NewHost(
-			req.GetId(), req.GetIp(), req.GetHostname(), req.GetPort(), req.GetDownloadPort(),
+			req.GetId(), req.GetIp(), req.GetHostname(), req.GetPort(), req.GetDownloadPort(), req.GetProxyPort(),
 			types.ParseHostType(req.GetType()), options...,
 		)
 
@@ -559,6 +559,7 @@ func (v *V1) AnnounceHost(ctx context.Context, req *schedulerv1.AnnounceHostRequ
 	// Host already exists and updates properties.
 	host.Port = req.GetPort()
 	host.DownloadPort = req.GetDownloadPort()
+	host.ProxyPort = req.GetProxyPort()
 	host.Type = types.ParseHostType(req.GetType())
 	host.OS = req.GetOs()
 	host.Platform = req.GetPlatform()
@@ -836,7 +837,7 @@ func (v *V1) storeHost(_ context.Context, peerHost *schedulerv1.PeerHost) *resou
 
 		host := resource.NewHost(
 			peerHost.Id, peerHost.Ip, peerHost.Hostname,
-			peerHost.RpcPort, peerHost.DownPort, types.HostTypeNormal,
+			peerHost.RpcPort, peerHost.DownPort, peerHost.ProxyPort, types.HostTypeNormal,
 			options...,
 		)
 
@@ -847,6 +848,7 @@ func (v *V1) storeHost(_ context.Context, peerHost *schedulerv1.PeerHost) *resou
 
 	host.Port = peerHost.RpcPort
 	host.DownloadPort = peerHost.DownPort
+	host.ProxyPort = peerHost.ProxyPort
 	host.Network.Location = peerHost.Location
 	host.Network.IDC = peerHost.Idc
 	host.UpdatedAt.Store(time.Now())
diff --git a/scheduler/service/service_v2.go b/scheduler/service/service_v2.go
index 4204d9a1..4295e1e2 100644
--- a/scheduler/service/service_v2.go
+++ b/scheduler/service/service_v2.go
@@ -378,6 +378,7 @@ func (v *V2) StatPeer(ctx context.Context, req *schedulerv2.StatPeerRequest) (*c
 		Ip:              peer.Host.IP,
 		Port:            peer.Host.Port,
 		DownloadPort:    peer.Host.DownloadPort,
+		ProxyPort:       peer.Host.ProxyPort,
 		Os:              peer.Host.OS,
 		Platform:        peer.Host.Platform,
 		PlatformFamily:  peer.Host.PlatformFamily,
@@ -414,10 +415,10 @@ func (v *V2) StatPeer(ctx context.Context, req *schedulerv2.StatPeerRequest) (*c
 			UploadTcpConnectionCount: peer.Host.Network.UploadTCPConnectionCount,
 			Location:                 &peer.Host.Network.Location,
 			Idc:                      &peer.Host.Network.IDC,
-			DownloadRate:             peer.Host.Network.DownloadRate,
-			DownloadRateLimit:        peer.Host.Network.DownloadRateLimit,
-			UploadRate:               peer.Host.Network.UploadRate,
-			UploadRateLimit:          peer.Host.Network.UploadRateLimit,
+			RxBandwidth:              &peer.Host.Network.RxBandwidth,
+			MaxRxBandwidth:           peer.Host.Network.MaxRxBandwidth,
+			TxBandwidth:              &peer.Host.Network.TxBandwidth,
+			MaxTxBandwidth:           peer.Host.Network.MaxTxBandwidth,
 		},
 		Disk: &commonv2.Disk{
 			Total:             peer.Host.Disk.Total,
@@ -638,10 +639,10 @@ func (v *V2) AnnounceHost(ctx context.Context, req *schedulerv2.AnnounceHostRequ
 				UploadTCPConnectionCount: req.Host.Network.GetUploadTcpConnectionCount(),
 				Location:                 req.Host.Network.GetLocation(),
 				IDC:                      req.Host.Network.GetIdc(),
-				DownloadRate:             req.Host.Network.GetDownloadRate(),
-				DownloadRateLimit:        req.Host.Network.GetDownloadRateLimit(),
-				UploadRate:               req.Host.Network.GetUploadRate(),
-				UploadRateLimit:          req.Host.Network.GetUploadRateLimit(),
+				RxBandwidth:              req.Host.Network.GetRxBandwidth(),
+				MaxRxBandwidth:           req.Host.Network.GetMaxRxBandwidth(),
+				TxBandwidth:              req.Host.Network.GetTxBandwidth(),
+				MaxTxBandwidth:           req.Host.Network.GetMaxTxBandwidth(),
 			}))
 		}
 
@@ -675,7 +676,7 @@ func (v *V2) AnnounceHost(ctx context.Context, req *schedulerv2.AnnounceHostRequ
 
 		host = standard.NewHost(
 			req.Host.GetId(), req.Host.GetIp(), req.Host.GetHostname(),
-			req.Host.GetPort(), req.Host.GetDownloadPort(), types.HostType(req.Host.GetType()),
+			req.Host.GetPort(), req.Host.GetDownloadPort(), req.Host.GetProxyPort(), types.HostType(req.Host.GetType()),
 			options...,
 		)
 
@@ -685,6 +686,7 @@ func (v *V2) AnnounceHost(ctx context.Context, req *schedulerv2.AnnounceHostRequ
 		// Host already exists and updates properties.
 		host.Port = req.Host.GetPort()
 		host.DownloadPort = req.Host.GetDownloadPort()
+		host.ProxyPort = req.Host.GetProxyPort()
 		host.Type = types.HostType(req.Host.GetType())
 		host.DisableShared = req.Host.GetDisableShared()
 		host.OS = req.Host.GetOs()
@@ -736,10 +738,10 @@ func (v *V2) AnnounceHost(ctx context.Context, req *schedulerv2.AnnounceHostRequ
 				UploadTCPConnectionCount: req.Host.Network.GetUploadTcpConnectionCount(),
 				Location:                 req.Host.Network.GetLocation(),
 				IDC:                      req.Host.Network.GetIdc(),
-				DownloadRate:             req.Host.Network.GetDownloadRate(),
-				DownloadRateLimit:        req.Host.Network.GetDownloadRateLimit(),
-				UploadRate:               req.Host.Network.GetUploadRate(),
-				UploadRateLimit:          req.Host.Network.GetUploadRateLimit(),
+				RxBandwidth:              req.Host.Network.GetRxBandwidth(),
+				MaxRxBandwidth:           req.Host.Network.GetMaxRxBandwidth(),
+				TxBandwidth:              req.Host.Network.GetTxBandwidth(),
+				MaxTxBandwidth:           req.Host.Network.GetMaxTxBandwidth(),
 			}
 		}
 
@@ -782,7 +784,7 @@ func (v *V2) AnnounceHost(ctx context.Context, req *schedulerv2.AnnounceHostRequ
 	if !loaded {
 		persistentCacheHost = persistentcache.NewHost(req.Host.GetId(), req.Host.GetHostname(), req.Host.GetIp(), req.Host.GetOs(),
 			req.Host.GetPlatform(), req.Host.GetPlatformFamily(), req.Host.GetPlatformVersion(), req.Host.GetKernelVersion(), req.Host.GetPort(),
-			req.Host.GetDownloadPort(), req.Host.GetSchedulerClusterId(), req.Host.GetDisableShared(), types.HostType(req.Host.GetType()),
+			req.Host.GetDownloadPort(), req.Host.GetProxyPort(), req.Host.GetSchedulerClusterId(), req.Host.GetDisableShared(), types.HostType(req.Host.GetType()),
 			persistentcache.CPU{
 				LogicalCount:   req.Host.Cpu.GetLogicalCount(),
 				PhysicalCount:  req.Host.Cpu.GetPhysicalCount(),
@@ -814,10 +816,10 @@ func (v *V2) AnnounceHost(ctx context.Context, req *schedulerv2.AnnounceHostRequ
 				UploadTCPConnectionCount: req.Host.Network.GetUploadTcpConnectionCount(),
 				Location:                 req.Host.Network.GetLocation(),
 				IDC:                      req.Host.Network.GetIdc(),
-				DownloadRate:             req.Host.Network.GetDownloadRate(),
-				DownloadRateLimit:        req.Host.Network.GetDownloadRateLimit(),
-				UploadRate:               req.Host.Network.GetUploadRate(),
-				UploadRateLimit:          req.Host.Network.GetUploadRateLimit(),
+				RxBandwidth:              req.Host.Network.GetRxBandwidth(),
+				MaxRxBandwidth:           req.Host.Network.GetMaxRxBandwidth(),
+				TxBandwidth:              req.Host.Network.GetTxBandwidth(),
+				MaxTxBandwidth:           req.Host.Network.GetMaxTxBandwidth(),
 			},
 			persistentcache.Disk{
 				Total:             req.Host.Disk.GetTotal(),
@@ -852,6 +854,7 @@ func (v *V2) AnnounceHost(ctx context.Context, req *schedulerv2.AnnounceHostRequ
 		// persistentCacheHost already exists and updates properties.
 		persistentCacheHost.Port = req.Host.GetPort()
 		persistentCacheHost.DownloadPort = req.Host.GetDownloadPort()
+		persistentCacheHost.ProxyPort = req.Host.GetProxyPort()
 		persistentCacheHost.Type = types.HostType(req.Host.GetType())
 		persistentCacheHost.DisableShared = req.Host.GetDisableShared()
 		persistentCacheHost.SchedulerClusterID = req.Host.GetSchedulerClusterId()
@@ -900,10 +903,10 @@ func (v *V2) AnnounceHost(ctx context.Context, req *schedulerv2.AnnounceHostRequ
 				UploadTCPConnectionCount: req.Host.Network.GetUploadTcpConnectionCount(),
 				Location:                 req.Host.Network.GetLocation(),
 				IDC:                      req.Host.Network.GetIdc(),
-				DownloadRate:             req.Host.Network.GetDownloadRate(),
-				DownloadRateLimit:        req.Host.Network.GetDownloadRateLimit(),
-				UploadRate:               req.Host.Network.GetUploadRate(),
-				UploadRateLimit:          req.Host.Network.GetUploadRateLimit(),
+				RxBandwidth:              req.Host.Network.GetRxBandwidth(),
+				MaxRxBandwidth:           req.Host.Network.GetMaxRxBandwidth(),
+				TxBandwidth:              req.Host.Network.GetTxBandwidth(),
+				MaxTxBandwidth:           req.Host.Network.GetMaxTxBandwidth(),
 			}
 		}
 
@@ -963,6 +966,7 @@ func (v *V2) ListHosts(ctx context.Context) (*schedulerv2.ListHostsResponse, err
 			Ip:              host.IP,
 			Port:            host.Port,
 			DownloadPort:    host.DownloadPort,
+			ProxyPort:       host.ProxyPort,
 			Os:              host.OS,
 			Platform:        host.Platform,
 			PlatformFamily:  host.PlatformFamily,
@@ -999,6 +1003,10 @@ func (v *V2) ListHosts(ctx context.Context) (*schedulerv2.ListHostsResponse, err
 				UploadTcpConnectionCount: host.Network.UploadTCPConnectionCount,
 				Location:                 &host.Network.Location,
 				Idc:                      &host.Network.IDC,
+				RxBandwidth:              &host.Network.RxBandwidth,
+				MaxRxBandwidth:           host.Network.MaxRxBandwidth,
+				TxBandwidth:              &host.Network.TxBandwidth,
+				MaxTxBandwidth:           host.Network.MaxTxBandwidth,
 			},
 			Disk: &commonv2.Disk{
 				Total:             host.Disk.Total,
@@ -1909,6 +1917,7 @@ func (v *V2) handleRegisterPersistentCachePeerRequest(ctx context.Context, strea
 					Ip:              parent.Host.IP,
 					Port:            parent.Host.Port,
 					DownloadPort:    parent.Host.DownloadPort,
+					ProxyPort:       parent.Host.ProxyPort,
 					Os:              parent.Host.OS,
 					Platform:        parent.Host.Platform,
 					PlatformFamily:  parent.Host.PlatformFamily,
@@ -1945,10 +1954,10 @@ func (v *V2) handleRegisterPersistentCachePeerRequest(ctx context.Context, strea
 						UploadTcpConnectionCount: parent.Host.Network.UploadTCPConnectionCount,
 						Location:                 &parent.Host.Network.Location,
 						Idc:                      &parent.Host.Network.IDC,
-						DownloadRate:             parent.Host.Network.DownloadRate,
-						DownloadRateLimit:        parent.Host.Network.DownloadRateLimit,
-						UploadRate:               parent.Host.Network.UploadRate,
-						UploadRateLimit:          parent.Host.Network.UploadRateLimit,
+						RxBandwidth:              &parent.Host.Network.RxBandwidth,
+						MaxRxBandwidth:           parent.Host.Network.MaxRxBandwidth,
+						TxBandwidth:              &parent.Host.Network.TxBandwidth,
+						MaxTxBandwidth:           parent.Host.Network.MaxTxBandwidth,
 					},
 					Disk: &commonv2.Disk{
 						Total:             parent.Host.Disk.Total,
@@ -2104,6 +2113,7 @@ func (v *V2) handleReschedulePersistentCachePeerRequest(ctx context.Context, str
 				Ip:              parent.Host.IP,
 				Port:            parent.Host.Port,
 				DownloadPort:    parent.Host.DownloadPort,
+				ProxyPort:       parent.Host.ProxyPort,
 				Os:              parent.Host.OS,
 				Platform:        parent.Host.Platform,
 				PlatformFamily:  parent.Host.PlatformFamily,
@@ -2140,10 +2150,10 @@ func (v *V2) handleReschedulePersistentCachePeerRequest(ctx context.Context, str
 					UploadTcpConnectionCount: parent.Host.Network.UploadTCPConnectionCount,
 					Location:                 &parent.Host.Network.Location,
 					Idc:                      &parent.Host.Network.IDC,
-					DownloadRate:             parent.Host.Network.DownloadRate,
-					DownloadRateLimit:        parent.Host.Network.DownloadRateLimit,
-					UploadRate:               parent.Host.Network.UploadRate,
-					UploadRateLimit:          parent.Host.Network.UploadRateLimit,
+					RxBandwidth:              &parent.Host.Network.RxBandwidth,
+					MaxRxBandwidth:           parent.Host.Network.MaxRxBandwidth,
+					TxBandwidth:              &parent.Host.Network.TxBandwidth,
+					MaxTxBandwidth:           parent.Host.Network.MaxTxBandwidth,
 				},
 				Disk: &commonv2.Disk{
 					Total:             parent.Host.Disk.Total,
@@ -2366,6 +2376,7 @@ func (v *V2) StatPersistentCachePeer(ctx context.Context, req *schedulerv2.StatP
 			Ip:              peer.Host.IP,
 			Port:            peer.Host.Port,
 			DownloadPort:    peer.Host.DownloadPort,
+			ProxyPort:       peer.Host.ProxyPort,
 			Os:              peer.Host.OS,
 			Platform:        peer.Host.Platform,
 			PlatformFamily:  peer.Host.PlatformFamily,
@@ -2402,10 +2413,10 @@ func (v *V2) StatPersistentCachePeer(ctx context.Context, req *schedulerv2.StatP
 				UploadTcpConnectionCount: peer.Host.Network.UploadTCPConnectionCount,
 				Location:                 &peer.Host.Network.Location,
 				Idc:                      &peer.Host.Network.IDC,
-				DownloadRate:             peer.Host.Network.DownloadRate,
-				DownloadRateLimit:        peer.Host.Network.DownloadRateLimit,
-				UploadRate:               peer.Host.Network.UploadRate,
-				UploadRateLimit:          peer.Host.Network.UploadRateLimit,
+				RxBandwidth:              &peer.Host.Network.RxBandwidth,
+				MaxRxBandwidth:           peer.Host.Network.MaxRxBandwidth,
+				TxBandwidth:              &peer.Host.Network.TxBandwidth,
+				MaxTxBandwidth:           peer.Host.Network.MaxTxBandwidth,
 			},
 			Disk: &commonv2.Disk{
 				Total:             peer.Host.Disk.Total,



Test patch:
diff --git a/client/daemon/announcer/announcer_test.go b/client/daemon/announcer/announcer_test.go
index eb73fb13..4511873f 100644
--- a/client/daemon/announcer/announcer_test.go
+++ b/client/daemon/announcer/announcer_test.go
@@ -35,6 +35,7 @@ func TestAnnouncer_New(t *testing.T) {
 		hostID             string
 		deamonPort         int32
 		deamonDownloadPort int32
+		daemonProxyPort    int32
 		expect             func(t *testing.T, announcer Announcer)
 	}{
 		{
@@ -43,6 +44,7 @@ func TestAnnouncer_New(t *testing.T) {
 			hostID:             "foo",
 			deamonPort:         8000,
 			deamonDownloadPort: 8001,
+			daemonProxyPort:    8002,
 			expect: func(t *testing.T, a Announcer) {
 				assert := assert.New(t)
 				instance := a.(*announcer)
@@ -67,6 +69,7 @@ func TestAnnouncer_New(t *testing.T) {
 				assert.Equal(instance.hostID, "")
 				assert.Equal(instance.daemonPort, int32(0))
 				assert.Equal(instance.daemonDownloadPort, int32(0))
+				assert.Equal(instance.daemonProxyPort, int32(0))
 				assert.NotNil(instance.managerClient)
 				assert.NotNil(instance.schedulerClient)
 			},
@@ -80,7 +83,7 @@ func TestAnnouncer_New(t *testing.T) {
 			mockManagerClient := managerclientmocks.NewMockV1(ctl)
 			mockSchedulerClient := schedulerclientmocks.NewMockV1(ctl)
 			mockDynconfig := configmocks.NewMockDynconfig(ctl)
-			tc.expect(t, New(tc.config, mockDynconfig, tc.hostID, tc.deamonPort, tc.deamonDownloadPort, mockSchedulerClient, WithManagerClient(mockManagerClient)))
+			tc.expect(t, New(tc.config, mockDynconfig, tc.hostID, tc.deamonPort, tc.deamonDownloadPort, tc.daemonProxyPort, mockSchedulerClient, WithManagerClient(mockManagerClient)))
 		})
 	}
 }
diff --git a/manager/handlers/peer_test.go b/manager/handlers/peer_test.go
index 1e07b72b..4a27b016 100644
--- a/manager/handlers/peer_test.go
+++ b/manager/handlers/peer_test.go
@@ -36,6 +36,7 @@ var (
 	mockPeerReqBody = `
 		{
 			"download_port": 8001,
+			"proxy_port": 8004,
 			"host_name": "foo",
 			"ip": "127.0.0.1",
 			"port": 8003,
@@ -48,6 +49,7 @@ var (
 		IP:                 "127.0.0.1",
 		Port:               8003,
 		DownloadPort:       8001,
+		ProxyPort:          8004,
 		SchedulerClusterID: 2,
 	}
 	mockPeerModel = &models.Peer{
@@ -57,6 +59,7 @@ var (
 		IP:                 "127.0.0.1",
 		Port:               8003,
 		DownloadPort:       8001,
+		ProxyPort:          8004,
 		SchedulerClusterID: 2,
 	}
 )
diff --git a/pkg/idgen/task_id_test.go b/pkg/idgen/task_id_test.go
index dd8cd302..b055cc52 100644
--- a/pkg/idgen/task_id_test.go
+++ b/pkg/idgen/task_id_test.go
@@ -219,7 +219,7 @@ func TestPersistentCacheTaskIDbyContent(t *testing.T) {
 			content: "This is a test file",
 			expect: func(t *testing.T, d any) {
 				assert := assert.New(t)
-				assert.Equal(d, "107352521")
+				assert.Equal(d, "e2d0fe1585a63ec6009c8016ff8dda8b17719a637405a4e23c0ff81339148249")
 			},
 		},
 	}
diff --git a/scheduler/resource/persistentcache/host_manager_test.go b/scheduler/resource/persistentcache/host_manager_test.go
index 94591f38..1d62c008 100644
--- a/scheduler/resource/persistentcache/host_manager_test.go
+++ b/scheduler/resource/persistentcache/host_manager_test.go
@@ -54,6 +54,7 @@ func TestHostManager_Load(t *testing.T) {
 					"ip":                                  "127.0.0.1",
 					"port":                                "8080",
 					"download_port":                       "8081",
+					"proxy_port":                          "8082",
 					"disable_shared":                      "false",
 					"os":                                  "linux",
 					"platform":                            "x86_64",
@@ -84,10 +85,10 @@ func TestHostManager_Load(t *testing.T) {
 					"network_upload_tcp_connection_count": "50",
 					"network_location":                    "location1",
 					"network_idc":                         "idc1",
-					"network_download_rate":               "1000000",
-					"network_download_rate_limit":         "2000000",
-					"network_upload_rate":                 "500000",
-					"network_upload_rate_limit":           "1000000",
+					"network_rx_bandwidth":                "1000000",
+					"network_max_rx_bandwidth":            "2000000",
+					"network_tx_bandwidth":                "500000",
+					"network_max_tx_bandwidth":            "1000000",
 					"disk_total":                          "100000000000",
 					"disk_free":                           "50000000000",
 					"disk_used":                           "50000000000",
@@ -116,6 +117,7 @@ func TestHostManager_Load(t *testing.T) {
 				IP:                 "127.0.0.1",
 				Port:               8080,
 				DownloadPort:       8081,
+				ProxyPort:          8082,
 				DisableShared:      false,
 				OS:                 "linux",
 				Platform:           "x86_64",
@@ -124,7 +126,7 @@ func TestHostManager_Load(t *testing.T) {
 				KernelVersion:      "5.10",
 				CPU:                CPU{LogicalCount: 4, PhysicalCount: 2, Percent: 50.0, ProcessPercent: 25.0, Times: CPUTimes{User: 10.0, System: 5.0, Idle: 100.0, Nice: 0.0, Iowait: 1.0, Irq: 0.5, Softirq: 0.2, Steal: 0.1, Guest: 0.0, GuestNice: 0.0}},
 				Memory:             Memory{Total: 8000000000, Available: 4000000000, Used: 4000000000, UsedPercent: 50.0, ProcessUsedPercent: 25.0, Free: 2000000000},
-				Network:            Network{TCPConnectionCount: 100, UploadTCPConnectionCount: 50, Location: "location1", IDC: "idc1", DownloadRate: 1000000, DownloadRateLimit: 2000000, UploadRate: 500000, UploadRateLimit: 1000000},
+				Network:            Network{TCPConnectionCount: 100, UploadTCPConnectionCount: 50, Location: "location1", IDC: "idc1", RxBandwidth: 1000000, MaxRxBandwidth: 2000000, TxBandwidth: 500000, MaxTxBandwidth: 1000000},
 				Disk:               Disk{Total: 100000000000, Free: 50000000000, Used: 50000000000, UsedPercent: 50.0, InodesTotal: 100000, InodesUsed: 50000, InodesFree: 50000, InodesUsedPercent: 50.0, WriteBandwidth: 10000000, ReadBandwidth: 20000000},
 				Build:              Build{GitVersion: "v1.0.0", GitCommit: "commit1", GoVersion: "1.16", Platform: "linux/amd64"},
 				SchedulerClusterID: 1,
@@ -343,6 +345,7 @@ func TestHostManager_Load(t *testing.T) {
 				assert.Equal(t, tt.expectedHost.IP, host.IP)
 				assert.Equal(t, tt.expectedHost.Port, host.Port)
 				assert.Equal(t, tt.expectedHost.DownloadPort, host.DownloadPort)
+				assert.Equal(t, tt.expectedHost.ProxyPort, host.ProxyPort)
 				assert.Equal(t, tt.expectedHost.DisableShared, host.DisableShared)
 				assert.Equal(t, tt.expectedHost.OS, host.OS)
 				assert.Equal(t, tt.expectedHost.Platform, host.Platform)
@@ -398,6 +401,7 @@ func TestHostManager_LoadAll(t *testing.T) {
 						"ip":                                  "127.0.0.1",
 						"port":                                "8080",
 						"download_port":                       "8081",
+						"proxy_port":                          "8082",
 						"disable_shared":                      "false",
 						"os":                                  "linux",
 						"platform":                            "x86_64",
@@ -428,10 +432,10 @@ func TestHostManager_LoadAll(t *testing.T) {
 						"network_upload_tcp_connection_count": "50",
 						"network_location":                    "location1",
 						"network_idc":                         "idc1",
-						"network_download_rate":               "1000000",
-						"network_download_rate_limit":         "2000000",
-						"network_upload_rate":                 "500000",
-						"network_upload_rate_limit":           "1000000",
+						"network_rx_bandwidth":                "1000000",
+						"network_max_rx_bandwidth":            "2000000",
+						"network_tx_bandwidth":                "500000",
+						"network_max_tx_bandwidth":            "1000000",
 						"disk_total":                          "100000000000",
 						"disk_free":                           "50000000000",
 						"disk_used":                           "50000000000",
@@ -472,6 +476,7 @@ func TestHostManager_LoadAll(t *testing.T) {
 						"ip":                                  "127.0.0.1",
 						"port":                                "8080",
 						"download_port":                       "8081",
+						"proxy_port":                          "8082",
 						"disable_shared":                      "false",
 						"os":                                  "linux",
 						"platform":                            "x86_64",
@@ -502,10 +507,10 @@ func TestHostManager_LoadAll(t *testing.T) {
 						"network_upload_tcp_connection_count": "50",
 						"network_location":                    "location1",
 						"network_idc":                         "idc1",
-						"network_download_rate":               "1000000",
-						"network_download_rate_limit":         "2000000",
-						"network_upload_rate":                 "500000",
-						"network_upload_rate_limit":           "1000000",
+						"network_rx_bandwidth":                "1000000",
+						"network_max_rx_bandwidth":            "2000000",
+						"network_tx_bandwidth":                "500000",
+						"network_max_tx_bandwidth":            "1000000",
 						"disk_total":                          "100000000000",
 						"disk_free":                           "50000000000",
 						"disk_used":                           "50000000000",
@@ -536,6 +541,7 @@ func TestHostManager_LoadAll(t *testing.T) {
 						"ip":                                  "127.0.0.1",
 						"port":                                "8080",
 						"download_port":                       "8081",
+						"proxy_port":                          "8082",
 						"disable_shared":                      "false",
 						"os":                                  "linux",
 						"platform":                            "x86_64",
@@ -566,10 +572,10 @@ func TestHostManager_LoadAll(t *testing.T) {
 						"network_upload_tcp_connection_count": "50",
 						"network_location":                    "location1",
 						"network_idc":                         "idc1",
-						"network_download_rate":               "1000000",
-						"network_download_rate_limit":         "2000000",
-						"network_upload_rate":                 "500000",
-						"network_upload_rate_limit":           "1000000",
+						"network_rx_bandwidth":                "1000000",
+						"network_max_rx_bandwidth":            "2000000",
+						"network_tx_bandwidth":                "500000",
+						"network_max_tx_bandwidth":            "1000000",
 						"disk_total":                          "100000000000",
 						"disk_free":                           "50000000000",
 						"disk_used":                           "50000000000",
@@ -723,6 +729,7 @@ func TestHostManager_RunGC(t *testing.T) {
 						"ip":                                  "127.0.0.1",
 						"port":                                "8080",
 						"download_port":                       "8081",
+						"proxy_port":                          "8082",
 						"disable_shared":                      "false",
 						"os":                                  "linux",
 						"platform":                            "x86_64",
@@ -753,10 +760,10 @@ func TestHostManager_RunGC(t *testing.T) {
 						"network_upload_tcp_connection_count": "50",
 						"network_location":                    "location1",
 						"network_idc":                         "idc1",
-						"network_download_rate":               "1000000",
-						"network_download_rate_limit":         "2000000",
-						"network_upload_rate":                 "500000",
-						"network_upload_rate_limit":           "1000000",
+						"network_rx_bandwidth":                "1000000",
+						"network_max_rx_bandwidth":            "2000000",
+						"network_tx_bandwidth":                "500000",
+						"network_max_tx_bandwidth":            "1000000",
 						"disk_total":                          "100000000000",
 						"disk_free":                           "50000000000",
 						"disk_used":                           "50000000000",
diff --git a/scheduler/resource/persistentcache/host_test.go b/scheduler/resource/persistentcache/host_test.go
index 8b265829..437855f2 100644
--- a/scheduler/resource/persistentcache/host_test.go
+++ b/scheduler/resource/persistentcache/host_test.go
@@ -35,6 +35,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -57,6 +58,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -105,10 +107,10 @@ var (
 		UploadTCPConnectionCount: 1,
 		Location:                 mockHostLocation,
 		IDC:                      mockHostIDC,
-		DownloadRate:             100,
-		DownloadRateLimit:        200,
-		UploadRate:               100,
-		UploadRateLimit:          200,
+		RxBandwidth:              100,
+		MaxRxBandwidth:           200,
+		TxBandwidth:              100,
+		MaxTxBandwidth:           200,
 	}
 
 	mockDisk = Disk{
@@ -150,6 +152,7 @@ func TestNewHost(t *testing.T) {
 		kernelVersion      string
 		port               int32
 		downloadPort       int32
+		proxyPort          int32
 		schedulerClusterId uint64
 		disableShared      bool
 		typ                types.HostType
@@ -175,6 +178,7 @@ func TestNewHost(t *testing.T) {
 			kernelVersion:      "5.10.0",
 			port:               8002,
 			downloadPort:       8001,
+			proxyPort:          8004,
 			schedulerClusterId: 1,
 			disableShared:      false,
 			typ:                types.HostTypeNormal,
@@ -209,10 +213,10 @@ func TestNewHost(t *testing.T) {
 				UploadTCPConnectionCount: 50,
 				Location:                 "us-west",
 				IDC:                      "test-idc",
-				DownloadRate:             1024 * 1024,
-				DownloadRateLimit:        2 * 1024 * 1024,
-				UploadRate:               512 * 1024,
-				UploadRateLimit:          1024 * 1024,
+				RxBandwidth:              1024 * 1024,
+				MaxRxBandwidth:           2 * 1024 * 1024,
+				TxBandwidth:              512 * 1024,
+				MaxTxBandwidth:           1024 * 1024,
 			},
 			disk: Disk{
 				Total:             1000 * 1024 * 1024 * 1024,
@@ -243,7 +247,7 @@ func TestNewHost(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			got := NewHost(
 				tc.id, tc.hostname, tc.ip, tc.os, tc.platform, tc.platformFamily, tc.platformVersion,
-				tc.kernelVersion, tc.port, tc.downloadPort, tc.schedulerClusterId, tc.disableShared,
+				tc.kernelVersion, tc.port, tc.downloadPort, tc.proxyPort, tc.schedulerClusterId, tc.disableShared,
 				tc.typ, tc.cpu, tc.memory, tc.network, tc.disk, tc.build, tc.announceInterval,
 				tc.createdAt, tc.updatedAt, tc.log,
 			)
@@ -258,6 +262,7 @@ func TestNewHost(t *testing.T) {
 			assert.Equal(t, tc.kernelVersion, got.KernelVersion)
 			assert.Equal(t, tc.port, got.Port)
 			assert.Equal(t, tc.downloadPort, got.DownloadPort)
+			assert.Equal(t, tc.proxyPort, got.ProxyPort)
 			assert.Equal(t, tc.schedulerClusterId, got.SchedulerClusterID)
 			assert.Equal(t, tc.disableShared, got.DisableShared)
 			assert.Equal(t, tc.typ, got.Type)
diff --git a/scheduler/resource/standard/host_manager_test.go b/scheduler/resource/standard/host_manager_test.go
index d254f710..b5904c53 100644
--- a/scheduler/resource/standard/host_manager_test.go
+++ b/scheduler/resource/standard/host_manager_test.go
@@ -135,7 +135,7 @@ func TestHostManager_Load(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			hostManager, err := newHostManager(mockHostGCConfig, gc)
 			if err != nil {
 				t.Fatal(err)
@@ -190,7 +190,7 @@ func TestHostManager_Store(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			hostManager, err := newHostManager(mockHostGCConfig, gc)
 			if err != nil {
 				t.Fatal(err)
@@ -243,7 +243,7 @@ func TestHostManager_LoadOrStore(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			hostManager, err := newHostManager(mockHostGCConfig, gc)
 			if err != nil {
 				t.Fatal(err)
@@ -298,7 +298,7 @@ func TestHostManager_Delete(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			hostManager, err := newHostManager(mockHostGCConfig, gc)
 			if err != nil {
 				t.Fatal(err)
@@ -321,10 +321,10 @@ func TestHostManager_LoadRandom(t *testing.T) {
 			hosts: []*Host{
 				NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type),
 				NewHost(
 					mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type),
+					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type),
 			},
 			mock: func(m *gc.MockGCMockRecorder) {
 				m.Add(gomock.Any()).Return(nil).Times(1)
@@ -346,10 +346,10 @@ func TestHostManager_LoadRandom(t *testing.T) {
 			hosts: []*Host{
 				NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type),
 				NewHost(
 					mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type),
+					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type),
 			},
 			mock: func(m *gc.MockGCMockRecorder) {
 				m.Add(gomock.Any()).Return(nil).Times(1)
@@ -389,10 +389,10 @@ func TestHostManager_LoadRandom(t *testing.T) {
 			hosts: []*Host{
 				NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type),
 				NewHost(
 					mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type),
+					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type),
 			},
 			mock: func(m *gc.MockGCMockRecorder) {
 				m.Add(gomock.Any()).Return(nil).Times(1)
@@ -479,7 +479,7 @@ func TestHostManager_RunGC(t *testing.T) {
 				assert := assert.New(t)
 				mockSeedHost := NewHost(
 					mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
+					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)
 				hostManager.Store(mockSeedHost)
 				err := hostManager.RunGC(context.Background())
 				assert.NoError(err)
@@ -523,7 +523,7 @@ func TestHostManager_RunGC(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(mockPeerID, mockTask, mockHost)
 			hostManager, err := newHostManager(mockHostGCConfig, gc)
diff --git a/scheduler/resource/standard/host_test.go b/scheduler/resource/standard/host_test.go
index d2edc49c..0310e596 100644
--- a/scheduler/resource/standard/host_test.go
+++ b/scheduler/resource/standard/host_test.go
@@ -38,6 +38,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -59,6 +60,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -106,10 +108,10 @@ var (
 		UploadTCPConnectionCount: 1,
 		Location:                 mockHostLocation,
 		IDC:                      mockHostIDC,
-		DownloadRate:             100,
-		DownloadRateLimit:        200,
-		UploadRate:               100,
-		UploadRateLimit:          200,
+		RxBandwidth:              100,
+		MaxRxBandwidth:           200,
+		TxBandwidth:              100,
+		MaxTxBandwidth:           200,
 	}
 
 	mockDisk = Disk{
@@ -156,6 +158,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.SchedulerClusterID, uint64(0))
 				assert.Equal(host.AnnounceInterval, time.Duration(0))
@@ -181,6 +184,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawSeedHost.IP)
 				assert.Equal(host.Port, mockRawSeedHost.Port)
 				assert.Equal(host.DownloadPort, mockRawSeedHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawSeedHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.SchedulerClusterID, uint64(0))
 				assert.Equal(host.AnnounceInterval, time.Duration(0))
@@ -207,6 +211,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.SchedulerClusterID, uint64(1))
 				assert.Equal(host.ConcurrentUploadLimit.Load(), int32(config.DefaultPeerConcurrentUploadLimit))
 				assert.Equal(host.ConcurrentUploadCount.Load(), int32(0))
@@ -231,6 +236,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(1))
 				assert.Equal(host.SchedulerClusterID, uint64(0))
 				assert.Equal(host.AnnounceInterval, time.Duration(0))
@@ -257,6 +263,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.SchedulerClusterID, uint64(0))
 				assert.Equal(host.AnnounceInterval, time.Duration(0))
@@ -283,6 +290,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.OS, "linux")
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -310,6 +318,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.Platform, "ubuntu")
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -337,6 +346,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.PlatformFamily, "debian")
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -364,6 +374,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.PlatformVersion, "22.04")
 				assert.Equal(host.AnnounceInterval, time.Duration(0))
@@ -390,6 +401,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.KernelVersion, "5.15.0-27-generic")
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -417,6 +429,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.EqualValues(host.CPU, mockCPU)
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -444,6 +457,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.EqualValues(host.Memory, mockMemory)
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -471,6 +485,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.EqualValues(host.Network, mockNetwork)
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -498,6 +513,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.EqualValues(host.Disk, mockDisk)
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -525,6 +541,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.EqualValues(host.Build, mockBuild)
 				assert.Equal(host.SchedulerClusterID, uint64(0))
@@ -552,6 +569,7 @@ func TestHost_NewHost(t *testing.T) {
 				assert.Equal(host.IP, mockRawHost.IP)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.ObjectStoragePort, int32(0))
 				assert.Equal(host.SchedulerClusterID, uint64(0))
 				assert.Equal(host.AnnounceInterval, 5*time.Minute)
@@ -572,7 +590,7 @@ func TestHost_NewHost(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			tc.expect(t, NewHost(
 				tc.rawHost.ID, tc.rawHost.IP, tc.rawHost.Hostname,
-				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.Type,
+				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.ProxyPort, tc.rawHost.Type,
 				tc.options...))
 		})
 	}
@@ -619,7 +637,7 @@ func TestHost_LoadPeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			host := NewHost(
 				tc.rawHost.ID, tc.rawHost.IP, tc.rawHost.Hostname,
-				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.Type)
+				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.ProxyPort, tc.rawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, host)
 
@@ -664,7 +682,7 @@ func TestHost_StorePeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			host := NewHost(
 				tc.rawHost.ID, tc.rawHost.IP, tc.rawHost.Hostname,
-				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.Type)
+				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.ProxyPort, tc.rawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(tc.peerID, mockTask, host)
 
@@ -710,7 +728,7 @@ func TestHost_DeletePeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			host := NewHost(
 				tc.rawHost.ID, tc.rawHost.IP, tc.rawHost.Hostname,
-				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.Type)
+				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.ProxyPort, tc.rawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, host)
 
@@ -762,7 +780,7 @@ func TestHost_LeavePeers(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			host := NewHost(
 				tc.rawHost.ID, tc.rawHost.IP, tc.rawHost.Hostname,
-				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.Type)
+				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.ProxyPort, tc.rawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, host)
 
@@ -814,7 +832,7 @@ func TestHost_FreeUploadCount(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			host := NewHost(
 				tc.rawHost.ID, tc.rawHost.IP, tc.rawHost.Hostname,
-				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.Type)
+				tc.rawHost.Port, tc.rawHost.DownloadPort, tc.rawHost.ProxyPort, tc.rawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, host)
 
diff --git a/scheduler/resource/standard/peer_manager_test.go b/scheduler/resource/standard/peer_manager_test.go
index 7c2b2e8e..7bd74a85 100644
--- a/scheduler/resource/standard/peer_manager_test.go
+++ b/scheduler/resource/standard/peer_manager_test.go
@@ -136,7 +136,7 @@ func TestPeerManager_Load(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, mockHost)
 			peerManager, err := newPeerManager(mockPeerGCConfig, gc)
@@ -193,7 +193,7 @@ func TestPeerManager_Store(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, mockHost)
 			peerManager, err := newPeerManager(mockPeerGCConfig, gc)
@@ -248,7 +248,7 @@ func TestPeerManager_LoadOrStore(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, mockHost)
 			peerManager, err := newPeerManager(mockPeerGCConfig, gc)
@@ -305,7 +305,7 @@ func TestPeerManager_Delete(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, mockHost)
 			peerManager, err := newPeerManager(mockPeerGCConfig, gc)
@@ -578,7 +578,7 @@ func TestPeerManager_RunGC(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, mockHost)
 			peerManager, err := newPeerManager(tc.gcConfig, gc)
diff --git a/scheduler/resource/standard/peer_test.go b/scheduler/resource/standard/peer_test.go
index bc4bc37f..bc73bd5a 100644
--- a/scheduler/resource/standard/peer_test.go
+++ b/scheduler/resource/standard/peer_test.go
@@ -168,7 +168,7 @@ func TestPeer_NewPeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			tc.expect(t, NewPeer(tc.id, mockTask, mockHost, tc.options...), mockTask, mockHost)
 		})
@@ -203,7 +203,7 @@ func TestPeer_AppendPieceCost(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -240,7 +240,7 @@ func TestPeer_PieceCosts(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -282,7 +282,7 @@ func TestPeer_LoadReportPieceResultStream(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			tc.expect(t, peer, stream)
@@ -315,7 +315,7 @@ func TestPeer_StoreReportPieceResultStream(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			tc.expect(t, peer, stream)
@@ -348,7 +348,7 @@ func TestPeer_DeleteReportPieceResultStream(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			tc.expect(t, peer, stream)
@@ -389,7 +389,7 @@ func TestPeer_LoadAnnouncePeerStream(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			tc.expect(t, peer, stream)
@@ -422,7 +422,7 @@ func TestPeer_StoreAnnouncePeerStream(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			tc.expect(t, peer, stream)
@@ -455,7 +455,7 @@ func TestPeer_DeleteAnnouncePeerStream(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			tc.expect(t, peer, stream)
@@ -511,7 +511,7 @@ func TestPeer_LoadPiece(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -552,7 +552,7 @@ func TestPeer_StorePiece(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -597,7 +597,7 @@ func TestPeer_DeletePiece(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -645,7 +645,7 @@ func TestPeer_Parents(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			seedPeer := NewPeer(mockSeedPeerID, mockTask, mockHost)
@@ -691,7 +691,7 @@ func TestPeer_Children(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			seedPeer := NewPeer(mockSeedPeerID, mockTask, mockHost)
@@ -773,7 +773,7 @@ func TestPeer_DownloadTinyFile(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -925,7 +925,7 @@ func TestPeer_CalculatePriority(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			peer := NewPeer(mockPeerID, mockTask, mockHost)
 			tc.mock(peer, dynconfig.EXPECT())
diff --git a/scheduler/resource/standard/task_manager_test.go b/scheduler/resource/standard/task_manager_test.go
index fa3c019f..254093cd 100644
--- a/scheduler/resource/standard/task_manager_test.go
+++ b/scheduler/resource/standard/task_manager_test.go
@@ -349,7 +349,7 @@ func TestTaskManager_RunGC(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, WithDigest(mockTaskDigest))
 			mockPeer := NewPeer(mockPeerID, mockTask, mockHost)
 			taskManager, err := newTaskManager(mockTaskGCConfig, gc)
diff --git a/scheduler/resource/standard/task_test.go b/scheduler/resource/standard/task_test.go
index b0b8f73a..470885d3 100644
--- a/scheduler/resource/standard/task_test.go
+++ b/scheduler/resource/standard/task_test.go
@@ -189,7 +189,7 @@ func TestTask_LoadPeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(mockPeerID, task, mockHost)
 
@@ -258,7 +258,7 @@ func TestTask_LoadRandomPeers(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			host := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 
 			tc.expect(t, task, host)
@@ -296,7 +296,7 @@ func TestTask_StorePeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(tc.peerID, task, mockHost)
 
@@ -338,7 +338,7 @@ func TestTask_DeletePeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(mockPeerID, task, mockHost)
 
@@ -377,7 +377,7 @@ func TestTask_PeerCount(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(mockPeerID, task, mockHost)
 
@@ -475,7 +475,7 @@ func TestTask_AddPeerEdge(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 
 			tc.expect(t, mockHost, task)
@@ -579,7 +579,7 @@ func TestTask_DeletePeerInEdges(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 
 			tc.expect(t, mockHost, task)
@@ -681,7 +681,7 @@ func TestTask_DeletePeerOutEdges(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 
 			tc.expect(t, mockHost, task)
@@ -768,7 +768,7 @@ func TestTask_CanAddPeerEdge(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 
 			tc.expect(t, mockHost, task)
@@ -831,7 +831,7 @@ func TestTask_PeerDegree(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 
 			tc.expect(t, mockHost, task)
@@ -894,7 +894,7 @@ func TestTask_PeerInDegree(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 
 			tc.expect(t, mockHost, task)
@@ -957,7 +957,7 @@ func TestTask_PeerOutDegree(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 
 			tc.expect(t, mockHost, task)
@@ -1028,7 +1028,7 @@ func TestTask_HasAvailablePeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(mockPeerID, task, mockHost)
 
@@ -1092,10 +1092,10 @@ func TestTask_LoadSeedPeer(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockSeedHost := NewHost(
 				mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
+				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(mockPeerID, task, mockHost)
 			mockSeedPeer := NewPeer(mockSeedPeerID, task, mockSeedHost)
@@ -1159,10 +1159,10 @@ func TestTask_IsSeedPeerFailed(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockSeedHost := NewHost(
 				mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
+				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(mockPeerID, task, mockHost)
 			mockSeedPeer := NewPeer(mockSeedPeerID, task, mockSeedHost)
@@ -1549,7 +1549,7 @@ func TestTask_ReportPieceResultToPeers(t *testing.T) {
 
 			mockHost := NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
 			mockPeer := NewPeer(mockPeerID, task, mockHost)
 			task.StorePeer(mockPeer)
diff --git a/scheduler/scheduling/evaluator/evaluator_base_test.go b/scheduler/scheduling/evaluator/evaluator_base_test.go
index a46ddce2..755dbdf0 100644
--- a/scheduler/scheduling/evaluator/evaluator_base_test.go
+++ b/scheduler/scheduling/evaluator/evaluator_base_test.go
@@ -40,6 +40,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -61,6 +62,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -108,10 +110,10 @@ var (
 		UploadTCPConnectionCount: 1,
 		Location:                 mockHostLocation,
 		IDC:                      mockHostIDC,
-		DownloadRate:             100,
-		DownloadRateLimit:        200,
-		UploadRate:               100,
-		UploadRateLimit:          200,
+		RxBandwidth:              100,
+		MaxRxBandwidth:           200,
+		TxBandwidth:              100,
+		MaxTxBandwidth:           200,
 	}
 
 	mockDisk = standard.Disk{
@@ -187,7 +189,7 @@ func TestEvaluatorBase_EvaluateParents(t *testing.T) {
 				standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 				standard.NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)),
 			totalPieceCount: 1,
 			mock: func(parent []*standard.Peer, child *standard.Peer) {
 			},
@@ -204,13 +206,13 @@ func TestEvaluatorBase_EvaluateParents(t *testing.T) {
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 			},
 			child: standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 				standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 				standard.NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)),
 			totalPieceCount: 1,
 			mock: func(parent []*standard.Peer, child *standard.Peer) {
 			},
@@ -229,33 +231,33 @@ func TestEvaluatorBase_EvaluateParents(t *testing.T) {
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 				standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						"bar", mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 				standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						"baz", mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 				standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						"bac", mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 				standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						"bae", mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 			},
 			child: standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 				standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 				standard.NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)),
 			totalPieceCount: 1,
 			mock: func(parents []*standard.Peer, child *standard.Peer) {
 				parents[1].Host.ConcurrentUploadCount.Add(4)
@@ -280,33 +282,33 @@ func TestEvaluatorBase_EvaluateParents(t *testing.T) {
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 				standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						"bar", mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 				standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						"baz", mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 				standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						"bac", mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 				standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 					standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 					standard.NewHost(
 						"bae", mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+						mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 			},
 			child: standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 				standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 				standard.NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)),
 			totalPieceCount: 1,
 			mock: func(parents []*standard.Peer, child *standard.Peer) {
 				parents[1].FinishedPieces.Set(0)
@@ -350,12 +352,12 @@ func TestEvaluatorBase_evaluate(t *testing.T) {
 				standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 				standard.NewHost(
 					mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 			child: standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 				standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 				standard.NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)),
 			totalPieceCount: 1,
 			mock: func(parent *standard.Peer, child *standard.Peer) {
 			},
@@ -370,12 +372,12 @@ func TestEvaluatorBase_evaluate(t *testing.T) {
 				standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 				standard.NewHost(
 					mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)),
+					mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)),
 			child: standard.NewPeer(idgen.PeerIDV1("127.0.0.1"),
 				standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest)),
 				standard.NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)),
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)),
 			totalPieceCount: 1,
 			mock: func(parent *standard.Peer, child *standard.Peer) {
 				parent.FinishedPieces.Set(0)
@@ -399,7 +401,7 @@ func TestEvaluatorBase_evaluate(t *testing.T) {
 func TestEvaluatorBase_calculatePieceScore(t *testing.T) {
 	mockHost := standard.NewHost(
 		mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-		mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+		mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 	mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 
 	tests := []struct {
@@ -561,7 +563,7 @@ func TestEvaluatorBase_calculatehostUploadSuccessScore(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			host := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			mockPeer := standard.NewPeer(mockPeerID, mockTask, host)
 			e := newEvaluatorBase()
@@ -611,7 +613,7 @@ func TestEvaluatorBase_calculateFreeUploadScore(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			host := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			mockPeer := standard.NewPeer(mockPeerID, mockTask, host)
 			e := newEvaluatorBase()
@@ -663,7 +665,7 @@ func TestEvaluatorBase_calculateHostTypeScore(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			e := newEvaluatorBase()
@@ -738,10 +740,10 @@ func TestEvaluatorBase_calculateIDCAffinityScore(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			dstHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			srcHost := standard.NewHost(
 				mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
+				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)
 			e := newEvaluatorBase()
 			tc.mock(dstHost, srcHost)
 			tc.expect(t, e.(*evaluatorBase).calculateIDCAffinityScore(dstHost.Network.IDC, srcHost.Network.IDC))
@@ -877,7 +879,7 @@ func TestEvaluatorBase_calculateMultiElementAffinityScore(t *testing.T) {
 func TestEvaluatorBase_IsBadParent(t *testing.T) {
 	mockHost := standard.NewHost(
 		mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-		mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+		mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 	mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 
 	tests := []struct {
diff --git a/scheduler/scheduling/scheduling_test.go b/scheduler/scheduling/scheduling_test.go
index 12981063..0f036d68 100644
--- a/scheduler/scheduling/scheduling_test.go
+++ b/scheduler/scheduling/scheduling_test.go
@@ -70,6 +70,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -91,6 +92,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -138,10 +140,10 @@ var (
 		UploadTCPConnectionCount: 1,
 		Location:                 mockHostLocation,
 		IDC:                      mockHostIDC,
-		DownloadRate:             100,
-		DownloadRateLimit:        200,
-		UploadRate:               100,
-		UploadRateLimit:          200,
+		RxBandwidth:              100,
+		MaxRxBandwidth:           200,
+		TxBandwidth:              100,
+		MaxTxBandwidth:           200,
 	}
 
 	mockDisk = standard.Disk{
@@ -438,12 +440,12 @@ func TestScheduling_ScheduleCandidateParents(t *testing.T) {
 			ctx, cancel := context.WithCancel(context.Background())
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			mockSeedHost := standard.NewHost(
 				mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
+				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)
 			seedPeer := standard.NewPeer(mockSeedPeerID, mockTask, mockSeedHost)
 			blocklist := set.NewSafeSet[string]()
 
@@ -709,12 +711,12 @@ func TestScheduling_ScheduleParentAndCandidateParents(t *testing.T) {
 			ctx, cancel := context.WithCancel(context.Background())
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			mockSeedHost := standard.NewHost(
 				mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
+				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)
 			seedPeer := standard.NewPeer(mockSeedPeerID, mockTask, mockSeedHost)
 			blocklist := set.NewSafeSet[string]()
 
@@ -1038,7 +1040,7 @@ func TestScheduling_FindCandidateParents(t *testing.T) {
 			persistentCacheResource := persistentcache.NewMockResource(ctl)
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -1046,7 +1048,7 @@ func TestScheduling_FindCandidateParents(t *testing.T) {
 			for i := range 11 {
 				mockHost := standard.NewHost(
 					idgen.HostIDV2("127.0.0.1", uuid.New().String(), false), mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 				peer := standard.NewPeer(idgen.PeerIDV1(fmt.Sprintf("127.0.0.%d", i)), mockTask, mockHost)
 				mockPeers = append(mockPeers, peer)
 			}
@@ -1356,7 +1358,7 @@ func TestScheduling_FindParentAndCandidateParents(t *testing.T) {
 			persistentCacheResource := persistentcache.NewMockResource(ctl)
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -1364,7 +1366,7 @@ func TestScheduling_FindParentAndCandidateParents(t *testing.T) {
 			for i := range 11 {
 				mockHost := standard.NewHost(
 					idgen.HostIDV2("127.0.0.1", uuid.New().String(), false), mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 				peer := standard.NewPeer(idgen.PeerIDV1(fmt.Sprintf("127.0.0.%d", i)), mockTask, mockHost)
 				mockPeers = append(mockPeers, peer)
 			}
@@ -1618,7 +1620,7 @@ func TestScheduling_FindSuccessParent(t *testing.T) {
 			persistentCacheResource := persistentcache.NewMockResource(ctl)
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -1626,7 +1628,7 @@ func TestScheduling_FindSuccessParent(t *testing.T) {
 			for i := range 11 {
 				mockHost := standard.NewHost(
 					idgen.HostIDV2("127.0.0.1", uuid.New().String(), false), mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 				peer := standard.NewPeer(idgen.PeerIDV1(fmt.Sprintf("127.0.0.%d", i)), mockTask, mockHost)
 				mockPeers = append(mockPeers, peer)
 			}
@@ -1687,6 +1689,7 @@ func TestScheduling_constructSuccessNormalTaskResponse(t *testing.T) {
 									Ip:              candidateParents[0].Host.IP,
 									Port:            candidateParents[0].Host.Port,
 									DownloadPort:    candidateParents[0].Host.DownloadPort,
+									ProxyPort:       candidateParents[0].Host.ProxyPort,
 									Os:              candidateParents[0].Host.OS,
 									Platform:        candidateParents[0].Host.Platform,
 									PlatformFamily:  candidateParents[0].Host.PlatformFamily,
@@ -1723,10 +1726,10 @@ func TestScheduling_constructSuccessNormalTaskResponse(t *testing.T) {
 										UploadTcpConnectionCount: candidateParents[0].Host.Network.UploadTCPConnectionCount,
 										Location:                 &candidateParents[0].Host.Network.Location,
 										Idc:                      &candidateParents[0].Host.Network.IDC,
-										DownloadRate:             candidateParents[0].Host.Network.DownloadRate,
-										DownloadRateLimit:        candidateParents[0].Host.Network.DownloadRateLimit,
-										UploadRate:               candidateParents[0].Host.Network.UploadRate,
-										UploadRateLimit:          candidateParents[0].Host.Network.UploadRateLimit,
+										RxBandwidth:              &candidateParents[0].Host.Network.RxBandwidth,
+										MaxRxBandwidth:           candidateParents[0].Host.Network.MaxRxBandwidth,
+										TxBandwidth:              &candidateParents[0].Host.Network.TxBandwidth,
+										MaxTxBandwidth:           candidateParents[0].Host.Network.MaxTxBandwidth,
 									},
 									Disk: &commonv2.Disk{
 										Total:             candidateParents[0].Host.Disk.Total,
@@ -1762,7 +1765,7 @@ func TestScheduling_constructSuccessNormalTaskResponse(t *testing.T) {
 			defer ctl.Finish()
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			candidateParents := []*standard.Peer{standard.NewPeer(idgen.PeerIDV1("127.0.0.1"), mockTask, mockHost, standard.WithRange(nethttp.Range{
 				Start:  1,
@@ -1812,7 +1815,7 @@ func TestScheduling_constructSuccessPeerPacket(t *testing.T) {
 			defer ctl.Finish()
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
diff --git a/scheduler/service/service_v1_test.go b/scheduler/service/service_v1_test.go
index 2d733c5a..2ba9b919 100644
--- a/scheduler/service/service_v1_test.go
+++ b/scheduler/service/service_v1_test.go
@@ -72,13 +72,14 @@ var (
 	}
 
 	mockPeerHost = &schedulerv1.PeerHost{
-		Id:       mockHostID,
-		Ip:       "127.0.0.1",
-		RpcPort:  8003,
-		DownPort: 8001,
-		Hostname: "baz",
-		Location: mockHostLocation,
-		Idc:      mockHostIDC,
+		Id:        mockHostID,
+		Ip:        "127.0.0.1",
+		RpcPort:   8003,
+		DownPort:  8001,
+		ProxyPort: 8004,
+		Hostname:  "baz",
+		Location:  mockHostLocation,
+		Idc:       mockHostIDC,
 	}
 
 	mockTaskBackToSourceLimit   int32  = 200
@@ -804,12 +805,12 @@ func TestServiceV1_RegisterPeerTask(t *testing.T) {
 
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			mockPeer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 			mockSeedHost := resource.NewHost(
 				mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
+				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)
 			mockSeedPeer := resource.NewPeer(mockSeedPeerID, mockTask, mockSeedHost)
 			tc.mock(
 				tc.req, mockPeer, mockSeedPeer,
@@ -1067,7 +1068,7 @@ func TestServiceV1_ReportPieceResult(t *testing.T) {
 
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			mockPeer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 			tc.mock(mockPeer, res, peerManager, res.EXPECT(), peerManager.EXPECT(), stream.EXPECT())
@@ -1216,7 +1217,7 @@ func TestServiceV1_ReportPeerResult(t *testing.T) {
 
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			mockPeer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 			tc.run(t, mockPeer, tc.req, svc, mockPeer, res, peerManager, res.EXPECT(), peerManager.EXPECT(), dynconfig.EXPECT())
@@ -1573,7 +1574,7 @@ func TestServiceV1_AnnounceTask(t *testing.T) {
 			svc := NewV1(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, res, scheduling, dynconfig)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			mockPeer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -1769,7 +1770,7 @@ func TestServiceV1_LeaveTask(t *testing.T) {
 			peerManager := resource.NewMockPeerManager(ctl)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			peer := resource.NewPeer(mockSeedPeerID, mockTask, mockHost)
 			svc := NewV1(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, res, scheduling, dynconfig)
@@ -2198,7 +2199,7 @@ func TestServiceV1_AnnounceHost(t *testing.T) {
 			hostManager := resource.NewMockHostManager(ctl)
 			host := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockPeerHost.ProxyPort, mockRawHost.Type)
 			svc := NewV1(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, res, scheduling, dynconfig)
 
 			tc.run(t, svc, tc.req, host, hostManager, res.EXPECT(), hostManager.EXPECT(), dynconfig.EXPECT())
@@ -2431,7 +2432,7 @@ func TestServiceV1_LeaveHost(t *testing.T) {
 			hostManager := resource.NewMockHostManager(ctl)
 			host := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			mockPeer := resource.NewPeer(mockSeedPeerID, mockTask, host)
 			svc := NewV1(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, res, scheduling, dynconfig)
@@ -2535,7 +2536,7 @@ func TestServiceV1_prefetchTask(t *testing.T) {
 			seedPeer := resource.NewMockSeedPeer(ctl)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			peer := resource.NewPeer(mockPeerID, task, mockHost)
 			svc := NewV1(tc.config, res, scheduling, dynconfig)
@@ -3001,10 +3002,10 @@ func TestServiceV1_triggerTask(t *testing.T) {
 
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockSeedHost := resource.NewHost(
 				mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
-				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
+				mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.ProxyPort, mockRawSeedHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			mockPeer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 			mockSeedPeer := resource.NewPeer(mockSeedPeerID, mockTask, mockSeedHost)
@@ -3127,6 +3128,7 @@ func TestServiceV1_storeHost(t *testing.T) {
 				assert.Equal(host.ID, mockRawHost.ID)
 				assert.Equal(host.Port, mockRawHost.Port)
 				assert.Equal(host.DownloadPort, mockRawHost.DownloadPort)
+				assert.Equal(host.ProxyPort, mockRawHost.ProxyPort)
 				assert.Equal(host.Network.Location, mockRawHost.Network.Location)
 				assert.Equal(host.Network.IDC, mockRawHost.Network.IDC)
 				assert.NotEqual(host.UpdatedAt.Load(), mockRawHost.UpdatedAt.Load())
@@ -3180,7 +3182,7 @@ func TestServiceV1_storeHost(t *testing.T) {
 			hostManager := resource.NewMockHostManager(ctl)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 
 			tc.mock(mockHost, hostManager, res.EXPECT(), hostManager.EXPECT(), dynconfig.EXPECT())
 			host := svc.storeHost(context.Background(), tc.peerHost)
@@ -3199,7 +3201,7 @@ func TestServiceV1_storePeer(t *testing.T) {
 			run: func(t *testing.T, svc *V1, peerManager resource.PeerManager, mr *resource.MockResourceMockRecorder, mp *resource.MockPeerManagerMockRecorder) {
 				mockHost := resource.NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 				mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 				mockPeer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 
@@ -3219,7 +3221,7 @@ func TestServiceV1_storePeer(t *testing.T) {
 			run: func(t *testing.T, svc *V1, peerManager resource.PeerManager, mr *resource.MockResourceMockRecorder, mp *resource.MockPeerManagerMockRecorder) {
 				mockHost := resource.NewHost(
 					mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-					mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+					mockRawHost.Port, mockRawHost.DownloadPort, mockPeerHost.ProxyPort, mockRawHost.Type)
 				mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 				gomock.InOrder(
 					mr.PeerManager().Return(peerManager).Times(1),
@@ -3320,7 +3322,7 @@ func TestServiceV1_triggerSeedPeerTask(t *testing.T) {
 			seedPeer := resource.NewMockSeedPeer(ctl)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			task := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			peer := resource.NewPeer(mockPeerID, task, mockHost)
 			svc := NewV1(&config.Config{Scheduler: mockSchedulerConfig, SeedPeer: mockSeedPeerConfig}, res, scheduling, dynconfig)
@@ -3400,7 +3402,7 @@ func TestServiceV1_handleBeginOfPiece(t *testing.T) {
 			dynconfig := configmocks.NewMockDynconfigInterface(ctl)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			peer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV1(&config.Config{Scheduler: mockSchedulerConfig}, res, scheduling, dynconfig)
@@ -3415,7 +3417,7 @@ func TestServiceV1_handleBeginOfPiece(t *testing.T) {
 func TestServiceV1_handlePieceSuccess(t *testing.T) {
 	mockHost := resource.NewHost(
 		mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-		mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+		mockRawHost.Port, mockRawHost.DownloadPort, mockPeerHost.ProxyPort, mockRawHost.Type)
 	mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 
 	tests := []struct {
@@ -3727,7 +3729,7 @@ func TestServiceV1_handlePieceFail(t *testing.T) {
 			peerManager := resource.NewMockPeerManager(ctl)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			peer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 			parent := resource.NewPeer(mockSeedPeerID, mockTask, mockHost)
@@ -3851,7 +3853,7 @@ func TestServiceV1_handlePeerSuccess(t *testing.T) {
 			mockRawHost.DownloadPort = int32(port)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockPeerHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			peer := resource.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV1(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, res, scheduling, dynconfig)
@@ -3931,7 +3933,7 @@ func TestServiceV1_handlePeerFail(t *testing.T) {
 			svc := NewV1(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, res, scheduling, dynconfig)
 			mockHost := resource.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockPeerHost.ProxyPort, mockRawHost.Type)
 			mockTask := resource.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, resource.WithDigest(mockTaskDigest))
 			peer := resource.NewPeer(mockSeedPeerID, mockTask, mockHost)
 			child := resource.NewPeer(mockPeerID, mockTask, mockHost)
diff --git a/scheduler/service/service_v2_test.go b/scheduler/service/service_v2_test.go
index 51e1a897..a59b17d6 100644
--- a/scheduler/service/service_v2_test.go
+++ b/scheduler/service/service_v2_test.go
@@ -65,6 +65,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -86,6 +87,7 @@ var (
 		IP:              "127.0.0.1",
 		Port:            8003,
 		DownloadPort:    8001,
+		ProxyPort:       8004,
 		OS:              "darwin",
 		Platform:        "darwin",
 		PlatformFamily:  "Standalone Workstation",
@@ -162,6 +164,7 @@ var (
 		IP:                 "127.0.0.1",
 		Port:               8003,
 		DownloadPort:       8001,
+		ProxyPort:          8004,
 		OS:                 "darwin",
 		Platform:           "darwin",
 		PlatformFamily:     "Standalone Workstation",
@@ -353,6 +356,7 @@ func TestServiceV2_StatPeer(t *testing.T) {
 						Ip:              peer.Host.IP,
 						Port:            peer.Host.Port,
 						DownloadPort:    peer.Host.DownloadPort,
+						ProxyPort:       peer.Host.ProxyPort,
 						Os:              peer.Host.OS,
 						Platform:        peer.Host.Platform,
 						PlatformFamily:  peer.Host.PlatformFamily,
@@ -389,10 +393,10 @@ func TestServiceV2_StatPeer(t *testing.T) {
 							UploadTcpConnectionCount: peer.Host.Network.UploadTCPConnectionCount,
 							Location:                 &peer.Host.Network.Location,
 							Idc:                      &peer.Host.Network.IDC,
-							DownloadRate:             peer.Host.Network.DownloadRate,
-							DownloadRateLimit:        peer.Host.Network.DownloadRateLimit,
-							UploadRate:               peer.Host.Network.UploadRate,
-							UploadRateLimit:          peer.Host.Network.UploadRateLimit,
+							RxBandwidth:              &peer.Host.Network.RxBandwidth,
+							MaxRxBandwidth:           peer.Host.Network.MaxRxBandwidth,
+							TxBandwidth:              &peer.Host.Network.TxBandwidth,
+							MaxTxBandwidth:           peer.Host.Network.MaxTxBandwidth,
 						},
 						Disk: &commonv2.Disk{
 							Total:             peer.Host.Disk.Total,
@@ -433,7 +437,7 @@ func TestServiceV2_StatPeer(t *testing.T) {
 			peerManager := standard.NewMockPeerManager(ctl)
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockSeedPeerID, mockTask, mockHost, standard.WithRange(mockPeerRange))
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -507,7 +511,7 @@ func TestServiceV2_DeletePeer(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockSeedPeerID, mockTask, mockHost, standard.WithRange(mockPeerRange))
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -658,10 +662,10 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 						UploadTcpConnectionCount: mockNetwork.UploadTCPConnectionCount,
 						Location:                 &mockNetwork.Location,
 						Idc:                      &mockNetwork.IDC,
-						DownloadRate:             mockNetwork.DownloadRate,
-						DownloadRateLimit:        mockNetwork.DownloadRateLimit,
-						UploadRate:               mockNetwork.UploadRate,
-						UploadRateLimit:          mockNetwork.UploadRateLimit,
+						RxBandwidth:              &mockNetwork.RxBandwidth,
+						MaxRxBandwidth:           mockNetwork.MaxRxBandwidth,
+						TxBandwidth:              &mockNetwork.TxBandwidth,
+						MaxTxBandwidth:           mockNetwork.MaxTxBandwidth,
 					},
 					Disk: &commonv2.Disk{
 						Total:             mockDisk.Total,
@@ -796,10 +800,10 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 						UploadTcpConnectionCount: mockNetwork.UploadTCPConnectionCount,
 						Location:                 &mockNetwork.Location,
 						Idc:                      &mockNetwork.IDC,
-						DownloadRate:             mockNetwork.DownloadRate,
-						DownloadRateLimit:        mockNetwork.DownloadRateLimit,
-						UploadRate:               mockNetwork.UploadRate,
-						UploadRateLimit:          mockNetwork.UploadRateLimit,
+						RxBandwidth:              &mockNetwork.RxBandwidth,
+						MaxRxBandwidth:           mockNetwork.MaxRxBandwidth,
+						TxBandwidth:              &mockNetwork.TxBandwidth,
+						MaxTxBandwidth:           mockNetwork.MaxTxBandwidth,
 					},
 					Disk: &commonv2.Disk{
 						Total:             mockDisk.Total,
@@ -934,10 +938,10 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 						UploadTcpConnectionCount: mockNetwork.UploadTCPConnectionCount,
 						Location:                 &mockNetwork.Location,
 						Idc:                      &mockNetwork.IDC,
-						DownloadRate:             mockNetwork.DownloadRate,
-						DownloadRateLimit:        mockNetwork.DownloadRateLimit,
-						UploadRate:               mockNetwork.UploadRate,
-						UploadRateLimit:          mockNetwork.UploadRateLimit,
+						RxBandwidth:              &mockNetwork.RxBandwidth,
+						MaxRxBandwidth:           mockNetwork.MaxRxBandwidth,
+						TxBandwidth:              &mockNetwork.TxBandwidth,
+						MaxTxBandwidth:           mockNetwork.MaxTxBandwidth,
 					},
 					Disk: &commonv2.Disk{
 						Total:             mockDisk.Total,
@@ -1068,10 +1072,10 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 						UploadTcpConnectionCount: mockNetwork.UploadTCPConnectionCount,
 						Location:                 &mockNetwork.Location,
 						Idc:                      &mockNetwork.IDC,
-						DownloadRate:             mockNetwork.DownloadRate,
-						DownloadRateLimit:        mockNetwork.DownloadRateLimit,
-						UploadRate:               mockNetwork.UploadRate,
-						UploadRateLimit:          mockNetwork.UploadRateLimit,
+						RxBandwidth:              &mockNetwork.RxBandwidth,
+						MaxRxBandwidth:           mockNetwork.MaxRxBandwidth,
+						TxBandwidth:              &mockNetwork.TxBandwidth,
+						MaxTxBandwidth:           mockNetwork.MaxTxBandwidth,
 					},
 					Disk: &commonv2.Disk{
 						Total:             mockDisk.Total,
@@ -1202,10 +1206,10 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 						UploadTcpConnectionCount: mockNetwork.UploadTCPConnectionCount,
 						Location:                 &mockNetwork.Location,
 						Idc:                      &mockNetwork.IDC,
-						DownloadRate:             mockNetwork.DownloadRate,
-						DownloadRateLimit:        mockNetwork.DownloadRateLimit,
-						UploadRate:               mockNetwork.UploadRate,
-						UploadRateLimit:          mockNetwork.UploadRateLimit,
+						RxBandwidth:              &mockNetwork.RxBandwidth,
+						MaxRxBandwidth:           mockNetwork.MaxRxBandwidth,
+						TxBandwidth:              &mockNetwork.TxBandwidth,
+						MaxTxBandwidth:           mockNetwork.MaxTxBandwidth,
 					},
 					Disk: &commonv2.Disk{
 						Total:             mockDisk.Total,
@@ -1303,6 +1307,7 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 					Ip:              "127.0.0.1",
 					Port:            8003,
 					DownloadPort:    8001,
+					ProxyPort:       8004,
 					DisableShared:   false,
 					Os:              "darwin",
 					Platform:        "darwin",
@@ -1340,10 +1345,10 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 						UploadTcpConnectionCount: mockNetwork.UploadTCPConnectionCount,
 						Location:                 &mockNetwork.Location,
 						Idc:                      &mockNetwork.IDC,
-						DownloadRate:             mockNetwork.DownloadRate,
-						DownloadRateLimit:        mockNetwork.DownloadRateLimit,
-						UploadRate:               mockNetwork.UploadRate,
-						UploadRateLimit:          mockNetwork.UploadRateLimit,
+						RxBandwidth:              &mockNetwork.RxBandwidth,
+						MaxRxBandwidth:           mockNetwork.MaxRxBandwidth,
+						TxBandwidth:              &mockNetwork.TxBandwidth,
+						MaxTxBandwidth:           mockNetwork.MaxTxBandwidth,
 					},
 					Disk: &commonv2.Disk{
 						Total:             mockDisk.Total,
@@ -1380,6 +1385,7 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 						assert.Equal(host.IP, req.Host.Ip)
 						assert.Equal(host.Port, req.Host.Port)
 						assert.Equal(host.DownloadPort, req.Host.DownloadPort)
+						assert.Equal(host.ProxyPort, req.Host.ProxyPort)
 						assert.Equal(host.DisableShared, req.Host.DisableShared)
 						assert.Equal(host.OS, req.Host.Os)
 						assert.Equal(host.Platform, req.Host.Platform)
@@ -1418,11 +1424,11 @@ func TestServiceV2_AnnounceHost(t *testing.T) {
 			persistentcacheHostManager := persistentcache.NewMockHostManager(ctl)
 			host := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			persistentCacheHost := persistentcache.NewHost(
 				mockRawPersistentCacheHost.ID, mockRawPersistentCacheHost.Hostname, mockRawPersistentCacheHost.IP,
 				mockRawPersistentCacheHost.OS, mockRawPersistentCacheHost.Platform, mockRawPersistentCacheHost.PlatformFamily, mockRawPersistentCacheHost.PlatformVersion, mockRawPersistentCacheHost.KernelVersion,
-				mockRawPersistentCacheHost.Port, mockRawPersistentCacheHost.DownloadPort, mockRawPersistentCacheHost.SchedulerClusterID, mockRawPersistentCacheHost.DisableShared, pkgtypes.HostType(mockRawPersistentCacheHost.Type),
+				mockRawPersistentCacheHost.Port, mockRawPersistentCacheHost.DownloadPort, mockRawPersistentCacheHost.ProxyPort, mockRawPersistentCacheHost.SchedulerClusterID, mockRawPersistentCacheHost.DisableShared, pkgtypes.HostType(mockRawPersistentCacheHost.Type),
 				mockRawPersistentCacheHost.CPU, mockRawPersistentCacheHost.Memory, mockRawPersistentCacheHost.Network, mockRawPersistentCacheHost.Disk,
 				mockRawPersistentCacheHost.Build, mockRawPersistentCacheHost.AnnounceInterval, mockRawPersistentCacheHost.CreatedAt, mockRawPersistentCacheHost.UpdatedAt, mockRawHost.Log)
 
@@ -1476,6 +1482,7 @@ func TestServiceV2_ListHosts(t *testing.T) {
 					Ip:           "127.0.0.1",
 					Port:         8003,
 					DownloadPort: mockRawHost.DownloadPort,
+					ProxyPort:    mockRawHost.ProxyPort,
 					Cpu: &commonv2.CPU{
 						LogicalCount:   mockCPU.LogicalCount,
 						PhysicalCount:  mockCPU.PhysicalCount,
@@ -1507,10 +1514,10 @@ func TestServiceV2_ListHosts(t *testing.T) {
 						UploadTcpConnectionCount: mockNetwork.UploadTCPConnectionCount,
 						Location:                 &mockNetwork.Location,
 						Idc:                      &mockNetwork.IDC,
-						DownloadRate:             mockNetwork.DownloadRate,
-						DownloadRateLimit:        mockNetwork.DownloadRateLimit,
-						UploadRate:               mockNetwork.UploadRate,
-						UploadRateLimit:          mockNetwork.UploadRateLimit,
+						RxBandwidth:              &mockNetwork.RxBandwidth,
+						MaxRxBandwidth:           mockNetwork.MaxRxBandwidth,
+						TxBandwidth:              &mockNetwork.TxBandwidth,
+						MaxTxBandwidth:           mockNetwork.MaxTxBandwidth,
 					},
 					Disk: &commonv2.Disk{
 						Total:             mockDisk.Total,
@@ -1546,7 +1553,7 @@ func TestServiceV2_ListHosts(t *testing.T) {
 
 			hostManager := standard.NewMockHostManager(ctl)
 			host := standard.NewHost(
-				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname, mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type,
+				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname, mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type,
 				standard.WithCPU(mockCPU), standard.WithMemory(mockMemory), standard.WithNetwork(mockNetwork), standard.WithDisk(mockDisk), standard.WithBuild(mockBuild))
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
 
@@ -1624,7 +1631,7 @@ func TestServiceV2_DeleteHost(t *testing.T) {
 			hostManager := standard.NewMockHostManager(ctl)
 			host := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			mockPeer := standard.NewPeer(mockSeedPeerID, mockTask, host)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig, Metrics: config.MetricsConfig{EnableHost: true}}, resource, nil, scheduling, job, internalJobImage, dynconfig)
@@ -1928,7 +1935,7 @@ func TestServiceV2_handleRegisterPeerRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			seedPeer := standard.NewPeer(mockSeedPeerID, mockTask, mockHost)
@@ -2023,7 +2030,7 @@ func TestServiceV2_handleDownloadPeerStartedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -2117,7 +2124,7 @@ func TestServiceV2_handleDownloadPeerBackToSourceStartedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -2190,7 +2197,7 @@ func TestServiceV2_handleRescheduleRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -2265,7 +2272,7 @@ func TestServiceV2_handleDownloadPeerFinishedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -2463,7 +2470,7 @@ func TestServiceV2_handleDownloadPeerBackToSourceFinishedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockHost.IP = ip
 			mockHost.DownloadPort = int32(port)
 
@@ -2540,7 +2547,7 @@ func TestServiceV2_handleDownloadPeerFailedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -2661,7 +2668,7 @@ func TestServiceV2_handleDownloadPeerBackToSourceFailedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -2821,7 +2828,7 @@ func TestServiceV2_handleDownloadPieceFinishedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -2948,7 +2955,7 @@ func TestServiceV2_handleDownloadPieceBackToSourceFinishedRequest(t *testing.T)
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -3060,7 +3067,7 @@ func TestServiceV2_handleDownloadPieceFailedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -3127,7 +3134,7 @@ func TestServiceV2_handleDownloadPieceBackToSourceFailedRequest(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -3343,7 +3350,7 @@ func TestServiceV2_handleResource(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			mockPeer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&config.Config{Scheduler: mockSchedulerConfig}, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)
@@ -3621,7 +3628,7 @@ func TestServiceV2_downloadTaskBySeedPeer(t *testing.T) {
 
 			mockHost := standard.NewHost(
 				mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
-				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
+				mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.ProxyPort, mockRawHost.Type)
 			mockTask := standard.NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_STANDARD, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit, standard.WithDigest(mockTaskDigest))
 			peer := standard.NewPeer(mockPeerID, mockTask, mockHost)
 			svc := NewV2(&tc.config, resource, persistentCacheResource, scheduling, job, internalJobImage, dynconfig)