62556


## 概要

現在、勉強の為にgRPC+Go+React+TypeScriptを用いた個人開発を行っています。  
ReactとGoの間にはEnvoy Proxyを置いています。  
gRPCは初めてということもあり、新規会員登録機能においてgRPCの接続テストを行っています。  
具体的には、新規会員登録機能にアクセスするとgRPCでリクエストを送り、それに対するレスポンスをReact側で`console.log`するというものです。  
しかし、そこで下記の内容のエラーが発生しました。  
自分なりに色々調べてみましたが、解決せず…。  
このままだと一向に次のフェーズに進めそうにないです…。  
どなたか解決方法のご教授お願い致します。

## エラーの内容

[code]

    Error: upstream connect error or disconnect/reset before headers. reset reason: connection termination
    
[/code]

## 該当のソースコード

[code]

    // client
    
    FROM  node:latest
    
    WORKDIR /HEW2020/client
    COPY . .
    RUN yarn install --ignore-engines --network-timeout 1000000
    CMD ["yarn", "start"]
    EXPOSE 3000
    
[/code]

[code]

    // server
    
    FROM golang:1.12
    
    ENV GO111MODULE=on
    
    WORKDIR /go/src/HEW2020/server
    COPY . .
    RUN go get github.com/pilu/fresh
    CMD ["fresh"]
    EXPOSE 49200 49201
    
[/code]

[code]

    // envoy
    
    FROM  envoyproxy/envoy:v1.12.2
    WORKDIR /HEW2020/proxy
    COPY ./envoy.yaml .
    CMD /usr/local/bin/envoy -c /HEW2020/proxy/envoy.yaml
    EXPOSE 8080
    
[/code]

[code]

    // docker-compose.yml
    
    version: "3"
    
    services:
      proxy:
        build: ./proxy
        volumes:
          - ./proxy:/HEW2020/proxy
        ports:
          - "8080:8080"
        links:
          - "server"
        container_name: "hew2020-proxy"
    
      server:
        build: ./server
        volumes:
          - ./server:/go/src/HEW2020/server
        ports:
          - "49200:49200"
        container_name: "hew2020-server"
    
      client:
        build: ./client
        volumes:
          - ./client:/HEW2020/client
        ports:
          - "3000:3000"
        container_name: "hew2020-client"
    
      db:
        image: mysql:5.7
        restart: always
        volumes:
          - ../mysql/data:/var/lib/mysql
          - ../mysql/conf:/etc/mysql/conf.d
          - ../mysql/initdb.d:/docker-entrypoint-initdb.d
        environment:
          MYSQL_ROOT_PASSWORD: secret
          MYSQL_DATABASE: hew2020
          MYSQL_USER: root
          MYSQL_PASSWORD: secret
          # TZ: 'Asia/Tokyo'
        ports:
          - "13306:3306"
        container_name: hew2020-db
    
[/code]

[code]

    // envoy.yaml
    
    admin:
      access_log_path: /tmp/admin_access.log
      address:
        socket_address: { address: 0.0.0.0, port_value: 9901 }
    
    static_resources:
      listeners:
        - name: listener_0
          address:
            # 全IPの8080PortでListen
            socket_address: { address: 0.0.0.0, port_value: 8080 }
          filter_chains:
            - filters:
                - name: envoy.http_connection_manager
                  config:
                    codec_type: auto
                    stat_prefix: ingress_http
                    route_config:
                      name: local_route
                      virtual_hosts:
                        - name: local_service
                          domains: ["*"]
                          routes:
                            - match: { prefix: "/" }
                              route:
                                cluster: web_app_service
                                max_grpc_timeout: 0s
                          cors:
                            allow_origin:
                              - "*"
                            allow_methods: GET, PUT, DELETE, POST, OPTIONS
                            allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                            max_age: "1728000"
                            expose_headers: custom-header-1,grpc-status,grpc-message
                    http_filters:
                      - name: envoy.grpc_web
                      - name: envoy.cors
                      - name: envoy.router
      clusters:
        - name: web_app_service
          connect_timeout: 0.25s
          type: logical_dns
          http2_protocol_options: {}
          upstream_connection_options:
            tcp_keepalive:
              keepalive_time: 300
          lb_policy: round_robin
          # win/mac hosts: Use address: host.docker.internal instead of address: localhost in the line below
          hosts:
            [
              {
                socket_address:
                  { address: host.docker.internal, port_value: 49200 },
              },
            ]
    
[/code]

[code]

    // Signup.tsx
    
    import { SexTypes } from "../../proto/enums_pb"
    import { SignUpRequest } from "../../proto/messages_pb"
    import { WebAppServiceClient } from "../../proto/web_app_service_pb_service"
    
    const Signup: React.FC = () => {
      const classes = useStyles()
    
      useEffect(() => {
        const req = new SignUpRequest()
        req.setName("MyName")
        req.setSex(SexTypes.SEX_MALE)
        req.setAge(22)
        req.setUserId("abcdefg")
        req.setUserPw("password")
    
        const client = new WebAppServiceClient("http://localhost:8080", {})
        client.signUp(req, (err, res) => {
          if (err || res === null) {
            throw err
          }
          console.log(res.getMessage())
        })
      })
      return (
        <Root>
          <div className={classes.toolbar} />
          <h1>Signup</h1>
          <h1>Signup</h1>
          <h1>Signup</h1>
        </Root>
      )
    }
    
[/code]

[code]

    // web_app_service.proto
    
    web_app_service_proto
    service WebAppService {
        rpc SignUp (messages.SignUpRequest) returns (messages.AuthResponse) {}
    }
    
[/code]

[code]

    // messages.proto
    
    message AuthResponse {
        bool status = 1;
        enums.StatusCodes status_code = 2;
        string token = 3;
    }
    message SignUpRequest {
        string name  = 1;
        enums.SexTypes sex = 2;
        uint32 age = 3;
        string user_id = 4;
        string user_pw = 5;
    }
    
[/code]

## 追記

公式サイト([該当ページ](https://www.envoyproxy.io/learn/backpressure))をチェックしてみたところ下記の様な記述がありました。

[code]

    Two quick definitions, used by Envoy:
    
    Upstream connections are the service Envoy is initiating the connection to.
    Downstream connections are the client that is initiating a request through Envoy.
    
[/code]

[code]

    Upstream Connection Closed
    What it is: When the upstream closes the connection before the response is finished sending, Envoy cannot send a complete response to the downstream.
    
    Result: This depends on whether the downstream has started receiving data.
    
    If it has not (i.e. the upstream disconnects quickly), the downstream connection is reset.
    If it has, the downstream receives an HTTP 503 and the body text “upstream connect error or disconnect/reset before headers”
    
[/code]

これはUpstream（つまりGo）側に問題があるということでしょうか？


CC BY-SA 4.0
2020-01-25T05:19:20.000
62536
2020-01-26T04:31:40.467
2020-01-25T06:14:11.743
32711
32711
question
javascript go reactjs typescript
gRPC+Go+React+TypeScript における Connect error


Go側でエラーが発生していました…。修正したところ無事解決いたしました。  
ありがとうございました！


CC BY-SA 4.0
2020-01-26T04:31:40.467
62556
2020-01-26T04:31:40.467
32711
62536
answer